Communitygithub.com

Reel 字幕与叠层效果

为已完成的垂直人物访谈视频片段添加上参考级 Reel 风格的字幕和叠层效果。该效果包含粗轮廓衬线字体字幕、B-roll 无衬线字幕、砖红色标题卡、红色网格搜索药丸全屏覆盖、浮动倾斜卡片、步骤列表、新旧对比分割、工具芯片卡片和产品演示可听卡片,适用于赞助 Reel、访谈 Reel,并每 6-10 秒插入编辑图形节拍,使 Reel 不显得像广告。

Reel 字幕与叠层效果 是什么?

Reel 字幕与叠层效果技能是一个专业工具,用于为已剪辑的 9:16 垂直视频(例如人物访谈片段)添加参考级视觉润色。它通过一个 `edit.json` 文件驱动两种渲染引擎:HyperFrames(默认)和 Remotion,确保两者逐帧匹配。该技能通过多种精心设计的图形元件增强内容,包括带粗轮廓的衬线字体单字字幕(放置在画面 75% 高度处,避免遮挡手部或麦克风)、用于 B-roll 覆盖的无衬线字幕、用于开场语的砖红色标题卡、用于产品提及的全屏网格覆盖、用于统计或技巧的浮动卡片、步骤列表、新旧对比分割以及可听产品演示卡片。对于赞助 Reel,它会强制加入至少两个产品演示节拍,并包含一个可验证的优惠线条(Offer Line)。技能还通过 `verify.py` 脚本进行严格的质量检查,包括帧计数、损坏帧、字幕可读性、卡片边缘以及 CTA 优惠的可见性。默认情况下,它会混合授权音乐和音效,使用“steady-funk-bed”预设,并通过 `music_stage.sh` 和 `music_verify.py` 确保语音清晰度。该技能支持 HyperFrames(Apache-2.0)和 Remotion(个人和三人以下公司免费),并提供了完整的命令行工作流程,从转录到最终渲染和验证。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/dtenuta/reel-editing-skills/tree/main/skills/reel-captions-overlays

在你喜欢的 AI 中提问

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

文档

Reel 字幕 + 叠层效果

为一个已经剪辑好的 9:16 Reel(通常为 2160x3840,30fps,例如 talking-head-edit 的输出)添加字幕和叠层效果。一切由 edit.json(逐帧的字幕页和叠层)驱动,两个渲染器都读取该文件,确保 HyperFrames 和 Remotion 版本逐帧匹配。

SK=~/.claude/skills/reel-captions-overlays
PY=$($SK/scripts/find_python.sh)                          # faster-whisper large-v3 + opencv ($REELKIT_PYTHON, 仓库 .venv, 或 python3)
AUDIO_PY=~/.cache/reel-audio/venv/bin/python               # 音乐阶段 (scripts/setup_audio.sh 创建)
ANA_PY=~/.cache/reel-audio/analysis-venv/bin/python        # 参考风格分析 (scripts/setup_audio.sh --analysis)

默认工具:HyperFrames (Apache-2.0, 固定版本 [email protected])。Remotion (4.0.539) 作为同位构建保留。Remotion 对个人和三人以下公司免费;较大公司需要购买商业使用许可 (remotion.pro/license)。HyperFrames 没有此类许可条件。

