video-recap-skills

zenstory-aiMIT活跃维护

把长视频自动切成镜头、用多模态模型看画面写解说词、再配音合成成片,还能一键导出可编辑的剪映/CapCut 草稿,全程不用 GPU。

AI 视频解说全流程 skill 包:自动切镜头、看画面写解说词、配音合成成片,支持一键导出可编辑的剪映/CapCut 草稿,无需 GPU | Agent skills that turn videos into narrated recaps & editable CapCut drafts

v0.6.2发布于 2026-10-04 06:42 UTC619star +9 / 7 天114fork同步于 2026-11-11 11:55 UTC

怎么上手

由 README 提炼,执行前请确认
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
硬件要求按 README 说明

无需 GPU,本地只需 Python 3.10+ 和 ffmpeg;ASR、VLM、TTS 均走小米 MiMo 云端 API,不下载模型。烧录字幕需带 libass 的 ffmpeg,画面文字叠加需带 drawtext。

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

把视频自动做成中文解说成片的 Agent 技能包,还能导出可编辑的剪映草稿

把长视频自动切成镜头、用多模态模型看画面写解说词、再配音合成成片,还能一键导出可编辑的剪映/CapCut 草稿,全程不用 GPU。

核心能力

  • 七个技能串联理解、写稿、配音、组装全流程
  • 用 ASR 加 VLM 分析画面与对白,生成创作 brief
  • 先剪后配,按成片时间轴写解说,保证音画对齐
  • 多轨 timeline.json 一键导出剪映/CapCut 草稿
  • 旁白 lint 与组装 QC 生成机器可读报告

容易踩的坑

Homebrew 自带 ffmpeg 缺 libass,默认不烧录字幕只输出外挂 .srt,需装 ffmpeg-full 并调整 PATH。必须自备小米 MiMo API Key,tp-* Token Plan key 还要设 MIMO_TOKEN_PLAN_CLUSTER。仓库已从 worldwonderer 迁到 zenstory-ai,旧地址安装需重新指向新仓库。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.6.2
  1. 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。

  2. 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。

  3. 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 个加固点。
  4. 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」两种环境各跑一次;ruff clean;validate 在 ubuntu / macOS / Windows 三平台通过。

  5. 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。

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    上面这条 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 上下文;见背景调研指南。

    延伸阅读

    致谢

    许可

    MIT,见 LICENSE。

    ZenStory AI 项目

    本项目由 ZenStory AI 维护——一套开源的 Agent 故事创作、改编与生产工具(GitHub 组织:zenstory-ai)。同组织项目:

    项目用途
    oh-story-claudecode网文写作 skill 包:扫榜、拆文、写作、去AI味、封面图
    drama-skillsAI 短剧 / 漫剧创作 skill 合集:剧本、资产、分镜、图片/视频提示词、独立审查
    novel-to-game小说改编游戏 skill 合集:原著拆解、目标运行环境构建与实机运行验收
    video-recap-skills将支持的视频文件制作成中文解说,可选导出可编辑的剪映/CapCut 草稿(本仓库)
    oh-story-dshDeepSeek Harness 社区插件,提供小说、短剧、游戏和视频解说工作台
    zenstory对话即创作的 AI 小说写作工作台(app.zenstory.ai)