前言
FFmpeg 是一个强大的多媒体处理工具,但过多的参数很容易劝退人。其实它的使用并没有想象的麻烦,例如通过它管理视频的字幕是很方便的,也很容易理解。
本文将告诉你应该怎么做。 这是一篇 新手向教程 。过程十分简单!
在往下阅读前,你最好掌握一些基本的 FFmpeg 参数含义和用途。
本文的命令多次使用
-i
参数,它表示输入文件,即我们要操作的文件。当存在多个输入时(例如视频文件、字幕文件)就会有多个
-i
参数。
本文的命令多次使用
-c
参数,它用于指定编码器。但由于操作字幕通常是无需重新编码的,所以使用
copy
这个特殊值,它表示直接复制而不涉及编码。
因为没有重编码过程,所以速度通常非常快。它基本上只是流的复制和容器格式的重新封装。
流选择/映射
本文的命令多次使用
-map
参数,它用于选择流并将其映射到输出。例如
-map 0
表示将第一个输入文件的
所有流
映射到输出,
-map 0:a
表示将第一个输入文件的
音频流
映射到输出。或者更具体一点如
-map 0:a:0
表示将第一个输入文件的
第一个音频流
映射到输出。
映射可以指定多个,它是本文的核心参数。
字幕元数据
字幕可以通过
--metadata:s:s:[i]
参数设置元数据,其中
[i]
表示字幕流的索引。不同的字幕格式可能有不同的元数据,本文的重点在于设置字幕的
language
和
title
。前者基本上是必要的,它表示字幕的语言,而后者是可选的,它表示字幕的标题。
为了便于理解,后文普遍会将「索引」称作「位置」。
标题在本文被用于展示语言名称,如 Simplified Chinese(简体中文)。
本章节会列举添加字幕的方法,你需要提前准备好字幕的
.srt
文件,并将其命名为
chi.srt
。
此处的
chi
是一个语言代码,是符合 ISO-639-2 规范的代表「中文」的标准值。
在下面的过程中,我会将原视频命名为
input.mkv
,输出的视频命名为
output.mkv
。如果你使用 MP4 格式,可参考
输出为 MP4
章节。
这是最简便的方式,我们直接将字幕插入到最前面,作为第一个流(或者叫轨道)。执行如下 FFmpeg 命令:
ffmpeg -i input.mkv -i chi.srt \
-c copy \
-map 1:s -map 0 \
-metadata:s:s:0 language=chi \
-metadata:s:s:0 title="Simplified Chinese" \
-disposition:s:s:0 default \
output.mkv
注意它同时设置了与中文相关的字幕元数据并作为默认字幕。这个命令的优势是,我们无需事先知道原视频中有多少字幕流,因为我们始终把字幕添加到第一个位置,原有的流向后移动。
这样造成的问题是,视频文件不再按照传统的
视频 -> 音频 -> 字幕
顺序排列流,变成了
字幕 -> 视频 -> 音频 -> 字幕
。这一般不会对视频的播放造成影响,但不排除有软件是按照流的固定位置(如第一个一定是视频)来解析视频文件。如果你认为存在隐患,那么可以使用下面的方法将字幕添加到最后。
要想把字幕添加为末尾的流,得获取原视频的字幕流数量。执行如下命令:
ffprobe -v error -show_entries stream=codec_type -of default=nw=1:nk=1 input.mp4 | uniq -c
输出如下(留意
subtitle
左边的数字):
1 video
1 audio
2 subtitle
这表示视频文件中有 1 个视频流、1 个音频流和 2 个字幕流。所以我们指定新字幕的位置为
2
即可:
ffmpeg -i input.mkv -i chi.srt \
-c copy \
-map 0 -map 1:s \
-metadata:s:s:2 language=chi \
-metadata:s:s:2 title="Simplified Chinese" \
-disposition:s:s:2 default \
output.mkv
位置从
0
开始数,因为原视频有 2 个字幕,所以是位置是
0+2
(其实就等于字幕数量)。注意以上命令的
-metadata:s:s:[i]
和
-disposition:s:s:[i]
是需要替换值的部分,如果
[i]
搞错会错误的修改原有字幕的元信息而不是新字幕。
此处介绍的方法是「插入(头部)」或「追加(尾部)」字幕到原视频中,原有的字幕仍然保留。如果你想替换掉原有字幕,请参考 替换字幕 章节。
删除字幕的方法相对简单。我们仅需指定需要保留的流,或需删除的流即可。删除前记得用
ffmpeg -i input.mkv
查看原视频的流信息,让自己了解原视频的字幕数量和对应位置。
删除全部字幕
删除全部字幕无需在意原视频信息,直接执行:
ffmpeg -i input.mkv -map 0:v -map 0:a -c copy output.mkv
以上命令将保留原视频的视频和音频流,但不保留字幕流。即达到删除全部字幕的目的。
删除特定字幕
首先我们用
-map 0
选中所有流,然后指定需要排除的字幕流即可。比如我们要删除第二个和第三个字幕:
ffmpeg -i input.mkv -map 0 -map -0:s:1 -map -0:s:2 -c copy output.mkv
注意不要忘了,我之前提到过位置以
0
开始。所以此处的
0:s:1
表示第二个字幕而不是第一个,后面的
0:s:2
同理。
保留特定字幕
我们依然用
-map 0
选中所有流,然后指定需要保留的字幕流即可。比如我们仅保留第一个流:
ffmpeg -i input.mkv -map 0 -map 0:s:0 -c copy output.mkv
注意到区别了吗?删除字幕的参数值
-0:s:1
多了一个
-
前缀,没有
-
即表示保留。通常保留特定字幕的目的也是为了删除字幕,例如字幕实在太多指定删除会很麻烦。保留只是删除的思维反转。
替换字幕实际上是以上操作的综合。替换的逻辑是,在添加字幕的同时删除或仅保留特定字幕。替换可能是大多人会考虑的做法,尤其是从国外知名 BT 网站下载的视频。因为它总是包含很多语言的字幕,却可能缺失中文。
假设我们不在意原视频中的字幕,仅需我们自己添加的字幕。那么:
ffmpeg -i input.mkv -i chi.srt \
-c copy \
-map 0:v -map 0:a -map 1:s \
-metadata:s:s:0 language=chi \
-metadata:s:s:0 title="Simplified Chinese" \
-disposition:s:s:0 default \
output.mkv
在这个例子中,我仅选中了新字幕以及原有的视频流和音频流,所以只会保留我们新增的字幕。这样就达成了一个命令添加新字幕并替换掉所有字幕的目的。
假设我们的原视频有 2 个字幕流,我们用新字幕替换掉原来的第二个字幕(位置
1
)。如下:
ffmpeg -i input.mkv -i chi.srt \
-c copy \
-map 0 -map 1:s -map -0:s:1 \
-metadata:s:s:1 language=chi \
-metadata:s:s:1 title="Simplified Chinese" \
-disposition:s:s:1 default \
output.mkv
这次我们选中了所有字幕(包括新字幕),但排除掉位置为
1
的字幕。因为我们提前知道字幕的数量,所以编辑字幕
1
的元数据(因为排除掉原字幕后新字幕会在这个位置,而不是
2
)。这样就达成了替换特定字幕的目的。
如果我们进一步扩展命令使用
-map
排除或保留更多,就可以实现删除多个字幕流的目的。但要注意新字幕的位置,它会随着删除的字幕数量而变化(原字幕数量减去删除的字幕数量)。
明确知道删除了多少字幕流很重要
。
移除默认字幕标识
如果原有字幕已经存在默认标识了,但又想把新增的字幕设置为默认,可以清除原字幕流的配置。如果存在多个默认流配置,选择哪个字幕是不一定的(看播放器行为)。
假设我们保留第一个原字幕,但移除它的默认流标识。操作如下:
ffmpeg -i input.mkv -i chi.srt \
-c copy \
-map 0 -map 1:s \
-metadata:s:s:1 language=chi \
-metadata:s:s:1 title="Simplified Chinese" \
-disposition:s:s:1 default \
-disposition:s:s:0 0 \
output.mkv
注意新增的
-disposition:s:s:0 0
参数,它会清除第一个字幕流的配置。注意
s:s:0
是指定字幕位置,参数值
0
才表示清除。这样就只有新字幕被设置为默认。
输出为 MP4
以上的例子全部使用 MKV 容器格式,默认情况下这些参数不一定能输出为其它容器格式。例如导出为 MP4 时需要指定为字幕为
mov_text
格式,并且
mov_text
不支持
title
元数据。
但保留命令参数是无害的,虽然播放器看不到字幕标题。
具体如下:
ffmpeg -i input.mkv -i chi.srt \
-c copy \
-c:s mov_text \
-map 0 -map 1:s \
-metadata:s:s:1 language=chi \
-metadata:s:s:1 title="Simplified Chinese" \
-disposition:s:s:1 default \
output.mp4
注意新增的
-c:s mov_text
参数,它会将原视频的所有字幕转换为
mov_text
格式。也许有人会问,你仅指定新字幕为
mov_text
不就行了,为什么要影响其它字幕?好问题,因为 MKV 容器中的其它字幕可能是
SubRip
等 MP4 不支持的格式,如果不转换全部字幕就会失败。
字幕标题显示(mov_text 并不支持):
这就是用 FFmpeg 操作视频字幕的方法了。对于有一定经验的 FFmpeg 用户,通过本文你应该能自由的管理字幕了。如果是纯小白,可能仍只能照猫画虎,我建议使用更低门槛的图形化工具(虽然我没有推荐的)。
MPV 是一个怎样的播放器?一文带你认识 MPV
前言 很多 Windows 用户经常过度吹捧一些平凡的商业软件(例如 PotPlayer),将其称作宇宙最强什么的。一般他们并不知道 Linux/Mac 用户使用什么,也不会了解到开源领域里那些从不营销但实际强大得多的软件产品。本文的主角 MPV 就是开源世界著名的视频播放器,它虽有门槛但总体仍是易
自建照片/视频管理方案(Immich 的部署和使用)
前言 Immich 是一个开源的照片/视频管理方案,它的功能和用途类似于 Google 相册或 iCloud 照片。任何个人都可以利用 Immich 搭建自己私有的云同步相册,并支持多端/多人使用。 本文将告诉你怎么部署。这是一篇新手向教程。过程十分简单! 效果 过程 建议使用内网的路由器/软路由或
喵星 ICP 备案系统介绍
前言 最近收到某个神秘组织的委托,让我开发一套面向喵星的网站备案系统。在遥远的喵星,有一种高度智慧的猫科文明——喵星人。它们通过访问部署在地球的网站了解地球人。其实地球上存在着大量喵星驻地球大使馆,但都隐藏极深。而近期联系我的就是附近某个使馆中的神秘喵星人,更多的不能再说了。 喵星与互联网 在中文网