Communitygithub.com

视频添加字幕

为视频添加专业字幕,包括时间轴对齐、样式选择、卡拉OK特效和B-roll合成感知放置。需要先运行 `video-understand` 以获取词语级时间戳。

视频添加字幕 是什么?

该技能用于为视频添加字幕,提供从时间轴对齐、字幕分组、样式选择到最终渲染的完整工作流。它依赖于 `video-understand` 技能提供的词语级转录和时间轴信息,并需要系统安装 `ffmpeg`、`ffprobe`、Python 的 `Pillow` 库和 Node.js >= 22。该技能支持两种演示模式:`Standard`(标准,适合大多数内容)和 `Expressive`(表现力,根据语义在底部和中心位置切换,并强调关键词和数字)。`Expressive` 模式还支持卡拉OK效果和英雄句(`hero_line`)标注。该技能能够感知B-roll合成的空间上下文,确保字幕不与关键视觉元素重叠。它包含 `human`(人工)和 `agent`(代理)两种决策模式,允用户或AI代理控制字幕风格和布局的决策。主要输出包括字幕计划 (`captions-plan.json`)、SRT文件、HTML预览和各种样式审查证据。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/WhiteTowerAI/cut-as-code/tree/main/skills/video-add-captions

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

视频添加字幕 是做什么的?

依赖项

/video-understand 是先决条件。请先运行它,以便字幕使用经过验证的词语级转录和规范时间轴。 在开始之前,验证它是否已安装。如果未安装,请警告用户缺少此先决条件,并在处理媒体之前停止。

需要系统PATH中包含 ffmpeg/ffprobe、安装有 Pillow 的Python环境以及 Node.js >= 22(用于运行 .mjs 脚本和按需获取的 npx hyperframes)。hyperframes render/snapshot 驱动无头Chrome——它管理自己的 chrome-headless-shell,并在缓存的Chrome不可用时回退到系统Chrome(可设置 CHROME 环境变量进行覆盖)。在处理媒体之前检查这些依赖项。

范围

此技能负责字幕分组、样式选择、审查以及透明字幕轨。它不进行转录、剪切、重新计时、调色、重新构图或选择交付音频策略。

如果同时选择了内容卡片和图形动画,请在它们之前运行字幕。已批准的字幕布局会建立一个保留的子标题区域,后续两个操作都必须保持该区域清晰。当只有一对操作处于活动状态时,此相对顺序也适用。

先使用 video-understand。如果进行了剪切,请为活动节目时间轴添加字幕;不要将源转录的秒数视为节目秒数。

协议输入

必需:

  • work/project.json
  • work/understand/transcript.json,包含词语级源时间戳
  • work/understand/media.json
  • work/timeline.json
  • work/project.json 指定的源视频文件

时间轴是唯一的源到节目映射。所有范围都是左闭右开的 [start_s, end_s)。scripts/build_captions.py 使用共享的 projectlib.map_transcript_to_timeline;被丢弃的源范围内的词语消失,保留的词语移动到节目时间,提示总是在剪辑边界处断开。

持久化输出