工作流程

  1. 设置 (首次运行)。$SK/scripts/new_reel.sh <reel.mp4> <workdir> 该脚本使用 large-v3 模型进行带时间戳的词级转录,每 0.5 秒检测人脸框 (生成 faces_src.json) 和镜头剪切点 (生成 cuts.txt),将 overlays.example.json 复制到 <workdir>/overlays.json,然后停止。
  2. 填写 overlays.json。首先阅读 words_raw.json。
    • corrections:通过令牌序列修正品牌名称,例如 ["Ackme"]→"Acme", ["re","-motion,"]→"Remotion,", ["Acme","Voice."]→"Acme Voice."。将品牌词对粘合为一个令牌可确保它们在同一字幕页上。 保持外语原文不变(例如 "Même voix, autre langue.")。
    • sansWindows:B-roll 切换镜头、覆盖和 promptDemo 跨度的 [开始,结束] 秒数。这些区域的字幕切换到粗无衬线字体(相同的 75% 高度车道)。
    • overlays:参见下面的样式规范和图形计划。时间以秒为单位,取自词级时间戳。
    • sponsored: true:用于付费或品牌 Reel。它启用演示节拍规则(见下方的赞助 Reel)和验证警告。
  3. 构建两个项目。$SK/scripts/new_reel.sh <reel.mp4> <workdir> <workdir>/overlays.json
  4. 渲染前预览。cd <workdir>/hyperframes && npx [email protected] snapshot --at 2.5,20,30 --no-end (或在 remotion/ 目录中执行 npx remotion still Reel x.png --frame=N --scale=0.5)。
  5. 渲染。这些需要 Chrome,因此在 Bash 沙箱外运行 (dangerouslyDisableSandbox)。在沙箱内,Chrome 在 Mach 端口查找时会失败。
    • <workdir>/hyperframes/render.sh <out>_captions_hyperframes.mp4 渲染一个 1080x1920 布局,超采样至 2160x3840,CRF 16,带有 faststart。
    • <workdir>/remotion/render.sh <out>_captions_remotion.mp4 以 --scale=2、CRF 16、AAC 192k 和 faststart 执行相同操作,然后运行 scripts/repair_remotion.py(参见注意事项)。
  6. 验证。$PY -I $SK/scripts/verify.py <reel.mp4> <out.mp4> <workdir>/edit.json <workdir>/faces_src.json <workdir>/qc <label> (如果帧数、损坏帧、可读性、卡片边缘或 CTA 优惠不通过,则退出代码为 1 并打印 FAIL;在 60 秒 4K Reel 上约需 9 分钟)
    • 检查帧计数和时长是否与源匹配。
    • 扫描每一帧是否有损坏(错误视频帧或黑色方块)。corrupt_frames 必须为 0。
    • 抽查 5 个字幕页:页面开始前一帧的色带必须为空,页面开始后两帧的色带必须填满。
    • 测量每个叠层下的人脸框像素变化。这应该接近 0,除了全屏覆盖和 promptDemo 卡片(它们故意遮挡脸部,因此被排除在人脸、损坏帧和可读性检查之外)。
    • 列出 demo_beats(promptDemo 叠层,或任何带 "demo": true 的叠层)。当 edit.json 中有 sponsored: true 且演示节拍少于 2 个时,打印 WARN 并将其添加到 warnings 中(非硬性失败;修复 Reel 或在报告中说明原因)。
    • 之前/之后分隔符 (v7, 警告)。对于每个 promptDemo 的前后行对,报告 before_after:两个剪辑共有的词、剪辑间隙、渲染中的静音检测,以及剪辑是否包含切换色带和切换音效 (build_edit ba)。如果一对行重复了词但缺少所有元素(间隙 >= 400 毫秒、色带、音效),则打印 WARN:重复的行没有分隔符会被视为剪辑故障(参见 promptDemo)。
    • CTA 优惠 (v7, 硬性检查)。带有 offer 的 cta 必须完全可见 >= 2.5 秒,大小 >= 40 像素(在 360 像素宽手机上为 13+ 像素),并且实际绘制(其色带内的像素变化)。<label>_offer_mobile.jpg 以手机尺寸显示该优惠;请查看。如果赞助 Reel 的 CTA 没有 offer,则生成 WARN。
    • 手机尺寸可读性:将 8 个字幕页缩小至 360 像素宽,测量笔划粗细、文本高度和轮廓光晕(字形亮度减去其周围环)。最低要求:笔划 >= 4.0 像素,高度 >= 28 像素,光晕 >= 130。legibility_ok 必须为 true。<label>_mobile.jpg 显示裁剪区域;请查看。
    • 生成一个接触表,其中包含每个叠层中间的一帧静止图像,以及一个同步裁剪表。在报告前打开这两个文件。
  7. 音乐 + 音效 (默认阶段;使用 --no-music 或 MUSIC=0 跳过)。填写 <workdir>/music_plan.json(首次运行时从 music_plan.example.json 复制而来;使用默认风格预设 steady-funk-bed;参见下方的音乐和声音设计),然后执行 $SK/scripts/music_stage.sh <out_hyperframes.mp4> <workdir> <out>_music.mp4 此脚本将背景音乐和音效混合到语音下方,使用视频流复制(不重新编码)和音频裁剪至视频时长进行复用,生成 <out>_music_mobile.mp4 手机副本 (MOBILE_OUT= 可将其放置于其他位置),并运行 music_verify.py,包括对照计划预设的风格检查。必须输出 PASS。它拒绝覆盖已存在的输出(使用 FORCE=1 允许覆盖)。如果任何句子的语音低于其下方音乐超过 6 dB,则也会失败(在报告中为 voice_over_music,--min-voice-over-music):重要的是每一行都能被清晰听到。背景音乐是一个稳定的、约为 -13 dB(相对于语音)的未压缩律动,因此即使段落平均值通过,一句安静的话也可能沉入其中。在上游使用 talking-head-edit 的语音电平调整或分段增益来修复问题,而不是降低整个背景音乐。一个典型的通过检查的访谈 Reel 测得最小 11.2 dB,中位数 14.1 dB。打开 <workdir>/qc/music_sections.png。首次运行会创建 ~/.cache/reel-audio/venv (scripts/setup_audio.sh)。
  8. 手机副本(用于发送,当音乐阶段被跳过时):ffmpeg -i <out.mp4> -vf scale=720:1280:flags=lanczos -c:v libx264 -preset slow -crf 22 -maxrate 2800k -bufsize 5600k -pix_fmt yuv420p -c:a copy -movflags +faststart <out>_mobile.mp4(对于 60 秒视频约 14-19 MB,低于 25 MB 限制)。复制已处理的音频,切勿重新编码:二次 128k AAC 编码曾将一个 Reel 的真实峰值从 -1.3 提升至 -0.7 dBTP。

