字幕控制需求 / ASS Caption Requirements

以 ASS 烧制字幕为最终产物,前端 GUI 只负责预览和简化配置

一、核心需求和自动化策略

自动适配

  • PlayResX / PlayResY 默认等于视频真实宽高。
  • 支持常见比例:9:16、16:9、1:1、4:5、3:4、5:4 等。
  • 同一比例不同清晰度共用策略,默认字号保持一致,边距和位置按真实像素换算。

跟读和排版

  • 高亮以朗读单元为单位:空格语种按词切分,标点跟随前一个词;日语不按英文词数处理,需单独按显示字符数和实测宽度限制;阿语等 RTL 语种按朗读逻辑顺序推进,屏幕视觉表现应从右到左高亮。
  • 每行同时受最多朗读单元数和可显示宽度约束:先按语种和画幅给软上限,再用 ASS/libass 实际测量行宽,超出左右安全边距则提前换行。
  • 默认最多 2 行;ASS 烧制用显式行中心控制位置,当前实烧示意按两行中心间距 = 字号 x 1.1。
  • 若 2 行仍放不下,剩余朗读单元切到下一段字幕窗口;极端长词需降级处理,如缩小字号、轻微压缩 ScaleX 或按语种规则拆分。
  • 词间距需要比普通正文更松;ASS 没有独立的 word-spacing,后端可在文本生成阶段用额外空格、硬空格或分词定位来控制。

默认样式

  • 每行最多朗读单元默认:拉丁语系/俄语可按竖屏 4、方屏 4、偏竖中间比例 4、偏横中间比例 5、横屏 6 作为软上限;阿语可适当放宽到竖屏 4-5、方屏/中间比例 5-6、横屏 7-8。最终仍以安全边距内可容纳宽度为准。
  • 默认字体:拉丁语系/俄语优先 Montserrat Bold 700,中文/日韩优先映射同等粗字重的 Source Han Sans;阿语不用 Cairo,不加粗,按 Montserrat Regular + 阿语常规字重兜底字体处理。
  • 紫色高亮底块按词 bbox 生成,基础字号 70,竖屏 720x1280 基准底块高度约 60。
  • 字体兜底:Source Sans Pro + Noto Sans 多语系字体;前端预览和后端烧制需使用同一套字体映射。
  • GUI 仅覆盖常用快捷配置,其余高级参数通过 agent 对话继续微调。

二、ASS 实现评估

正式产物由后端生成 ASS,并通过 ASS/libass/ffmpeg 烧制到视频;前端 HTML/CSS 只做近似预览。后端需要评估 ASS 参数范围和对应实现方式,包括 Style 参数、Dialogue 覆写、词级时间切分、绘图底块、字体映射、大小写文本处理,以及必要的降级方案。

三、四种预设样式效果

样式 1:紫色高亮跟读
视频相对路径:https://cdn-tobatsu.funplus-marketing.ai/adhoc/visual-explain/ass-caption-control/spec/style-1-f81a1b51.mp4
样式 2:黄字黑描边跟读
视频相对路径:https://cdn-tobatsu.funplus-marketing.ai/adhoc/visual-explain/ass-caption-control/spec/style-2-f62ed0c4.mp4
样式 3:蓝绿渐变跟读
视频相对路径:https://cdn-tobatsu.funplus-marketing.ai/adhoc/visual-explain/ass-caption-control/spec/style-3-64ec30ff.mp4
样式 4:逐词跳出
视频相对路径:https://cdn-tobatsu.funplus-marketing.ai/adhoc/visual-explain/ass-caption-control/spec/style-4-c105ffd4.mp4
预设 固定视觉参数 动态效果
紫色高亮跟读 白字,字重约 700,黑描边 3;当前词紫色底块 #8b19ff,高亮词叠原地黑色柔边 blur5 按词推进,当前词显示底块,读过词恢复白色。
黄字黑描边跟读 白字,当前词黄字 #fff000,黑描边 5,X 阴影 6。 只高亮当前词,已读词和未读词均为白色。
蓝绿渐变跟读 白字,黑描边 3,无 X 阴影;目标视觉为当前词蓝绿底块。 按词推进;纯 ASS 可用切片近似或单色降级。
逐词跳出 白字,黑描边 4,无 X/Y 阴影。 每次只显示一个词,词级切换,不逐字累加。