work/captions/
|-- captions-plan.json
|-- caption-spatial-context.json (仅适用于符合条件的B-roll合成)
`-- caption-interaction.json
work/cache/captions/
|-- preview-project/
|-- preview-snapshots/
|-- overlay-project/
`-- overlay-frames/frame_000001.png ...
review/05-captions/
|-- captions.srt
|-- captions-style-review-<UUID>.html
|-- captions-style-review.html
|-- captions-review.html
|-- preview-early.png
|-- preview-middle.png
|-- preview-late.png
|-- preview-no-caption.png
|-- captions-evidence.json
`-- captions-summary.md

生成的HTML、复制的运行时文件、提取的源帧和叠加帧是缓存。计划、可选的空间上下文、SRT、决策收据和审查证据是持久化的。

字幕计划

work/captions/captions-plan.json 是规范的字幕计划,以 overlay 为目标,并使用节目时间。它记录:

  • timeline_id、program_duration_s 和源转录路径;
  • 提示分组设置;
  • 批准的样式、决策模式、理由、图库选择和完整的解析样式;
  • 带源支持的审查证据和审批人;
  • 带有兼容性字段 start、end、text、lines 和 words 的提示;
  • 每个提示的 program_range 和 source_ranges;
  • 每个映射词语的节目/源范围和 clip_id;
  • 带有精确有理数FPS和哈希运行时资产的本地渲染器配方。

生成器也接受旧的顶级提示数组。那只是一个独立的兼容性适配器;它无法表达时间轴来源或重新生成已批准的协议贡献。

Standard 是默认的演示模式。Standard 计划不需要 presentation 字段,并且不能仅仅为了添加一个字段而迁移。Expressive 是一种明确的演示模式,而不是一个预设:使用 --presentation-mode expressive 请求它。然后构建步骤会添加稳定的提示ID、默认的词语 semantic_role 值以及一个草稿 presentation 规划外壳;它不会猜测布局变体。

Expressive 仅支持 bottom-standard 和 center-emphasis。在填充外壳之前阅读 reference/caption-rules.md。现有的渲染器只消费已完成的 presentation.layout_beats;它不会推断位置或在节拍内更改布局。

Expressive 提示还可以定义一个连续的短语级 hero_line。使用规范 level: hero;它会以 1.5x 大小在单独行上以金色渲染该短语。旧的 level: strong 仍然被接受为输入别名并呈现相同效果,但新的代理编写的计划不得使用它。维护的词语角色 keyword、number 和 contrast 各使用 1.22x;normal 保持 1.0x。这些处理与预设正交,不会创建新的样式ID。阅读 reference/caption-rules.md 了解 schema、溢出策略和卡拉OK规则。

当活动的、经审查批准的B-roll操作包含已批准或已验证的说话人插入合成时,字幕可以从冻结的上游计划、证据、标准化合成和明确的子镜头 display_mode 中推导出 caption-spatial-context.json。这不会修改或重新选择B-roll布局。它在Expressive规划之前对齐提示边界,并仅解析维护的 preset-bottom、frame-center、panel-center 和边界仅 panel-bottom 放置。仅当 unsplittable_word_boundary 与位于下中焦点面板相邻时,才允许 panel-bottom;它将稳定提示居中于结构化说话人矩形下方的保留条带内。此类提示会与它所交叉的每个视觉上下文进行检查,而不仅仅是包含词语中点的上下文。如果没有此上下文,所有现有的 Standard 和 Expressive 放置行为保持不变。

样式

维护的预设是 clean、minimal、social-bold、pill、boxed、stroked 和 shorts。图库组合ID添加维护的主题,例如 pill-yellow、stroked-blue 和 shorts-green。卡拉OK是一个选项,而不是单独的预设。

默认委托选择:clean,卡拉OK关闭。仅当目标或素材证明合理时,才选择更具表现力的预设。将特定于作业的更改存储在一个覆盖JSON中;不要编辑生成器以进行普通的样式反馈。

Expressive 同时支持 semantic-only(卡拉OK关闭)和 semantic-plus-karaoke(卡拉OK开启)。在两种配置中,语义强调持续整个提示。在共存模式下,语义强调和活动的卡拉OK词语在所有高亮模式下都使用 style.wordHighlight.activeColor 作为其前景色;背景高亮仍然是一个附加效果。有效缩放比例为 max(semantic scale, karaoke active scale),绝不是它们的乘积。Expressive 从不渲染下划线,包括用于兼容的 contrast 语义角色。

现有的审查合约继续使用 semantic-only 作为主要的Expressive证据,并将 semantic-plus-karaoke 单独绑定。兼容性载荷字段仍然命名为 experimental_comparison;在没有审批协议迁移的情况下,不要重命名它。

阅读:

  • reference/caption-rules.md 在更改分组限制之前;
  • reference/caption-style-themes.md 了解样式词汇;
  • reference/caption-feedback-mapping.md 了解覆盖映射。

决策模式

两种诚实的模式共享相同的基于哈希的状态机:

  • human:将确切的复制图库摘要传递给 select,显示所有真实的预览证据,并将确切的复制批准或修订摘要传递给 confirm 或 adjust。绑定到审查页面的命令不接受简单的批准短语。
  • agent:仅当用户明确委托字幕决策时使用。以非空的委托说明开始,然后使用带有非空理由的 agent-select 和 agent-confirm。

人类命令在代理模式下失败,代理命令在人类模式下失败。没有空间上下文的 Standard 模式需要四个维护的源支持图像;Expressive 和合成感知审查使用它们的动态证据合约。对源、计划、时间轴、样式、覆盖、项目元数据、审查页面或证据的更改会使批准失效;空间上下文、上游B-roll修订或绑定合成的更改也是如此。重建受影响的工件并再次审查它们。

规范工作流

从仓库根目录运行。设置项目路径:

$RepoRoot = (Resolve-Path ".").Path
$SkillRoot = Join-Path $RepoRoot "skills\video-add-captions"
$ProjectRoot = (Resolve-Path "<project-root>").Path
$Work = Join-Path $ProjectRoot "work"
$SourceVideo = "<absolute path from work/project.json>"
$Plan = Join-Path $Work "captions\captions-plan.json"
$SpatialContext = Join-Path $Work "captions\caption-spatial-context.json"
$SpatialArgs = @()
$SpatialReviewArgs = @()
$Receipt = Join-Path $Work "captions\caption-interaction.json"
$Review = Join-Path $ProjectRoot "review\05-captions"
$Cache = Join-Path $Work "cache\captions"
$PreviewProject = Join-Path $Cache "preview-project"
$ComparisonProject = Join-Path $Cache "preview-project-expressive-karaoke"
$OverlayProject = Join-Path $Cache "overlay-project"
$OverlayFrames = Join-Path $Cache "overlay-frames"
New-Item -ItemType Directory -Force -Path (Split-Path $Plan),$Review,$Cache | Out-Null

在构建字幕计划之前,请询问用户选择演示模式,除非当前请求已经明确选择了一个。以用户当前会话的语言呈现问题,同时保持 Standard 和 Expressive 标识符不翻译。保存下面的英文源提示在此文件中,以当前会话的本地化形式呈现选择,然后 展示并停止:

选择字幕演示模式:

1. Standard:使用稳定的常规放置,适合大多数内容。
2. Expressive:根据语义在底部和中心放置之间切换,并强调关键词和数字。

回复 Standard、Expressive 或 "使用默认值 (Standard)。"

在用户响应之前不要运行 build_captions.py。如果用户以任何措辞明确委托选择,则选择 Standard。在构建计划之前声明选择了 Standard 作为保持兼容性的默认值。

构建节目时间提示和审查 SRT:

python "$SkillRoot\scripts\build_captions.py" `
  "$Work\understand\transcript.json" `
  $Plan `
  "$Review\captions.srt" `
  --timeline "$Work\timeline.json" `
  --source-transcript "understand/transcript.json" `
  --max-chars 42 --max-lines 2 --max-dur 6 --gap 0.6

在用户选择 Standard 后,上述命令会产生不变的 Standard 计划。在用户选择 Expressive 后,使用以下参数运行相同命令:

  --presentation-mode expressive

在草稿提示生成之后,以只读方式检查活动的 B-roll 操作及其绑定计划。仅当操作处于活动状态、其状态为 approved 或 verified、review.status 为 approved、说话人插入分析/代理输入/预览/许可绑定完整,并且至少有一个已验证或标准化的镜头具有维护的合成布局时,才启用合成感知放置。空间构建器使用明确的子镜头 display_mode: enabled 来确定说话人几何形状;pure_broll 和缺少说话人证据永远不会暗示说话人矩形。

当符合条件时,在填充任何 Expressive layout_beats 或 hero_line 之前,将草稿提示与每个 B-roll 视觉边界对齐。对齐仅在词语间隙处拆分并原子化写回;词语内的边界保持词语完整并记录强制审查证据:

python "$SkillRoot\scripts\caption_spatial_context.py" align `
  --project-root $ProjectRoot --plan $Plan --out-plan $Plan

