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

标签 ffmpeg video-processing subtitle

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

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

例子:

A video shows a person speaking about chess. Subtitles at the bottom of the screen say “winning”. Moments later, the subtitles change to “winning a”, then “winning a piece”, later “winning a piece now” and so on. Each consecutive word instantly appears in whole, but each word only appears when the speaker says it.

我以为我可以创建一个 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

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

最佳答案

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

具有重复文本的多个事件

要将单词添加到同一行,您需要在下一个单词必须出现时停止上一个 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

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

这是通常的做法。

带有覆盖标签的单个事件

或者,如果您的文本没有边框/轮廓和阴影(示例视频中不是这种情况),您可以通过将尚未唱的文本颜色 (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

如果您确实有边框或阴影(如示例视频中所示),那么普通卡拉 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

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

注意从右到左的文本

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

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

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

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

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

关于ffmpeg - 如何让ASS字幕中的单词一次出现一个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60608765/

相关文章:

ffmpeg - 有关 ffmpeg 的信息,如果有的话,它使用什么算法

audio - FFMPEG - 无法使用 av_write_frame() 生成 aac 音频文件

android - FFMPEG sws_scale 在 Android 上崩溃

android - 如何减少 flutter 中的视频录制大小?

image-processing - 从视频中提取中文字幕

JavaScript - 生成 .SRT 文件

php - 在 linux 的 ffmpeg 中找不到预设 'slower' 的文件

image-processing - 为什么 YUV <-> RGB 中的常数被选择为它们现在的值

保存图像时JavaCV EXCEPTION_ACCESS_VIOLATION

python-3.x - 如何使用帧单元制作 TIME 字幕(.srt、.smi 等)