/** * aigc_report.mjs — AIGC 分镜拉片报告生成器(JSS-03) * 读取 aigc_remake.json + aigc_prompt.md → 产出 aigc_report.html(暗色/手机自适应/相对路径) * 纯 ESM, 零依赖。CLI: node aigc_report.mjs workdir */ import fs from "node:fs"; const esc = (s) => String(s ?? "").replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); const fmtTs = (ms) => { const s = Math.floor(ms / 1000); return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, "0")}`; }; function scoreBars(dims) { return dims.map((d) => `
${esc(d.name)}${d.score}
${esc(d.note)}
`).join(""); } function shotRows(board) { return board.map((s) => { const img = s.file ? `frames/${s.file}` : ""; return `
#${s.i + 1}${esc(s.t_label)} ${s.dur}s${esc(s.role.split("(")[0])}
${img ? `shot ${s.i}` : ""}

画面: ${esc(s.caption)}

${s.lyric ? `

音频: ${esc(s.lyric)}

` : ""} ${s.vision?.char ? `

主体: ${esc(s.vision.char)}

` : ""} ${s.vision?.shot ? `

运镜: ${esc(s.vision.shot)}

` : ""} ${s.vision?.style ? `

风格: ${esc(s.vision.style)}

` : ""} ${s.vision?.aigc ? `

AI痕迹: ${esc(s.vision.aigc)}

` : ""}
`; }).join(""); } export function render(remake, promptMd) { const { video, type, structure, registry, storyboard, score, voc } = remake; const st = video.stats || {}; return ` AIGC分镜拉片:${esc((video.desc || "").split("#")[0].trim())}

🕷️ AIGC 分镜拉片报告

${esc(video.author)} · 原片 · ${fmtTs(video.duration_s * 1000)}
${esc(type.primaryLabel || "AIGC内容")} 置信度 ${type.confidence ?? "?"} 复刻模式: 分镜仿制
${(st.digg_count ?? 0).toLocaleString()}👍 点赞
${(st.comment_count ?? 0).toLocaleString()}💬 评论
${(st.collect_count ?? 0).toLocaleString()}🔖 收藏
${(st.share_count ?? 0).toLocaleString()}↗ 转发
${score.total}综合评分

🧬 复刻资产注册表

人物: ${(registry.characters || []).map(esc).join("、") || "—"}
场景: ${(registry.scenes || []).map(esc).join("、") || "—"}
风格: ${(registry.styles || []).map(esc).join("、") || "—"}
节奏: ${structure.shot_count} 镜 / 平均 ${structure.avg_shot_s}s / ${(structure.shot_count / (video.duration_s / 60)).toFixed(0)} 镜每分钟

🎬 片体结构

${(structure.sections || []).map((s) => ``).join("")}
段落时间类型内容
${esc(s.name)}${s.start}s–${s.end}s${esc(s.type || "")}${esc(s.content || s.lyric || "")}

🎞️ 分镜表(${storyboard.length} 镜)

${shotRows(storyboard)}

📊 六维评分

${scoreBars(score.dims)}

🧾 仿爆款长提示词

完整版: aigc_prompt.md — 直接投喂给 AIGC 创作智能体, 替换占位符即可逐镜复刻
${esc(promptMd)}

💬 评论区 VOC

${(voc?.top || []).map((c) => `
👍${c.likes} ${esc(c.text)}
`).join("") || "—"}
共采集 ${voc?.total || 0} 条

🚀 改进与复刻策略

${(remake.suggestions || []).map((s) => `

▸ ${esc(s)}

`).join("")}
`; } if (import.meta.url === `file://${process.argv[1]}`) { const wd = process.argv[2] || "."; const remake = JSON.parse(fs.readFileSync(`${wd}/aigc_remake.json`, "utf8")); const promptMd = fs.existsSync(`${wd}/aigc_prompt.md`) ? fs.readFileSync(`${wd}/aigc_prompt.md`, "utf8") : "(未生成)"; fs.writeFileSync(`${wd}/aigc_report.html`, render(remake, promptMd)); console.log(`→ ${wd}/aigc_report.html (${(fs.statSync(`${wd}/aigc_report.html`).size / 1024).toFixed(0)} KB)`); }