如何让 ASS 字幕中的单词一次出现一个?

Tha*_*Don 4 ffmpeg video-processing subtitle

我正在尝试将字幕刻录到视频中,以便它们以逐字方式出现,而不是一次全部出现。

我的意思是,一个词会出现,然后另一个词会出现在它旁边,依此类推。最终线路将清除,然后重复。

例子:

一段视频显示一个人在谈论国际象棋。 屏幕底部的字幕显示“获胜”。 片刻之后,字幕变为“中奖”,然后是“中奖”,然后是“现在中奖”等等。 每个连续的单词立即完整地出现,但每个单词只有在说话者说出来时才会出现。

我想我可以创建一个Advanced Substation Alpha文件,其中字幕共享相同的结束时间但不同的开始时间,但是 FFMPEG 在渲染文件时似乎不能很好地处理:

[Script Info]
; Script generated by FFmpeg/Lavc57.107.100
ScriptType: v4.00+
PlayResX: 384
PlayResY: 288

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,1,1,0,2,10,10,10,0

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:03.46,Default,,0,0,0,,I'm
Dialogue: 0,0:00:01.00,0:00:03.46,Default,,0,0,0,,a
Dialogue: 0,0:00:01.50,0:00:03.46,Default,,0,0,0,,subtitle
Run Code Online (Sandbox Code Playgroud)

这个想法I'm会出现,然后 1 秒后a会出现在它旁边,然后subtitle是半秒后

Cho*_*s-2 5

您走在正确的轨道上,但您现在所做的是创建新的文本。事实上,它们会并排显示,但它们会垂直堆叠,这不是您想要的。

具有重复文本的多个事件

要将单词添加到同一行,您需要在下一个单词必须出现时停止上一个 Dialogue 事件,并在下一个 Dialogue 事件中重复整个可见文本:

Dialogue: 0,0:00:00.00,0:00:01.00,Default,,0,0,0,,I'm
Dialogue: 0,0:00:01.00,0:00:01.50,Default,,0,0,0,,I'm a
Dialogue: 0,0:00:01.50,0:00:03.46,Default,,0,0,0,,I'm a subtitle
Run Code Online (Sandbox Code Playgroud)

如果文本居中或(对于从左到右书写的语言)右对齐文本,或者如果您的文本太长它会自动环绕并显示在多行上,您每次都需要指定整个文本所以对齐和换行计算在每个事件上的工作方式相同,但通过将文本完全透明来使文本中不可见的部分实际上不可见:

Dialogue: 0,0:00:00.00,0:00:01.00,Default,,0,0,0,,I'm {\alpha&HFF}a subtitle
Dialogue: 0,0:00:01.00,0:00:01.50,Default,,0,0,0,,I'm a {\alpha&HFF}subtitle
Dialogue: 0,0:00:01.50,0:00:03.46,Default,,0,0,0,,I'm a subtitle
Run Code Online (Sandbox Code Playgroud)

这是通常的做法。

带有覆盖标签的单个事件

或者,如果您的文本没有边框/轮廓和阴影(示例视频中并非如此),您可以通过将尚未播放的文本颜色 ( SecondaryColour) 设置为完全透明来使用 ASS 卡拉 OK 标签:

Dialogue: 0,0:00:00.00,0:00:03.46,Default,,0,0,0,,{\2a&HFF\k100}I'm {\k50}a {\k196}subtitle
Run Code Online (Sandbox Code Playgroud)

如果您确实有边框或阴影(如示例视频中所示),那么简单的卡拉 OK 是不够的,因为您还想修改边框/阴影颜色。你可以使用 ASS 的通用动画标签来做到这一点\t

Dialogue: 0,0:00:00.00,0:00:03.46,Default,,0,0,0,,I'm {\alpha&HFF\t(1000,1000,\alpha0)}a {\alpha&HFF\t(1500,1500,\alpha0)}subtitle
Run Code Online (Sandbox Code Playgroud)

在这里,对于除第一个以外的每个单词,当事件开始时,我将所有 alpha 值设置为完全透明,然后在该单词出现时立即将其切换为完全不透明。

关于从右到左文本的注意事项

问题中没有任何迹象表明您打算将它用于除从左到右的英文文本之外的任何内容,但这仍然值得谨慎对待。(您甚至可能认为现在假设这种区别无关紧要是很自然的。不幸的是,由于过去的一些错误决定和习惯,它仍然存在。)

如果您使用从右到左的文本(例如阿拉伯语或希伯来语)尝试这些方法中的任何一种,除了没有覆盖标签的第一种最简单的方法,您会发现 VSFilter 和 libass,两个主要的 ASS 渲染器,显示文本不同的是:libass 将使用与没有任何标签的单行相同的词序,但 VSFilter 将在覆盖标签处拆分文本并重新排序各部分,以便前面的部分始终位于后面部分的左侧

即使在没有任何覆盖标记的最简单的情况下,如果您的文本以某些标点符号(或其他方向中性字符)开头或结尾,它们将与文本的自然方向不匹配并显示反转。

目前没有适当的“解决方案”,但您可以通过在覆盖标签周围插入 Unicode 双向控制字符来解决这些差异,以使 libass 匹配 VSFilter 的顺序(这不是自然文本顺序)并强制任何开始/结束 -离线标点符号从右到左。

当然,如果您只是刻录字幕而不打算分发字幕文件,那么您不必担心它们在其他渲染器中的外观。FFmpeg 使用 libass。但是,libass 的行为可能会在未来的某个时候进行调整以匹配 VSFilter,因为 VSFilter 传统上拥有最大的市场份额(从 libass 甚至不存在的时候开始),并且大多数(如果不是全部)阿拉伯语字幕存在的文件实际上依赖于它对从右到左文本的错误处理,并要求它产生正确的输出。