ASS 参考参数

下面是给后端实现评估的参考写法。字号和位置示例按 720x1280 竖屏实烧校准值写;常见画幅默认基础字号为 70,不强制按手机预览宽度反推等大。ASS 的 Fontname 只能写单个字体名;多语系 fallback 由服务端字体映射处理。

样式 1:紫色高亮跟读

; 当前词紫色底块需要词级切片 + 绘图层
; #8b19ff -> ASS BGR: &H00FF198B
Style: PurpleHighlightFollow,Montserrat,70,&H00FFFFFF,&H00FFFFFF,&H00000000,&H00FF198B,-1,0,0,0,100,100,0,0,1,3,0,5,0,0,0,1
Style: PurpleHighlightShadow,Montserrat,70,&HCC000000,&HCC000000,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,0,0,5,0,0,0,1

; 底块层:坐标由当前词 bbox 计算;当前基准高度约 60,圆角 10
Dialogue: 0,0:00:00.00,0:00:00.80,PurpleHighlightFollow,,0,0,0,,{\an7\pos(222,1036)\p1\bord0\shad0\1c&H00FF198B&}m 10 0 l 266 0 b 271.52 0 276 4.48 276 10 l 276 50 b 276 55.52 271.52 60 266 60 l 10 60 b 4.48 60 0 55.52 0 50 l 0 10 b 0 4.48 4.48 0 10 0{\p0}

; 文字层:整行白字;当前词再叠白字 + 原地黑色柔边
Dialogue: 1,0:00:00.00,0:00:00.80,PurpleHighlightFollow,,0,0,0,,{\pos(360,996)}TILES SURVIVE
Dialogue: 2,0:00:00.00,0:00:00.80,PurpleHighlightShadow,,0,0,0,,{\pos(360,996)\blur5}SURVIVE
Dialogue: 3,0:00:00.00,0:00:00.80,PurpleHighlightFollow,,0,0,0,,{\pos(360,996)}SURVIVE

样式 2:黄字黑描边跟读

; 当前词黄字,其他词保持白色
; #fff000 -> ASS BGR: &H0000F0FF
Style: YellowStrokeFollow,Montserrat,70,&H00FFFFFF,&H00FFFFFF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,5,6,5,0,0,0,1

; 每个词一个时间片;当前词用 \1c 覆写为黄字
Dialogue: 0,0:00:00.00,0:00:00.60,YellowStrokeFollow,,0,0,0,,{\xshad6\yshad0}SURVIVING {\1c&H0000F0FF&}THE{\1c&H00FFFFFF&} APOCALYPSE

; 下一片再切到下一个词,已读词恢复白色
Dialogue: 0,0:00:00.60,0:00:01.20,YellowStrokeFollow,,0,0,0,,{\xshad6\yshad0}SURVIVING THE {\1c&H0000F0FF&}APOCALYPSE{\1c&H00FFFFFF&}

样式 3:蓝绿渐变跟读

; 目标视觉:当前词蓝绿渐变底块
; #118dff -> &H00FF8D11,#18d39e -> &H009ED318
Style: BlueGreenHighlightFollow,Montserrat,70,&H00FFFFFF,&H00FFFFFF,&H00000000,&H00FF8D11,-1,0,0,0,100,100,0,0,1,3,0,5,0,0,0,1