样式规范 (来自参考 Reel)

以下所有尺寸均基于 1080x1920 设计空间(以 2 倍渲染)。共享 CSS 位于 templates/style.css。

  • 字幕 (v2:v1 字幕为细白线,在手机上难以阅读。更粗、更大、带轮廓是默认设置。)
    • 每页一个词,偶尔两个:短功能词与其邻居合并,品牌词对被粘合。
    • 文本大小写和标点按实际发音书写 ("content.", "Then")。切勿使用全大写。无逐词高亮:每页 1-2 个词时只会增加噪音。
    • 字体:DM Serif Display(随附于版本 @fontsource/[email protected],OFL 许可),136px,白色。切勿再使用如 Instrument Serif Regular 之类的细衬线字体作为字幕字体。Instrument Serif 仅保留用于纸色或红色卡片标题。
    • 轮廓: 一个带描边的词副本(使用 ::before 和 data-t,-webkit-text-stroke: 6px,因此字形外 3px),颜色为 86% 的近黑色,绘制在填充文字后方,以确保不削弱字母。阴影: 0 0 3px,0 5px 12px 和 0 14px 34px,均为深色。
    • 适配: build_edit.py 根据 templates/fonts/caption_metrics.json 为每页设置 fs 字体大小,确保页面宽度不超过 820px(例如 "automatically." 使用 127px)。如果字体更改,请使用 scripts/caption_metrics.py 重新生成度量数据。
    • 位置: 一条居中车道,位于高度的 75% 处 (y=1440),低于说话者的手部和麦克风,高于底部 20% 的 UI。仅在特写镜头时降至下巴 + 6%(上限为 76%)。在典型的桌面设置中,手部位于 55-72%,因此“下巴下方”车道 (60%) 会与手部重叠。
    • 动画:一个 4 帧弹入效果 (缩放 0.86→1,y 偏移 14→0,淡入),提前一帧开始,确保词在其第一帧就可见。
    • 页面精确地在词的起始帧开始,并保持到下一页,或者在停顿时保持到词结束 + 0.2 秒。
  • B-roll 和覆盖字幕: Inter 900,120px,字距微调 -0.03em,相同的轮廓和 75% 车道。
  • 标题卡片 (titleCard,用于钩子短语)
    • 砖红色 #B23A2E 盒子,810px 宽 (75%),顶部位于 y=190。
    • 顶行:Anton 全大写,118px。其下方:白色 Instrument Serif 副标题,62px。
    • 其底部大约位于画面高度的 23%。此位置故意比参考值高 (顶部边缘 22-28%),因为脸部大约从 26% 开始。
  • CTA (cta)
    • 白色斜体衬线 "Comment" (82px) 位于一个红色盒子上方,盒子内为 Anton 关键字 (196px,例如 "GUIDE")。与标题卡片使用相同的上方色带区域。
    • 盒子在踢脚线后 3 帧弹入。
    • 优惠行 (offer, 赞助 Reel, v7):品牌优惠位于下巴下方的一张纸色卡片上,例如 "Use my link for a\nFREE 14-day trial."。使用品牌自己的措辞。\n 设置换行,全大写词 ("FREE") 获得白底红字框。"Comment / WORD" 仍是主要元素;优惠行是辅助行。build_edit.py 推导出 offerF (来自 offerAt,默认 CTA 开始后 10 帧),offerY (下巴 + 3%,来自 CTA 窗口上的 --faces,保持在画面高度的 55-60%,约在 1385px 处,高于字幕墨水) 和 offerFs (Inter 适配至 720px,最大 46px;低于 40px 时发出警告)。卡片宽 780px (x 150-930,避开右侧 UI) 并倾斜 -1.5°。
    • 优惠必须完全在屏幕上 >= 2.5 秒。 如果说话者说完 CTA 后 Reel 结束得太快,则保持最后一帧:$SK/scripts/hold_end.sh <reel.mp4> <frames> <reel_hold.mp4> 对剪辑进行流复制,追加 N 个已编码的最后一帧副本并附带数字静音,检查语音是否解码后样本一致。选择 N 使得 Reel 正好在音乐节拍前结束 (节拍 k = k * 60 / bpm,cue_at 为 0),将 CTA 的 end 和音乐计划部分的 end 设置为新长度,并使用新的 --frames 运行 build_edit。背景音乐在保持期间继续播放,并在最后一帧处切断(例如:32 帧,在 68.2 秒结束,正好在 110 BPM 背景音乐的第 125 拍之前,位于 68.207 秒;优惠完全显示 3.2 秒)。
  • 全屏覆盖 (takeover,用于工具或产品提及,持续 1.5-3 秒)
    • 全屏深红色 #8E1F17,带微妙的 8x14 浅红色网格。
    • 一个白色圆角搜索药丸(左侧为放大镜;右侧为麦克风和镜头),其粗斜体查询内容在 14 帧内逐字显示。
    • 其下方,一个白色圆角卡片,包含工具名称(衬线 128px)、一行描述、红色波形和 2-3 个标签。
    • 切勿伪造真实产品 UI。 使用仅包含文本的 neutral 卡片。语音在其下方继续。
  • 浮动卡片 (floatCard,用于统计数据、提示或标签;可选 kicker, width)
    • 纸色 #FBF7F1 卡片,470px 宽,顶部位于 y=200,在左侧或右侧。旋转 ±3-4° 并带有深阴影。
    • 内容可以是:可选踢脚线 + 大号 Anton 数字 + 衬线标签 + 小号大写行,或旗帜变体:flag: "es" (踢脚线 + CSS 旗帜 + 词) 或 flag: "us-es" (踢脚线 "Same voice, different language" + 美国国旗 → 西班牙国旗 + 词)。
    • Emoji 旗帜使用 CSS 绘制,因此从不依赖 emoji 字体。
  • 步骤列表 (steps):一张纸色卡片位于顶部 (y 150),带红色踢脚线和编号行 (DM Serif 54px)。每个项目有自己的 at 时间,并在说话者说出时弹入;当前数字为红色,较早的行变暗。当说话者说“三个步骤”、“首先...然后”时使用。
  • 新旧对比分割 (split):两个倾斜的窗格并排位于顶部,深色 "Old way" (带删除线) 和红色 "New way"。新窗格在 newAt 时弹出。使用 \n 控制 old/new 中的换行。当说话者对比过去和现在的方式时使用。
  • 芯片卡片 (chipCard):一张纸色卡片,带踢脚线、作为轮廓文本芯片(无 Logo)的工具名称和一行小字。用于“我使用的工具”。
  • 提示演示 (promptDemo,产品演示节拍,3-7 秒;仅 HyperFrames,Remotion 跳过)。在赞助商要求听到(而不仅仅是听说)产品后添加。
    • 全屏纸色卡片,带有覆盖在演示音频上的微弱网格。从顶部开始:
      • 红色标签药丸 (y 168),说明剪辑的真实制作方式,例如 "Acme Voice · v2 model";无 Logo,无 "MCP",除非 MCP 确实制作了它;
      • DM Serif 标题,命名任务 (y 252,例如 "Fix one word", "Sad to excited, one take");
      • 一张 "Prompt" 卡片 (y 400, 940px),其提示在 typeAt 和 typeEnd 之间逐字显示,随后是小型模型脚本,其中 [direction] 标签为红色(脚本超过 150 字符后为 24px);
      • 每个剪辑对应一行波形,在提示卡片下方流动 (.stack 网格:短提示时为 y 770,长提示 + 脚本时会下推,使得脚本的最后一行永不被隐藏;v6 错误)。键入的提示覆盖在一个不可见的完整副本之上,因此卡片从第一帧起就具有最终高度,并且当提示换行时各行不会跳动(v6 捕获了第三行处的 53px 跳动)。
    • 每行包含:
      • 一个标签 (kind: before gre...

[内容截断,待翻译]

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能