对于符合条件的项目,准备后面每个关卡使用的可选参数:

$SpatialArgs = @("--spatial-context", $SpatialContext)
$SpatialReviewArgs = @("--spatial-context", $SpatialContext, "--project-root", $ProjectRoot)

当不存在符合条件的合成时,跳过所有四个空间命令,并保持 $SpatialArgs 和 $SpatialReviewArgs 为空。不要创建或附加空上下文。

在开始样式选择或生成预览之前,代理必须一次性规划整个 Expressive 节目:

  1. 阅读转录、可用的理解工件、规范时间轴、生成的字幕提示以及证明布局更改合理所需的任何真实源帧证据。
  2. 填充所有 presentation.layout_beats,注释异常的词语 semantic_role 值,在必要时最多向一个提示添加一个连续的 hero_line 并使用规范 level: hero,为每个节拍/英雄行写一个理由,并写整体 presentation.planner.rationale。
  3. 仅当每个提示都被精确覆盖一次后,将 presentation.planning_status 设置为 complete。
  4. 在预览生成之前验证完成的计划:
python "$SkillRoot\scripts\build_captions.py" --validate-plan $Plan

对于符合条件的合成,仅在最终提示ID和Expressive候选完成后才构建、验证并附加上下文。这保留了上游布局,并将其当前修订版和哈希绑定到字幕计划中:

python "$SkillRoot\scripts\caption_spatial_context.py" build `
  --project-root $ProjectRoot --plan $Plan --out $SpatialContext
python "$SkillRoot\scripts\caption_spatial_context.py" validate `
  --project-root $ProjectRoot --plan $Plan --context $SpatialContext
python "$SkillRoot\scripts\caption_spatial_context.py" attach `
  --project-root $ProjectRoot --plan $Plan --context $SpatialContext

不要要求用户逐个提示地选择位置。用户审查现有的HTML证据,只纠正少量异常节拍。在规划后开始交互,保持现有的字幕计划哈希绑定具有权威性。

启动一种决策模式。对于 human 模式,无需用户定位文件,将维护的离线图库发布到项目审查目录:

$StartOutput = node "$SkillRoot\scripts\caption_interaction.mjs" start `
  --state $Receipt --source $Sou

…

[截断以供翻译]

Individual skills in this repo

This repo contains 8 individual skills — each has its own dedicated page.

相关技能