; ASS 绘图层不天然支持 CSS 渐变:
; 方案 A:用多段窄矩形模拟渐变;方案 B:降级为单色底块。
Dialogue: 0,0:00:00.00,0:00:00.80,BlueGreenHighlightFollow,,0,0,0,,{\an2\pos(360,1040)\p1\bord0\shad0\1c&H00FF8D11&}m 0 0 l 90 0 90 64 0 64{\p0}
Dialogue: 0,0:00:00.00,0:00:00.80,BlueGreenHighlightFollow,,0,0,0,,{\an2\pos(450,1040)\p1\bord0\shad0\1c&H009ED318&}m 0 0 l 90 0 90 64 0 64{\p0}
Dialogue: 1,0:00:00.00,0:00:00.80,BlueGreenHighlightFollow,,0,0,0,,{\xshad0\yshad0}TILES SURVIVE DOWNLOAD IT

样式 4:逐词跳出

; 每个时间片只显示当前词,不显示整句
Style: SingleWordPop,Montserrat,70,&H00FFFFFF,&H00FFFFFF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,4,0,5,0,0,0,1

; 基础版本:逐词 Dialogue
Dialogue: 0,0:00:00.00,0:00:00.40,SingleWordPop,,0,0,0,,{\xshad0\yshad0}IT
Dialogue: 0,0:00:00.40,0:00:00.80,SingleWordPop,,0,0,0,,{\xshad0\yshad0}SURVIVES

; 可选增强:后端评估 \fscx / \fscy / \t 做轻微弹出
Dialogue: 0,0:00:00.00,0:00:00.40,SingleWordPop,,0,0,0,,{\xshad0\yshad0\fscx112\fscy112\t(120,260,\fscx100\fscy100)}IT

多语种黑底预览

下图由 ffmpeg + ASS 实际渲染生成,用于校准四种预设在多语种文本下的视觉效果。
ASS 多语种黑底预览
英语
TILES SURVIVE
BUILD YOUR CAMP
英语
SURVIVING THE
FROZEN STORM
英语
DOWNLOAD IT
PLAY TODAY
英语
NOW
法语
SURVIS MAINTENANT
BÂTIS TON CAMP
法语
SAUVER LE
CAMP FORT
法语
JOUE LE
JEU
法语
VITE
德语
ÜBERLEBE JETZT
BAUE DEIN LAGER
德语
BAUE DAS
STARKE LAGER
德语
LADE ES
HEUTE
德语
LOS
俄语
ВЫЖИВИ СЕЙЧАС
СТРОЙ СВОЙ ЛАГЕРЬ
俄语
ПОСТРОЙ СВОЙ
ПРОЧНЫЙ ЛАГЕРЬ
俄语
СКАЧАЙ ИГРУ
ИГРАЙ СЕЙЧАС
俄语
ВПЕРЁД
阿拉伯语
انجُ الآن
ابنِ مخيمك
阿拉伯语
احمِ المخيم
واجه الخطر
阿拉伯语
حمّل اللعبة
والعب الآن
阿拉伯语
الآن
日语
今すぐ生き残れ
基地を守れ
日语
基地を守れ
敵を倒せ
日语
ゲームをダウンロード
今すぐ遊べ
日语
韩语
지금 살아남아라
기지를 지켜라
韩语
기지를 지켜라
적을 막아라
韩语
게임을 다운로드
지금 플레이
韩语
지금

四、不同尺寸的大小示意

下面用黑底示意不同尺寸下的默认字号和位置。截图均由 ASS/libass 实烧生成,并统一按 iPhone 16 的 393px CSS 视口宽度展示:不同视频在同一手机宽度下,高度随画幅比例变化;字幕不强制在手机预览中等大,常见画幅默认基础字号统一为 70。当前实烧示意的两行中心间距按字号 x 1.1。

