Communitygithub.com

vidmoat/字幕样式化

为移动端静音观看场景优化字幕样式、时间和位置,确保字幕可读。适用于添加、重新样式、修复或制作无障碍字幕,或准备短视频平台内容。

字幕样式化 是什么?

该技能提供了一套完整的字幕样式化规则和工作流程,专为移动设备静音观看场景设计。它包含默认参数表格(如行数、字符数、阅读速度、持续时间、位置、字体大小、颜色对比度等),以及从转录时间校正、分段、阅读速度检查、说话人标记到最终渲染检查的九个步骤。技能还详细列出了使用ffmpeg烧录字幕时的常见陷阱(如宽度估算偏差、时间偏移、ASS样式坐标转换、颜色内联更改导致的背景板接缝问题),并提供了对应的解决方案和检查脚本。该技能支持SRT和VTT格式,适用于TikTok、Reels、Shorts和YouTube等平台,确保字幕在移动端安全区内清晰显示。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/vidmoat/skills/tree/HEAD/skills/core/caption-styling

在你喜欢的 AI 中提问

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

文档

字幕样式化 是做什么的?

字幕大约在两秒内被阅读,在手机上,静音状态下,在移动画面之上,在应用按钮之下。以下每个默认值都服务于该读者。如果用户有编辑器,使用编辑器;数字在任何地方都是一致的。没有编辑器时,使用 references/ffmpeg-burn-in.md 中的 ffmpeg 配方。

默认值

除非用户或其样式指南另有说明,否则使用这些默认值。

设置默认值原因
每段字幕行数最多2行第三行会遮挡主体,且无法及时阅读。
每行字符数横屏16:9:42;竖屏9:16:以您的字号适应安全宽度:约64 px时为32,72 px时为28(大小写混合)过长的行会导致视线移动,竖屏时则会超出画框。
阅读速度最多每秒17个字符(约每分钟160至180词)广播实践;WCAG 未设定速度,因此这是工作标准。
单段持续时间最短1秒,最长6秒短于1秒会闪烁;超过6秒观众会重读。
段落间隔0 或至少2帧1帧的间隔视觉上像闪烁。
位置底部居中,在安全区内;在1080x1920上,文字保持在底部420 px(高度的22%)以上这样可以避开 TikTok 和 Reels。当下部三分之一出现人脸、烧录文字或应用UI时,移到顶部。
字号,句子式字幕横屏:画面高度的4.5至5%(1080p下为49至54 px)。竖屏:1080x1920下为64至72 px在手臂距离可读,且上述行长度仍适合900 px安全宽度。
字号,简短短视频字幕(1至3词)在1080x1920下约140至150 px,大小写混合每行最多约14个字符,全大写为11个这些是图形元素,而不是字幕。
颜色接近白色的 #F2F2F2,配70%至80%不透明度的深色底板,或3至5 px深色轮廓加柔和阴影移动画面的对比度无法逐帧测量;底板可保证 WCAG 4.5:1。
字体一种粗体无衬线字体(粗体或半粗体);视频中最多使用两种字体系列细体在压缩后会消失。
单词高亮(卡拉OK)仅对当前单词使用一种强调色,且该色也必须满足4.5:1对比度使用第二种颜色进行“强调”会让观众寻找含义。

渲染前进行适配检查。 一个粗体 Arial 类无衬线字体(大小写混合)平均每个字符占字体大小的0.44(测量值,含空格);全大写平均为0.55;紧凑字体约为0.35。因此,一行的大致宽度为 字符数 x 系数 x 字号_像素,并且必须适合安全宽度(1080x1920上为900 px,横屏上为宽度的90%),而不是画框。在96 px字号下,一个27字符的大小写混合行约为27 x 0.44 x 96 = 1,140 px:比整个1080 px画框还宽。这些系数是针对测量所用的字体的平均值(参见注意事项),因此请使用渲染帧确认。

平台像素安全区域以及如何为任何画布推导安全框的信息,请参阅 references/platform-safe-zones.md。在竖版视频放置字幕前请阅读该文档。

