Homebrew 自带 ffmpeg 缺 libass,默认不烧录字幕只输出外挂 .srt,需装 ffmpeg-full 并调整 PATH。必须自备小米 MiMo API Key,tp-* Token Plan key 还要设 MIMO_TOKEN_PLAN_CLUSTER。仓库已从 worldwonderer 迁到 zenstory-ai,旧地址安装需重新指向新仓库。
video-recap-skills
zenstory-aiMIT活跃维护把长视频自动切成镜头、用多模态模型看画面写解说词、再配音合成成片,还能一键导出可编辑的剪映/CapCut 草稿,全程不用 GPU。
AI 视频解说全流程 skill 包:自动切镜头、看画面写解说词、配音合成成片,支持一键导出可编辑的剪映/CapCut 草稿,无需 GPU | Agent skills that turn videos into narrated recaps & editable CapCut drafts
brew install ffmpeg
export MIMO_API_KEY=your-mimo-key
/plugin marketplace add zenstory-ai/video-recap-skills
/plugin install video-recap-skills@video-recap无需 GPU,本地只需 Python 3.10+ 和 ffmpeg;ASR、VLM、TTS 均走小米 MiMo 云端 API,不下载模型。烧录字幕需带 libass 的 ffmpeg,画面文字叠加需带 drawtext。
把视频自动做成中文解说成片的 Agent 技能包,还能导出可编辑的剪映草稿
把长视频自动切成镜头、用多模态模型看画面写解说词、再配音合成成片,还能一键导出可编辑的剪映/CapCut 草稿,全程不用 GPU。
核心能力
- 七个技能串联理解、写稿、配音、组装全流程
- 用 ASR 加 VLM 分析画面与对白,生成创作 brief
- 先剪后配,按成片时间轴写解说,保证音画对齐
- 多轨 timeline.json 一键导出剪映/CapCut 草稿
- 旁白 lint 与组装 QC 生成机器可读报告
容易踩的坑
- v0.6.2v0.6.2 — 外发与配音授权最新正式版2026-10-04 · 2026-10-04 06:42 UTC
用 dub 模式的命令(包括旧
work_dir打印的续跑命令)都要补上--confirm-voice-rights,否则在外发任何音频之前报错退出。补丁号不代表可以直接升级:本版收紧了 dub 的运行条件,并写明 video-script / video-voiceover 每条远程调用发什么、发给谁、怎样关闭。主要变化
- dub 需要显式确认声音权利。dub 会把源音轨发给 MiMo ASR、用原说话人的声音做 voiceclone;只在有权使用该视频、且说话人同意被克隆时传
--confirm-voice-rights。 - 远程调用逐条写明。video-script 只有建议型评审
review.py联网(只发文字,可用--no-review-narration关闭);video-voiceover 逐路径列出 MiMo / Fish Audio / 自托管 IndexTTS / dub 各自收到的内容。 - 没有
MIMO_API_KEY时评审不再发出稿件,在构造请求前退出。
升级提示
- 在所有
--edit-mode dub命令和直接调用dub.py --stage prepare|render的地方加--confirm-voice-rights;其他模式传这个参数会报错。
/plugin marketplace add zenstory-ai/video-recap-skills /plugin install video-recap-skills@video-recap完整变更见 CHANGELOG。
- dub 需要显式确认声音权利。dub 会把源音轨发给 MiMo ASR、用原说话人的声音做 voiceclone;只在有权使用该视频、且说话人同意被克隆时传
- v0.6.1v0.6.1 — 契约收紧与瘦身2026-10-03 · 2026-10-03 14:24 UTC
查看更新说明
升级前先从脚本和环境里删掉本版移除的参数与环境变量,读 QC 产物的脚本按升级提示改;full 模式超预算的解说稿现在 lint 失败,要改稿后重跑。虽是补丁号,本版改了契约:校验与导出不再静默改写或兼容旧形状,而是报错并写明改法。
主要变化
- full 模式校验只做 lint。不再截短、丢段、合并或重排解说稿,超预算段报
over_budget。 - 成片交付更稳(dub 模式除外)。H.264 8-bit 4:2:0 并带色彩标记,剪辑接点不丢帧,交付文件真峰值不超过 -1 dBTP,仍超标时以
delivered_true_peak_over_target阻断;缺 libass 时改交付外挂.srt,不再开跑前退出。 - TTS 段缓存按内容寻址。删一段旁白不再让后面所有段重新计费;幻读音频按失败重试(见升级提示)。
- 新增按需技能 video-reference。把成片拆成可复用的制作参考,不进默认生产路径。
升级提示
- 删掉
--mimo-qc、validate.py --preserve-approved-text、cut.py --clip-padding、dashboard_server.py --host等参数,以及 19 个调参环境变量和MIMO_QC*、CLIP_PADDING、SOURCE_VIDEO;读golden_eval.json的脚本改读final_qc.json,已读final_qc.json的按 schema 2 改读 finding(只剩 code/message/blocking/evidence/next_action);mimo_qc.json已删除且无替代,preflight_qc.json的内容直接读tts_meta.json/assembly_manifest.json/ cut QC。 - 默认开启的
TTS_MIN_SPEECH_RATE(2.5 字/秒)会让慢速旁白或慢速克隆声线重试后失败,可调低或设为0;--sources-manifest的别名形状、剪映 v1 时间线、改过名的素材目录等旧输入按报错提示改正(含未排序的解说段);报错与 brief 里的段号、场景号、块号改从 1 数;旧 work_dir 续跑会重剪、重新合成 TTS、重建故事索引各一次,缺 ASR 时间证据的还会重跑 ASR。
/plugin marketplace add zenstory-ai/video-recap-skills /plugin install video-recap-skills@video-recap完整变更见 CHANGELOG。
- full 模式校验只做 lint。不再截短、丢段、合并或重排解说稿,超预算段报
- v0.6.0v0.6.0 — 资源库与模板 · 只读剪辑台 · 架构梳理2026-09-28 · 2026-09-28 02:44 UTC
查看更新说明
三条主线:资源库与模板(登记与校验、项目绑定、每次运行的资源记录、字体文件、静态包装图层);只读的本机剪辑台 dashboard;以及 skill 层分包、去内容哈希、测试审计后的架构梳理。完整条目见 CHANGELOG。
资源库与模板
同一个系列要反复用同一首 BGM、同一套字幕样式、同一个包框和音色。以前它们散在环境变量和单次 work_dir 里,现在可以登记、采用、绑定,并在每条成片旁边留下记录。
- 登记与校验。 素材库根目录下新增
resources/(BGM、音效、音色、字体、图片)、templates/(字幕样式、包装图层,带版本)和samples/(样片)。library.py check|list|show只读校验,覆盖授权、声音授权、路径越界、引用完整性,以及"每行字数 × 字号放不放得进画布"。- 授权与"已采用"状态只由人填写,工具不会推断。
- 仓库只带合成示例库,不内置任何真实素材。
- 项目绑定
--project recap_project.json。 已采用的字幕样式模板、音色和 BGM 会转成各阶段已有的设置。以下情况都在配音之前停下:显式设置冲突、模板未采用、声音授权为 denied、模板画布与成片不符。 - 字体文件。
SUBTITLE_FONT_FILE让烧录字幕和画面文字都用指定的字体文件,不再依赖渲染机装了哪些字体。 - 静态包装图层。 包框、标题条、角标按画布坐标叠到成片上,叠在遮原字幕之后、字幕之前。
timeline.json同步写出位置一致的 image 轨,可以在剪映里继续编辑。 resource_lock.json。 每次 full / cut 合成后记下这次实际用了哪些原片、音色、BGM、字体、包装图层,以及它们的授权状态;需要人确认的项会在运行结束时打印出来。
只读剪辑台
python3 skills/video-recap/scripts/dashboard_server.py --root <目录>:纯标准库的本机服务,用 ZenStory 设计语言(与兄弟项目共用tokens.css)。- 视图。 按阶段分视图:理解、剪辑节奏条、旁白、成片播放器加四轨时间线、QC、资源;资源库和模板带画布示意;支持 ⌘K 搜索和明暗切换。
- 严格只读。 只接受 GET / HEAD,只绑定回环地址,校验 Host / Origin /
Sec-Fetch-Site。路径不出根目录,也不读符号链接和非普通文件。需要动手的地方只给一句可以复制回对话的话。
架构梳理
- 编排器共用收尾。 单视频和多视频流程共用同一段收尾;SKILL.md 新增
--edit-mode × --audio-mode路径表;新增docs/architecture.md。 - 测试审计。 补上两个真实的覆盖漏洞:dub 克隆缓存复用过期音频时没有测试会失败;去标点字数统计没有测试守护。删掉只给测试用的再导出、注入参数和永远走不到的分支,生产代码净减约 100 行、测试净减约 570 行。
行为变化(可能影响旧用法)
- 入口模块不再再导出内部函数,例如
mimo_qc.build_report、cut.load_clip_plan、brief.lint_narration、assemble.final_loudnorm_filter。进程内 import 这些名字的脚本,请改为从所属模块导入。 recap_inspect --json不再输出恒为空的forward_state_files。tts_meta.json新增voice字段,已有字段不变。
验证
- 全量测试:understanding 183、voiceover 127、script 117、orchestrator 433、inspect 23 全绿。cut 1 个、assemble 6 个失败与 main 基线相同,都是依赖本机 ffmpeg 版本的环境性失败。
ruff无告警。CI 在 ubuntu / macOS / Windows 三个平台通过。 - 真实端到端。 用一段合成的 900x1600 测试片,调用真实 MiMo ASR / VLM / 评审 / TTS,绑定示例项目,完成理解、写稿、配音、合成和剪映导出。这次运行抓到并修复了两个问题:字幕模板缺少每行字数校准;续跑命令里用了相对路径。
- 两轮对抗式审查。 资源库与项目绑定修复 3 个高、4 个中严重度问题;剪辑台修复 HTML 注入、符号链接与 FIFO 读取、跨站探测等 4 个问题和 1 个加固点。
- 登记与校验。 素材库根目录下新增
- v0.5.0v0.5.0 — Fish Audio TTS · 在边界校验一次 · 三处真实缺陷修复2026-09-05 · 2026-09-05 02:34 UTC
查看更新说明
两条主线:新增 Fish Audio TTS 通道与《锅火》60 秒案例,以及一次以「在边界校验一次,之后信任契约」为原则的全量瘦身。完整条目见 CHANGELOG。
新增
- TTS 可切换到 Fish Audio。
--tts-provider fish-audio(或TTS_PROVIDER=fish-audio)搭配FISH_API_KEY即可使用;默认走s2.1-pro-free与内置「娱乐扒妹」解说音色,FISH_TTS_REFERENCE_ID可覆盖。MiMo 仍是默认路径,不受影响。该免费模型无 SLA、受 Fair Use Policy 约束,官方公示的免费开放期至 2026-08-31。 - 《锅火》60 秒案例。
examples/guohuo-60s/收录一次完整创作的产物:核心 cut、音画锁定、包装探索、看片反馈、局部 conform / 再剪与冻结项复核,覆盖多集选段、原声与旁白分工、Fish Audio 配音与 TTS 对齐字幕。仓库不含原剧音视频二进制。
在边界校验一次,之后信任契约
各 skill 内部大量
.get(key, default)、isinstance(...)兜底与try/except被删除。理由很直接:一个 skill 包同时拥有自己产物的写入端和读取端,每次读取都重新校验一遍,只会掩盖当初写错它的那个 bug。校验因此收敛到真正的输入边界——
narration_lint.py负责 Agent 手写的narration.json,jianying_timeline_contract.py负责导出的剪映时间线,env_*负责环境变量。流水线自己写出的产物(tts_meta.json、timeline.json、clip_plan_validated.json、各 QC 报告)此后按字段直接读取。行为收紧(可能拒绝旧输入)
- 剪映资源契约收敛为规范 snake_case 对象。
resources条目必须是带source_path的对象,main_config必须是对象,不再接受 Jackson 的mainConfig/resourceId/coverImg别名,也不再按.cube/.ttf后缀推断resource_kind。外部输入请在调用前完成适配。 - 配置解析失败即报错。 无法解析的环境变量不再静默回退默认值;
MIMO_TOKEN_PLAN_CLUSTER取值非法时报错。 - 探测失败即报错。
ffprobe读不出时长或视频流时抛错,不再退回0.0或1280x720默认画布——错误的画布会静默产出错位的字幕几何,比直接失败更难查。 - 仓库迁移到
zenstory-ai。 按旧地址安装的用户需要重新指向zenstory-ai/video-recap-skills。
审查中发现并修复的三处真实缺陷
visual_overlays此前没有任何校验器覆盖。 缺type/text的 overlay 能干净地通过 lint,却让 recap 编排器在 TTS 跑完之后才以KeyError崩溃——白白付掉一整轮合成开销。校验前移到 TTS 之前。- 静音 TTS 块会中断整次配音。 零帧 WAV 触发除以零样本数的
ZeroDivisionError;现在原样透传并返回中性响度元数据。 - 没有 ffmpeg 的机器上交付 QC 崩溃。
_probe_audio_sample_rate是观测性质的 delivery QC,且会在尚未渲染的计划上运行,因此「ffprobe 不存在」与「报告不出采样率」按同一种结果处理。渲染路径上的探测仍照常抛错。
安全
default_mimo_api_url改为接收is_token_plan布尔值,由调用方先归类。它的返回值会被doctor.py打印,凭证本身不应流入;解析出的 URL 行为不变。skill-validate.yml补上最小权限permissions:声明。
验证
999 tests 全绿,并在「有 ffmpeg」与「无 ffmpeg」两种环境各跑一次;
ruffclean;validate在 ubuntu / macOS / Windows 三平台通过。 - TTS 可切换到 Fish Audio。
- v0.4.0v0.4.0 — 多源剪辑与 QC · 可携带剪映草稿 · 内容驱动创作流程 · 深度审查修复2026-07-26 · 2026-07-26 16:29 UTC
查看更新说明
汇总
v0.3.3之后的全部工作。完整条目见 CHANGELOG。新增
- 贴合原片字幕带。
tools/measure_subtitle.py抽帧检测原片字幕区并输出红框预览;--subtitle-y-top/--subtitle-y-bot把新字幕基线与字号适配到测得坐标。 - 半透明、解说时段遮罩。 默认
SUBTITLE_MASK_OPACITY=0.6+SOURCE_SUBTITLE_MASK_TIMING=narration,原声留白不再常驻黑条。 - 参考音色解说。 recap / voiceover 新增
--voice-ref,通过mimo-v2.5-tts-voiceclone克隆音色。 - 建议性 MiMo QC。
--mimo-qc pre-assemble|post-render|both,观察聚合进mimo_qc.json,全程不阻断交付。 - 可携带剪映草稿。 素材默认打包进
Resources/local;timeline v2 支持变速、倒放、transform、富文本、转场/mask/LUT、绿幕复合。
内容驱动的创作流程
Agent 在剪辑或写稿前先比较剪辑假设,记录 POV、戏剧问题、change-based beats、
audio_owner与narration_job。旁白比例改由素材决定,7:3降级为粗略回退而非配额。本轮深度审查修复的正确性问题
- 画面锚点整体偏移 1/fps 秒。 ffmpeg 的
fps滤镜首帧在源时间 0,而文件编号从 1 起——frame_00001.jpg是t=0,第 n 帧是(n-1)/fps。此前按n/fps计算,把frame_facts、场景归属与 storyboard 标签整体推后 1/fps 秒(>5min 视频默认 fps=1,即整整一秒)。这些时间戳会作为权威画面锚点交给写稿 Agent。 - 带封面图的素材渲染直接失败。 组装映射
0:v会匹配到 attached_pic 那一路视频流,ffmpeg 报Could not write header并留下损坏文件——发生在整条流程的最后一步。 --clip-padding非零时相邻片段被误判为重复素材,任意两个背靠背片段都会硬失败。CLIP_PADDING环境变量此前完全无效。
性能
file_fingerprint按进程记忆化:一次理解流程原本要对源视频做 8–10 次全量 sha256、对整套抽帧做 2–3 遍(40 分钟视频约 2400 张全分辨率 JPEG)。另有 VLM 逐帧 base64 缓存改 LRU、续传缓存批量落盘、TTS 响度归一单遍化、缓存命中不再 ffprobe、黑白帧过滤并行。配置面
每个配置旋钮只声明在读它的技能里,删除 583 条无效声明;新增不变量「任何技能不得声明自身从不读取的配置」。
升级提示
帧时间修复会提升帧/VLM 缓存版本,已有 work_dir 会重跑 VLM 分析(旧结果里烧进了偏移的时间戳)。ASR 与场景检测缓存不受影响,最耗时的转写结果得以保留。
环境要求
ffmpeg(烧录字幕需带 libass)+ 一个小米 MiMo API key。macOS / Linux / Windows。
- 贴合原片字幕带。
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
上面这条 59 秒横屏解说《这一秒过火》,是从四集短剧里选段、剪辑、写稿、配音、混音、包装并经多轮看片修改后的最终交付; 它的全部创作产物(故事计划、声音分工、旁白、时间线、QC 报告、看片修改记录、Remotion 包装源码)都在 examples/guohuo-60s/,下文的节选全部来自这些文件。
这是什么
七个技能(六个生产 + 一个按需参考)装进 Claude Code、Codex CLI、OpenCode 或 OpenClaw,你用自然语言给出视频路径和想要的成片,Agent 负责理解画面与对白、
决定故事与视听方案、剪辑、写稿、配音、混音和字幕。支持 .mp4 / .mov / .mkv / .webm。
- 一个 key,本地只要 ffmpeg。 ASR、VLM、TTS 都走小米 MiMo,本地只用 Python 标准库和
ffmpeg,不需要 GPU,不需要pip install,也不下载模型。配音可以换成 Fish Audio,只替换配音这一段。 - 先做创作决定,再分配声音。 首次策划时,Agent 比较可行的剪辑方向;已有指定结构或看片反馈时,按当前决定修订。观众承诺、POV、戏剧问题和每拍变化写进
recap_story_plan.json,再给每一拍指定画面任务和声音归属:旁白只在有明确任务时整块配音,强对白、动作声或沉默可以完整主导一拍。 - 先剪后配,时间轴天然对齐。 剪辑模式先把长视频剪成成片,再对着成片写解说;一次可以传多个视频,按
source_id选段剪成一条主线;视频分析可按需保存到文件系统素材库,后续在来源和设置匹配时复用。 - 成片之外还能继续改。 多轨时间线
timeline.json可一键导出剪映草稿,原片、解说、BGM、字幕、图片叠层都可编辑;自带一份准确字幕文件就会被当作原声字幕的首选来源。 - 每一步都留下可核对的记录。 旁白 lint、组装 QC 与最终 QC 会生成机器可读报告;看片修改可另记录本轮改动、冻结项与验证结果。
安装
ClawHub
ClawHub 条目与依赖由 显式发布清单 管理。编排器 video-recap 当前仍因同根安装验证未完成而标为 blocked;使用完整流程请按下方方式安装整套插件或源码。
前提:Python 3.10 或更新版本,PATH 上有 ffmpeg,以及一个小米 MiMo API Key。默认把字幕烧录进画面,这需要带 libass 的 ffmpeg;Homebrew 自带的 ffmpeg 没有 libass,这时默认运行不烧录,在成片旁输出同名 .srt 外挂字幕并在 final_qc.json 里记一条警告(显式传 --burn-subtitles 则在开跑前报错)。旁白里写了画面文字叠加(visual_overlays)时还需要带 drawtext 的 ffmpeg,缺了会在配音前报错。要在 macOS 上烧录字幕,可用 brew install ffmpeg-full(keg-only,需把它的 bin 放到 PATH 前面)。
brew install ffmpeg # macOS;Debian/Ubuntu 用 apt,Windows 用 choco / scoop / winget
export MIMO_API_KEY=your-mimo-key # Windows PowerShell:$env:MIMO_API_KEY="your-mimo-key"
export MIMO_TOKEN_PLAN_CLUSTER=cn # 仅 tp-* Token Plan key 需要:cn | sgp | ams
MiMo 不需要订阅,sk-* key 按量付费;本项目实测一条完整视频约 1.3 元,费用随视频时长和调用量变化。
在 Claude Code 里执行:
/plugin marketplace add zenstory-ai/video-recap-skills
/plugin install video-recap-skills@video-recap
也可以直接说一句话(支持导入 GitHub 仓库的 Agent 都适用):
安装这个插件:https://github.com/zenstory-ai/video-recap-skills
Codex CLI
codex plugin marketplace add zenstory-ai/video-recap-skills
codex plugin add video-recap-skills@video-recap
OpenCode:按官方 Agent Skills 文档,项目级技能放在 .opencode/skills/<name>/SKILL.md。克隆仓库后从仓库目录启动:
git clone https://github.com/zenstory-ai/video-recap-skills.git
cd video-recap-skills
mkdir -p .opencode
ln -s ../skills .opencode/skills # Windows 把 skills\* 复制到 .opencode\skills\
opencode debug skill # 应列出全部 7 个技能
OpenClaw:克隆后导入 Claude 插件包:
openclaw plugins install ./video-recap-skills
openclaw skills list
同一份技能只注册到一个发现目录,否则会重名或重复触发。
export TTS_PROVIDER=fish-audio
export FISH_API_KEY=your-fish-key
export FISH_TTS_REFERENCE_ID=your-voice-model-id # 可选;默认内置"娱乐扒妹"解说音色
默认模型 s2.1-pro-free,默认音色"娱乐扒妹"(reference ID 5653cea4ac83480aaf2bf45406556185),计费以 Fish Audio 官方为准。ASR 和 VLM 仍走 MiMo;本地参考音频克隆(--voice-ref)只在 MiMo 路径可用。
装好后让 Agent 自检一次:
检查 video-recap 的运行环境,告诉我 Python、ffmpeg/libass 和 MiMo 配置是否就绪。
变更见 CHANGELOG.md 与 Releases。仓库已从
worldwonderer/video-recap-skills迁到zenstory-ai/video-recap-skills,按旧地址安装的用户请重新指向新仓库。
看看它的输出
下面每一段都摘自 examples/guohuo-60s/ 里的真实文件,省略处用"…"标出。案例的输入是《这一秒过火》第 2、3、6、21 集,仓库只收录结构化产物,不含原剧音视频。
故事计划先写清"观众承诺",再写每一拍的变化
Agent 在剪任何一刀之前先写 recap_story_plan.json。导演意图是四个问题的答案:承诺什么、跟谁的视角、观众带着什么问题看、什么信息留到最后:
"director_intent": {
"viewer_promise": "60秒看懂死而复生的白月光为什么让男主一秒破防,并用三个名场面把关系推到婚服送嫁。",
"pov": "跟随慕容清峄的认知与反应,让观众和他一起从震惊、发疯走到确认她仍会护他。",
"dramatic_question": "她既然装作陌生人,为什么眼神、亲吻和保护都在暴露旧情?",
"emotional_start": "荒诞吃瓜式震惊",
"emotional_end": "抓马又上头的未完待续",
"ending_aftertaste": "明明相爱却要嫁给哥哥的强悬念",
"withhold_reveal": "前8秒先揭示准大嫂身份;中段以洗手台和护夫逐步证明旧情;最后才亮婚服。"
},
每个 beat 直接记录"发生了什么变化"、观众进场与离场时分别带着什么问题,以及必须保住的具体时刻和证据来源(10 拍节选 1 拍):
{
"beat_id": "b03",
"source_id": "episode-03",
"source_start": 1292.0,
"source_end": 1305.5,
"function": "escalation",
"event": "男主堵住女主说出日日夜夜想她与挫骨扬灰",
"change": "power: 女主回避→男主逼问",
"audience_question_in": "男主会忍吗",
"audience_question_out": "狠话里全是想念",
"character_focus": "慕容清峄",
"must_keep_moment": "完整原声“我日日夜夜地想你…挫骨扬灰”",
"evidence": ["asr", "vlm", "hard_subtitle"]
},
这一拍在 clip_plan.json 里变成一条带理由的选段,剪辑模式据此先剪出成片,再写旁白。
旁白让位给原声:谁主导这一拍是写在文件里的
visual_audio_board.json 给每一拍指定 audio_owner。上面那一拍由原声主导,旁白任务是 none,播放速度锁定 1.0(10 拍节选 1 拍):
{
"beat_id": "b03",
"source_id": "episode-03",
"source_start": 1292.0,
"source_end": 1305.24,
"output_start": 9.206666,
"output_end": 22.446666,
"picture_job": "performance",
"preferred_moment": "完整原声“我日日夜夜地想你…挫骨扬灰”",
"entry_reason": "尽量晚进到信息/动作将发生前",
"exit_reason": "台词、动作或反应完整落地后立即离开",
"audio_owner": "original_dialogue",
"original_audio_anchor": "完整原声“我日日夜夜地想你…挫骨扬灰”",
"narration_job": "none",
"handoff": "旁白先补关系,原声/动作发生时完全让位;下一拍承接人物反应。",
"playback_speed": 1.0
},
于是 narration.json 全片只有 7 个旁白块,第二块在 10.2 秒停下,第三块到 23.047 秒才进来,中间 13 秒完整留给那句原声:
{
"start": 5.773,
"end": 10.2,
"narration": "她改名方牧兰,嘴上装作不认识,一个眼神就把三年前的旧情全招了。",
"pause_after_ms": 80,
"overlaps_speech": true,
"emotion": "调侃"
},
{
"start": 23.047,
"end": 26.5,
"narration": "天呐,狠话还没落地,下一秒两个人直接亲上了。",
"pause_after_ms": 50,
"overlaps_speech": true,
"emotion": "吃瓜、上头"
},
三段被保护的原声由 Agent 校对后写进 original_subtitles.json,在留白处烧成「」字幕:
[
{ "start": 4.133, "end": 5.053, "text": "大嫂。" },
{ "start": 11.127, "end": 21.027, "text": "我好想你,日日夜夜地想你,想把你抽筋扒皮,挫骨扬灰。" },
{ "start": 35.673, "end": 37.473, "text": "有我在,你别怕。" }
]
组装时 timeline.json 的原声轨在每个旁白块处自动压低、块后恢复;这份时间线就是剪映草稿导出的来源。
看片之后怎么改,改了什么、冻结了什么,都有账
案例经历了四轮修改,每轮在 revision-log.json 里写成三项:改什么、冻结什么、怎么验证。最后一轮只解冻画面:
{
"baseline": "final_picture_conform",
"scope": "picture_conform",
"change_set": [
"remove the visible tail-frame pause near 42.08 seconds",
"restore continuous source movement around 46.24 seconds"
],
"frozen_set": [
"story and narration",
"all audio",
"caption timing and typography",
"title and accent graphics"
],
"verification": [
"normal-speed full watch",
"join playback around both change points",
"freeze detection as supporting evidence",
"audio stream-copy verification",
"full decode"
]
}
edit-map.json 记下 46 秒那处跳接的修复方式:直接补回原片被删掉的 2001–2004 秒同段连续运动,不靠溶解或闪白遮掩:
{
"name": "wedding_corridor_continuous_motion",
"beat_ids": ["b07", "b08"],
"output_frames": [1052, 1288],
"output_seconds": [42.08, 51.52],
"asset_id": "episode-21",
"source_seconds": [1996.0, 2010.32],
"speed": 1.516949153,
"repair": "Restored the omitted 2001-2004 source interval instead of hiding the jump with a transition."
},
交付前的机械检查写在 assembly_qc.json(响度、逐段旁白完整性、verdict / blocking_codes)和 delivery-qc.json:
"checks": {
"full_decode": true,
"audio_stream_matches_master": true,
"vmaf_mean": 93.844938,
"ssim_all": 0.989302,
"psnr_average_db": 45.415972
}
旁白里每一句话的事实依据则在 content-qc.md 逐条对照素材证据和公开资料,并把口语化表达的解释边界写明(9 行节选 1 行):
| “这一下伪装露馅,男主全懂了” | 挡击动作和“有我在”原声连续证明她仍在意男主 | [爱奇艺官方角色片花](https://www.iqiyi.com/v_r8e40v8g54.html)确认二人重逢后身份错位、爱恨拉扯 | **解释成立,但需限定语义**:“全懂”指看懂她仍在意他,不指此刻才第一次认出她是任素素 |
接着在剪映里改
加一句"导出剪映草稿",timeline.json 就会写成可编辑的多轨草稿:原片、逐段解说、BGM、字幕和图片叠层各占一轨,素材默认打包进 Resources/local,草稿搬到别的机器仍能打开。ffmpeg 渲染的 recap_<名>.mp4 是最终成片,草稿是给你继续改的。
导出内容与边界见剪映草稿导出与成本。
安装后的第一条请求
复制、改一改就能用。直接给视频路径、期望成片和必要背景,不需要手动运行仓库里的 Python 脚本。
完整视频解说:
给 /path/to/video.mp4 做一个中文解说成片。这是《庆余年》第一集,主角是范闲,字幕烧进画面。
长视频或多集剪成一条短解说:
用 /path/to/ep1.mp4 和 /path/to/ep2.mp4 做一个十分钟解说,围绕同一条主线剪辑,保留关键原声和人物反应,不要分成两个小总结。
先只做文本交接,不配音不渲染(把〈占位内容〉换成自己的信息):
我有权使用〈本地视频〉,并提供了对应的已核对画面与对白记录。先只给这段素材的声音分工建议:哪句对白、哪个动作声或停顿应完整保留,哪里确需旁白,依据是哪条记录。缺证据就列待核对项,不补人物动机或没出现的事件。交付分拍说明和必要的旁白草案,不调用配音或渲染。
完整制作请求由 Agent 完成理解、故事与视听规划、剪辑、写稿、配音和合成;只做文字交接的请求按指定范围停止。剪辑模式内部会先确定保留片段、生成剪后成片,再按输出时间轴写旁白;这些暂停和续跑也由 Agent 处理。
流程与七个技能
flowchart LR
video(["视频"]) --> understand["① 理解<br/>场景 · ASR · VLM"]
research["背景调研 · 可选"] -.-> understand
understand --> script["② 导演 · 剪辑 · 写稿<br/>Agent"] --> voiceover["③ 配音<br/>MiMo / Fish Audio"] --> assemble["④ 组装<br/>混音 · 字幕"] --> output(["Recap"])
understand -. 剪辑模式 · 先剪后配 .-> cut["剪辑<br/>先剪成片"] -.-> script
classDef io fill:#4f86c6,stroke:#3a6298,color:#fff;
classDef stage fill:#eef6ff,stroke:#4f86c6,color:#1f2937;
classDef opt fill:#f3f4f6,stroke:#9ca3af,color:#475569;
class video,output io;
class understand,script,voiceover,assemble stage;
class research,cut opt;
七个技能(六个生产 + 一个按需参考)通过 work_dir 里的 JSON / MP4 产物衔接:
| 技能 | 职责 | 输入 → 输出 |
|---|---|---|
video-recap | 编排器与环境自检;日常端到端制作用它 | 视频 → recap_<名>.mp4 |
video-understanding | 场景检测 · 抽帧 · ASR(mimo-v2.5-asr)· VLM(mimo-v2.5)· 时间轴融合 · 生成创作 brief | 视频 → scenes / asr_result / vlm_analysis / silence_periods / timeline_fusion / agent_narration_brief.md |
video-script | 导演 / 故事 / 画面 / 声音方案,解说写作,建议型评审与 lint;只做策划或写稿时单独调用 | brief + 索引 → recap_story_plan.json + visual_audio_board.json + [clip_plan.json] + narration.json |
video-cut | 片段计划 → 拼剪成片;剪辑模式先剪后配,解说按成片时间轴写 | clip_plan.json + 视频 → edited_source.mp4 |
video-voiceover | 合成解说音频(MiMo mimo-v2.5-tts / Fish Audio s2.1-pro-free) | narration.json → tts_segments/ + tts_meta.json |
video-assemble | 混音 · 压低原声 · 渲染字幕 · 多轨时间线 · 可选导出剪映 | 视频 + tts_meta → recap_<名>.mp4 + subtitles.srt/.ass + timeline.json |
video-reference | 按需拆片,不在生产路径上:把一部成片拆成可复用的制作参考(结构、节奏、镜头、旁白字幕、音画分工),原片事实只留本地,导出物只含方法与数值 | 成片 + 理解产物 → production_reference.json |
成片固定输出为 recap_<名>.mp4,同时产出 subtitles.srt/.ass;全部中间产物在 work_dir/,字段契约见数据结构。
进阶请求
复用已分析过的素材:
分析 /path/to/ep1.mp4,并把可复用的理解产物保存到 /path/to/.video-materials;后续制作时优先复用这个素材库。
素材库只保存 JSON / Markdown 和索引,不复制原始媒体、不建数据库、不做 embedding;Agent 直接在文件系统里 grep。
导出剪映草稿:
给 /path/to/video.mp4 做解说,并导出可继续编辑的剪映草稿。
让解说字幕贴合原片硬字幕的位置:
先检测 /path/to/video.mp4 的原片字幕区域并让我确认预览,再把解说字幕贴到同一区域生成成片。
检测预览保存在 .subtitle_measure/;当前要求方形或近方形像素视频(SAR 与 1:1 相差不超过 2%)和底部对齐字幕。
用有授权的参考音色配音:
用 /path/to/voice-ref.wav 的音色给 /path/to/video.mp4 做解说;我已获得音色所有者授权。
参考音频会发送给 MiMo 用于合成,只在获得音色所有者授权时使用。
英语视频译成中文并保留原说话人的声音:
把 /path/to/english.mp4 翻译成中文配音,保留原说话人的声音。我有权使用这段视频,说话人同意克隆其声音。
这是实验功能,直接替换原始台词,不叠加解说;当前支持单说话人整轨替换,不分离背景音乐。源视频音频会发给 MiMo ASR 转写,原说话人约 10 秒的声音会作为参考发给 MiMo 克隆音色,所以运行需要 --confirm-voice-rights:只在你有权使用该视频、且说话人同意被克隆声音时确认。
同一个系列复用字幕样式、音色、BGM 与包框:
把 /path/to/library 当作资源库:登记这首 BGM、这个字体和这张包框图,按竖屏 1080x1920 做一版字幕样式模板让我确认采用;
之后这个系列都用 /path/to/series/recap_project.json 绑定它们来出片。
资源、模板和样片是你自己目录里的 JSON 记录,授权与"已采用"状态只由你确认;绑定与显式设置冲突、模板画布与成片不符时,会在配音之前停下。
每次运行的 work_dir/resource_lock.json 记下这次实际用了哪些资源、授权是否清楚。格式见 资源库、模板与样片。
在浏览器里看项目、运行和资源库(只读):
在本机打开剪辑台,看看 /path/to/projects 下面的运行进度、成片和资源库。
剪辑台只读、只监听本机地址;需要改动的地方给你一句可以复制回对话的话,不会从页面上发起任何生产。
自带原声字幕,让留白处的「」字幕更准: 把 user_subtitles.json([{"start": 秒, "end": 秒, "text": "台词"}],按成片时间轴;包一层 {"timeline": "source", "lines": [...]} 则按原片时间轴自动映射)或 user_subtitles.srt / .ass(按原片时间轴)放进 work_dir。优先级:你的字幕文件 › Agent 校对的 original_subtitles.json › ASR 兜底。
常见问题
视频本来没有旁白、甚至没有对白,能给它加上新旁白吗?
可以。理解阶段靠 VLM 看画面,不要求原视频有旁白;素材连对白也没有时,让 Agent 跳过 ASR(--skip-asr),按画面生成解说。这是 issue #79 问过的问题。
长视频跑到一半报 429 或中断了,要从头再来吗?
VLM 会保存已完成的场景;遇到疑似限流会降低并发重试一轮,仍失败时保留错误供处理。解决原因后重复同一条命令,可以复用匹配的场景缓存并继续。写好 narration.json 后也用原命令续跑;剪辑模式用 recap_phase.json 绑定写稿时的计划,改了计划需重新核对或重写解说。续跑只接受同一源视频、同一组参数的工作目录。
VLM 认不出谁是谁,解说里全是"黑衣男子"?
片名或剧情明确时,先让 Agent 做背景调研写进 background_research.json,人物名和关系会折入 VLM 上下文;见背景调研指南。
延伸阅读
- 视频到解说完整流程 — 先确认画面、对白与已提供背景,不把猜测写成片中事实
- 原声与旁白分工 — 先定每拍声音任务,再写解说词
- 剪映 / CapCut 草稿导出 — 用真实
timeline.json独立导出 - 影视解说文案怎么写 — 仓库内文档:先定观众问题,再分配画面、原声与旁白
- AI 分析视频乱编剧情怎么办 — 仓库内文档:把观察、解释和未知分开
- 剪映草稿导出与成本 — 仓库内文档:草稿里有什么、自建与 SaaS 的账单差别
- 开源 AI 影视解说工具怎么选 — 仓库内文档:8 个项目按使用方式、许可证、剪映导出与模型来源对比(含利益相关说明)
- 仓库架构 — 仓库内文档:技能分工、功能子包、编排路径与复制模块清单
- 能力边界与验收原则 — 仓库内文档:哪些交付规则进通用库、哪些属于单个项目;三类验收不能互相冒充
- 《这一秒过火》案例复现 runbook · 从内容锁定到最终版的决策链
- 各技能契约:每个
skills/<skill>/SKILL.md;数据结构 · 配置手册 · 多轨时间线 / 剪映导出 · 创作剪辑手册
致谢
- LINUX DO - The New Ideal Community — 社区支持
- 剪映草稿协议参考 pyJianYingDraft、capcut-mate 和 duo-video
- 字幕带检测适配自 ops120/video-recap-skills-plus
许可
MIT,见 LICENSE。
ZenStory AI 项目
本项目由 ZenStory AI 维护——一套开源的 Agent 故事创作、改编与生产工具(GitHub 组织:zenstory-ai)。同组织项目:
| 项目 | 用途 |
|---|---|
| oh-story-claudecode | 网文写作 skill 包:扫榜、拆文、写作、去AI味、封面图 |
| drama-skills | AI 短剧 / 漫剧创作 skill 合集:剧本、资产、分镜、图片/视频提示词、独立审查 |
| novel-to-game | 小说改编游戏 skill 合集:原著拆解、目标运行环境构建与实机运行验收 |
| video-recap-skills | 将支持的视频文件制作成中文解说,可选导出可编辑的剪映/CapCut 草稿(本仓库) |
| oh-story-dsh | DeepSeek Harness 社区插件,提供小说、短剧、游戏和视频解说工作台 |
| zenstory | 对话即创作的 AI 小说写作工作台(app.zenstory.ai) |