720x1280 ASS 实烧截图
9:16 720p
真实视频 720x1280
iPhone 16 宽度示意:393x699
导出对应:70 字号,行距 1.1
底块高度约 60
1080x1080 ASS 实烧截图
1:1 1080
真实视频 1080x1080
iPhone 16 宽度示意:393x393
导出对应:70 字号,行距 1.1
底块高度约 60
1280x720 ASS 实烧截图
16:9 1280
真实视频 1280x720
iPhone 16 宽度示意:393x221
导出对应:70 字号,行距 1.1
底块高度约 60
1000x800 ASS 实烧截图
5:4 1000
真实视频 1000x800
iPhone 16 宽度示意:393x314
导出对应:70 字号,行距 1.1
底块高度约 60
画幅族 识别规则 字号规则 位置和底块规则
竖屏 宽高比小于等于 0.72 默认基础字号 70。 底行中心距底:长边 x 16.4%;两行中心间距约为字号 x 1.1;高亮底块高随字号缩放。
横屏 宽高比大于等于 1.4 默认基础字号 70;横屏主要通过更多朗读单元和更宽安全区适配。拉丁语系/俄语可先按 6 个词试排,阿语可先按 7-8 个朗读单元试排。 底行中心距底:短边 x 15.7%;左右安全区:长边 x 8%,且不超过宽度 24%。
方屏 宽高比 0.9 到 1.1 默认基础字号 70。 底行中心距底:长边 x 15.5%;左右安全区:长边 x 9%。
中间比例 例如 4:5、3:4、5:4 默认基础字号 70。 左右:短边 x 8%;底行中心距底:偏竖长边 x 16%,偏横长边 x 12.8%。

五、服务端处理链路

这部分属于后端烧制前的数据处理和 ASS 生成逻辑,不是单纯调 ASS Style 参数即可完成。核心原则是:文本处理、分行、词级时间轴、RTL/Bidi、测量和降级都在服务端先算好,ASS 负责最终绘制和烧制。

1. 视频和画幅参数

  • 读取视频真实宽高,设置 PlayResX / PlayResY 等于真实分辨率,并按宽高比归入竖屏、横屏、方屏或中间比例。
  • 按画幅族得到默认字号、底部位置、左右安全边距、每行最多朗读单元数和最大行数;这些是自动默认值,用户或 agent 可继续覆盖。
  • 所有位置、边距、字号都按真实像素写入 ASS,不用前端预览尺寸反推;同一比例不同清晰度时,规则按真实分辨率换算。

2. 语言和字体映射

  • 先确定字幕语种或脚本类型,再选择字体映射:拉丁语系/俄语优先 Montserrat Bold 700,中文/日韩优先映射 Source Han Sans 对应字重;阿语使用常规字重,不指定 Cairo,ASS 中可用 Montserrat Regular + Bold=0,再由服务端映射到稳定的阿语常规字重兜底字体。
  • ASS 的 Fontname 只能写单个字体名;多语种 fallback 不能只依赖前端 CSS 字体链,服务端需要明确字体安装、字体文件分发和 fallback 顺序。
  • 本地预览验证过:Montserrat 不包含阿语字形,libass 会 fallback 到系统阿语字体;生产环境不能依赖不确定的系统 fallback,需要随服务端包固定字体文件并在测量和烧制时使用同一套字体。
  • 最终字体确定后再做 libass 测量;不同字体的字宽、基线和 bbox 都会影响分行、高亮底块位置和圆角框尺寸。

3. 朗读单元切分

  • 英语、法语、德语、俄语等空格语种按词切分;标点符号绑定到前一个朗读单元,避免高亮时标点单独跳动。
  • 中文、日语、韩语等无空格或弱空格语种不能直接按空格切;需要语种分词器或上游 ASR 词级时间戳生成可高亮单元。
  • 日语预览不应人为插入英文式空格;如需要跟读,应按日语词法单元、假名/汉字短语或上游时间戳单元高亮,否则可降级为短语级高亮。
  • 日语的“每行多少内容”不使用最多单词数;建议先设显示字符数软上限,再用 libass 实测宽度兜底:竖屏约 10-12 个日文显示字符,方屏/中间比例约 12-16 个,横屏约 18-22 个。促音、长音、标点跟随前一单元,不能单独成行。
  • 阿语保持原始逻辑文本顺序,不手动倒序 token;高亮时间轴按朗读顺序推进,视觉排版交给 Bidi/shaping 引擎。
  • 阿语的空格词不能和英语词数一一等价:冠词、连词、介词常与词根粘连,横向视觉宽度也会随字体和连写变化。默认可比英语略放宽,竖屏约 4-5 个朗读单元,方屏/中间比例约 5-6 个,横屏约 7-8 个;仍由 libass 实测宽度兜底。