工作流程

  1. 从实际时间开始。 字幕需要带有段落或单词时间的转录稿。没有转录稿就无法制作字幕:请说明情况,或先进行转录。切勿编造措辞。

  2. 将时间重新调整到编辑后的时间线。 转录稿的时间是基于源文件的。在剪裁、剪切或改变速度后,需要将每段字幕的时间偏移和缩放以适应时间线(参见注意事项)。

  3. 将转录稿分段为段落。 在从句边界处断开:在标点符号后,在连词和介词前。切勿将冠词与其名词分开,将名字与其姓氏分开,或将数字与其单位分开。在两个可能的断点中,选择使两行长度最接近的那个。

  4. 强制执行阅读速度。 一段超过每秒17个字符的字幕应被拆分或延长到其后的静音部分。切勿缩小字体来适应。

  5. 标记说话者和声音。 说话者变化时,在行首使用 - (或首次使用时用括号给出名字将有意义的非语音内容放在方括号内:[门砰地关上],[紧张的音乐]。不要为已从音频中剪掉的填充词添加字幕。

  6. 根据默认值和该画布的安全框进行样式化和定位。

  7. 检查文件,然后修复它报告的每个错误:

    python scripts/check_captions.py captions.srt --fps 30 --max-chars 32
    

    它会检查行数、行长度、每秒字符数、持续时间、间隔和重叠,并在出现错误时以非零状态退出。添加 --json 可获取机器可读的报告。其默认行限制为32个字符,这是竖屏和可访问性的数值;对于横屏字幕,使用 --max-chars 42。

  8. 查看渲染的帧,而不是设置:查看第一段、最长的一段以及背景最繁忙的一段。确认没有任何内容被裁剪,没有内容位于应用UI下方,并且文字在手机尺寸下可读。

  9. 提供两个版本:一个用于社交媒体的烧录版本和一个用于可访问性和平台上传的侧挂 .srt 或 .vtt 文件,除非用户仅要求一个。

注意事项

  • 宽度估算在紧凑字体上不准确。 平均字形宽度的估算误差可能超过3倍:一次溢出检查报告某行每边超出127 px,而实际在1080 px画框中渲染为270 px宽。为了满足该估算而缩小字体,在1080x1920上产生了76 px的字幕,而紧凑样式要求约为150 px,在手机上太小无法阅读。请渲染一帧并测量。
  • 转录稿时间是相对于源文件的。 如果一个剪辑从其源文件开始后12.4秒处开始,则从每段字幕时间中减去12.4秒,并加上剪辑在时间线上的起始时间。在2倍速下,持续时间减半,因此段落可能低于1秒;请重新分段,而不是保留旧的段落边界。
  • ffmpeg 基于288行网格(而非像素)烧录SRT。 使用 subtitles=file.srt:force_style=... 时,FontSize 和 MarginV 是基于384x288的脚本空间的,因此 FontSize=24 在1080行视频上渲染为90 px字体,在1920行视频上渲染为160 px。使用 FontSize = px * 288 / frame_height 进行转换,或编写一个 PlayResX 和 PlayResY 等于视频大小的ASS文件,以便单位是像素(配方中已包含)。
  • ASS中的底板使用 OutlineColour。 使用 BorderStyle=3 时,框的颜色来自 OutlineColour,而非 BackColour,且ASS颜色格式为 &HAABBGGRR,其中alpha值 00 表示不透明(&H40000000 表示75%不透明度的黑色)。
  • ASS底板中的内联颜色更改会破坏底板。 BorderStyle=3 行内 {\c...} 高亮会为每个颜色运行绘制独立的框,且半透明框重叠会产生暗色接缝。应将底板绘制为自己的图层,带有不可见文字,并将可见文字放在上方图层(配方中展示了如何操作)。
  • 缺少字体时静默失败。 libass 会回退到另一种字体而不报错。请检查 ffmpeg 日志中的 fontselect: 行,或传递 fontsdir= 参数。
  • Windows路径会破坏字幕过滤器。 需要对驱动器冒号进行转义:subtitles='C\:/clips/subs.srt'。
  • 演唱歌词是短语计时的。 语音识别在音乐下会丢失单词(一次测试中17个单词丢失了4个),并返回短语时间,而非单词时间。在没有与音频核对的情况下,不要据此构建逐词卡拉OK。
  • 某个预设可能多处为当前单词上色。 一个编辑器霓虹灯预设同时使用高亮颜色和发光来绘制高亮,因此覆盖一个不存在的字段不会产生任何效果,且无任何错误。应覆盖所有携带该颜色的字段(使用其真实名称),并在渲染帧上确认。

Individual skills in this repo

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

相关技能