如何使用 ffmpeg 在视频中的任意位置显示大量字幕?
Posted
技术标签:
【中文标题】如何使用 ffmpeg 在视频中的任意位置显示大量字幕?【英文标题】:How can I display lots of subtitles at arbitrary positions in a video using ffmpeg? 【发布时间】:2021-09-25 15:14:33 【问题描述】:我正在尝试编写字幕并将其显示在视频中任意位置的多个位置。我有一长串时间和位置来显示视频中的文本,但我不知道如何将这些时间和位置编码到字幕文件中。网上的很多例子只展示了如何显示单个字幕,或者没有解释字幕文件的语法。
我找不到一个简单的答案来解决这个问题,所以我不得不把很多方法放在一起,我要回答我自己的问题。
【问题讨论】:
【参考方案1】:这样做的主要选项是:
使用 GUI/独立程序(@llogan 提到了aegisub) ffmpeg 中的“drawtext”过滤器 带有 SRT 文件的字幕过滤器 带有 SSA 文件的字幕过滤器 带有 ASS 文件的字幕过滤器我想在文本文件中编写自己的字幕(使其可编写脚本),而不是使用独立的 GUI。一些方法不允许任意定位(字幕总是在底部居中)。其他人不允许从文件中加载一长串字幕,即您必须将它们全部编码到 ffmpeg 命令字符串中,这很笨拙。
这里是字幕过滤器上的documentation,但它实际上并没有解释随附文件的语法。事实上,我发现很难找到任何字幕文件选项的清晰文档。我选择了 ASS,因为它似乎可以工作,而且我在互联网上发现了足够多的模板,我能够通过反复试验找出最重要的功能。
首先,创建一个名为 desc.ass
的文本文件,如下所示:
[Script Info]
PlayResY: 600
WrapStyle: 1
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, Alignment, MarginL, MarginV
Style: N,Arial,60,&H00FFFF,1,425,550
Style: NE,Arial,60,&H00FFFF,1,650,480
Style: E,Arial,60,&H00FFFF,1,700,250
Style: SE,Arial,60,&H00FFFF,1,600,50
Style: S,Arial,60,&H00FFFF,1,400,0
Style: SW,Arial,60,&H00FFFF,1,150,50
Style: W,Arial,60,&H00FFFF,1,100,250
Style: NW,Arial,60,&H00FFFF,1,150,500
[Events]
Format: Start, End, Style, Text
Dialogue: 00:00:01.00, 00:00:05.00, E, Text to display with the E style
Dialogue: 00:00:05.00, 00:00:05.50, N, Text to display with the N style
实际文件在此之后还有很多“对话”行,但为了便于阅读,我截断了。
我还不太了解Script Info
部分。 :(
V4+ Styles
部分允许您指定任意数量的“样式”,用于定义颜色、位置、字体和许多其他内容。每个实际的字幕都将使用其中一种样式。
如果每个字幕显示的位置很少,我认为为每个位置定义一个样式会更容易。因为我想在 8 个位置之一显示字幕,所以我定义了 8 种样式。但是您可以覆盖任何给定字幕的位置(见下文)。所以另一种选择是对所有内容使用单一样式,并根据需要定义每个字幕的位置。
PrimaryColour
是一个十六进制颜色参数(尽管由于某种原因它似乎是倒退的,所以黄色给你青色,反之亦然)。
Alignment
refers to the numerical keypad,所以 1 表示左下,5 表示中间。
MarginL
和 MarginV
允许您将水平和垂直偏移应用到默认对齐方式。
您可以在这里指定更多属性,只需将元素添加到Format
行,然后在每个Style
行上指定它们。 This page is the most comprehensive documentation I could find.
互联网上的每个人都复制/粘贴具有许多指定格式的相同示例文本(例如,here)。 This 是另一个更简单的例子。如果有人可以发布关于这些属性的含义的清晰文档,那就太好了!
[Events]
部分定义了各个字幕。在这里,我只指定基本信息:开始时间、结束时间、样式名称和文本。
您可以通过将字符串\pos(400,570)
添加到该行的Text
元素的开头来对任何给定的Dialogue
元素进行override the position。 (显然将 400、570 替换为您想要的位置。)
您可以使用ffplay
预览将这些字幕应用于名为video.mkv
的视频的结果,如下所示:
ffplay -i video.mkv -vf "subtitles=desc.ass"
有些人称之为软字幕,因为视频本身并没有被改变,字幕只是显示在它上面。
如果您想将字幕永久刻录到视频中(有时称为硬字幕),您可以像这样重新编码:
ffmpeg -i video.mkv -vf "subtitles=desc.ass" video_with_subtitles.mkv
Ref for burning subtitles
【讨论】:
值得一提的是aegisub是一个用于创建ASS文件的GUI程序。以上是关于如何使用 ffmpeg 在视频中的任意位置显示大量字幕?的主要内容,如果未能解决你的问题,请参考以下文章
FFmpeg本地任意文件读取漏洞 / FFmpeg Local arbitrary file read vulnerability