4. RTL / Bidi 处理

  • 阿语、希伯来语等 RTL 文本应在 Dialogue 文本层明确段落方向,例如使用 Unicode RTL 隔离/嵌入控制符,避免混入数字、英文或 ASS 标签时被误判为 LTR。
  • 当前词索引用朗读逻辑顺序计算:第一个朗读词在阿语行里通常显示在最右侧,因此视觉上应从右往左推进。
  • 不要为了视觉从右到左而把词数组反转;反转会破坏语义顺序、时间戳对应和标点归属。
  • RTL 行内不要用 ASS 标签把当前词透明隐藏再单独叠字,这会改变 Bidi 分段,导致高亮变化时整行词序跳变;推荐保持整行文本原样稳定渲染,只移动当前词背后的高亮底块。
  • RTL 当前词 bbox 建议用整行实测宽度和右侧累积宽度计算:先测整行宽、当前词宽和从第一个朗读词到当前词的累计宽度,再从行右边界反推当前词中心点。
  • 词距策略需按语种区分:拉丁语系可用额外空格让短视频字幕更疏;阿语默认使用正常空格,避免破坏连写、阅读节奏和 bbox 测量。

5. 分行和窗口切片

  • 每个字幕窗口最多 2 行;逐行试排时先检查最多单元数,再用 ASS/libass 测量候选行宽。
  • 候选行宽必须小于 PlayResX - 左右安全边距 - 描边/底块余量;超出就提前换行,2 行放不下则切到下一字幕窗口。
  • 当前实烧脚本会批量生成候选行并用 ffmpeg/libass 渲染测宽,避免只按词数断行导致文字越过可视区域。
  • 横屏可以允许更多单元数,但仍以实际可显示宽度为硬约束;不能只按“每行 6 词”强排。阿语横屏建议先给 7-8 个朗读单元的软上限,再由测宽结果决定是否提前换行。
  • 如果单个词或短语过长导致无法放入安全区,按优先级降级:减少当前窗口单元数、轻微缩小字号、轻微压缩 ScaleX、按语种规则拆分长词或切到下一窗口。

6. 高亮底块和烧制

  • 圆角高亮底块不是 ASS 原生背景能力;需要先用 libass 渲染测量当前词 bbox,再按 bbox 生成 ASS 绘图层。
  • 当前紫色底块基准为:字号 70 时底块高约 60,圆角约 10;尺寸随字号等比缩放,并以当前词 bbox 水平宽度为准。
  • 非 RTL 语种可把高亮词单独绘制一层,并将原行里的当前词透明隐藏,避免两层文字重影;RTL 语种保持整行文本不变,只移动底块,避免 Bidi 顺序跳变。
  • 最终 ASS 主要负责字体、字号、描边、阴影、显式定位、绘图底块和时间轴;分词、断行、RTL、词距近似、长词降级都属于烧制前的数据处理。
  • 每次修改字体、字号、描边、词距或画幅策略后,都需要重新测量 bbox 并生成 ASS,不能复用旧的底块坐标。

六、前端 GUI 计划

本需求的四种预设样式和其他字幕参数修改,统一要求服务端 ASS 能力支持。用户可在提交任务时要求指定样式,也可对生成结果继续通过右侧对话让 agent 微调。

后续前端计划提供面向用户的简易 GUI 表单,通过提交结构化参数到服务端完成调整。GUI 范围和结构化提交说明见 字幕 GUI 简化配置说明