2024-02-06

MKV 文件的字幕播放问题

很多网上下载的影片都是 MKV 格式,而 MKV 是一种容器格式,可以把不同类型的媒体放到容器中。家里新买的电视,已经自带了市面上各种通用的解码器,并且可以读取 MKV 文件中的字幕,唯一一个问题是无法读取外挂的字幕文件。把字幕带上音视频文件一起存到 MKV 文件中即可以很好的解决这个问题。

智能电视

记得十多年前就买过一台“智能电视”。当时的电视已经开始使用 Android 的系统,开机自动载入电视的 App ,然后有自己的 App 商城,甚至可以外装 App 来扩展电视的功能。本质上除了屏幕大和需要使用遥控器之外,“智能电视”和一台 Android 手机在使用上并没有特别的差别。

但在当时,若想用电视来播放本地的电影文件,仍然是一件非常困难的事情。因为视频格式的编码繁多,多数的流行的视频格式都无法直接用电视进行解码,而商城里也没有合适的 App 可以做解码工作。再加上其 CPU 性能也不高,所以只能外接电脑,将电视机做为一台显示器的方式来播放本地电影。

字幕问题

最近搬家后,买了新的电视,仍然是 Android 系统,屏幕更大(98寸),CPU 更快。并且惊奇地发现,电视内置的播放器已经支持市面上流行的视频编码格式了,像 MKV 这种视频容器格式也能被很好地支持,存储在 MKV 里的字幕可以被很好地显示出来。唯一的缺点是,在播放的时候不会自动搜寻并载入外挂字幕文件。

可是并不是每部电影都内嵌了中文字幕,可以说在 90% 的情况下,我都是外挂中文字幕的方式来看电影的。要解决中文字幕的问题,有三个办法:

  • 安装第三方的 App 来支持,例如 VLC;

  • 手动将外挂字幕嵌到 MKV 文件中;

  • 外接电脑,将电视变成一台大号的显示器;

最开始尝试在电视机里安装第三方 App,尝试了几种方法,都没有成功,也没有找到官方的能安装 App 的商城。可能电视机厂商为了降低电视出问题的机率,把这些接口都关掉了。而我非常地不愿意通过外接电脑的方式来播放电影,占用地方不说,有时候还得上鼠标和键盘来进行操作。

MKV 字幕合并

可以把 MKV 文件想象成一个容器,所有的对象(包括一个或多个的视频,音轨,字幕等)都保存在容器中,每个容器都被用一个独立的序号(index)来标识,该序号从 0 开始。比如,视频对象一般序号值为 0 (index=0),音轨通常从 1 开始,字幕排在音轨之后。

简单做个调研,MKV 相关的工具有一个叫做 mkvtoolnix,是一个开源的,Linux 下的工具,提供了 mkvmergemkvextractmkvinfo 等一些相关的 commands。看字面就很容易知道,mkvmerge 用于合并文件到 MKV 文件中,而 mkvextract 自然就是从 MKV 中提取文件,而 mkvinfo 则是用于读取 MKV 文件的基本信息。这些命令的功能繁多,经过一番抽丝拔茧,最简单的合并字幕的命令是:mkvmerge --default-language chi -o [输出文件.mkv] [源文件.mkv] [字幕文件.srt]。其中使用 --default-language chi 来指定这个新的字幕文件的语言为“中文”。命令输入后需要等待一段时间,系统会把源文件中的视频,音频连同新的字幕一起拷贝到输出文件中。

选择音轨

之前有播放一部俄文的电影,发现这部电影虽然带有英文的音轨,但是其默认是播放俄文的音轨。虽然电视的播放器可以选择英文音轨,但是我仍然希望在播放影片时,默认载入英文的音轨。既然 MKV 文件中的字幕可以调整,那么音轨也一定是可以的。这里需要用到 mkvextractmkvinfo 命令。思路就是:

  1. 找到英文音轨;

使用命令:mkvinfo [源文件.mkv] 可以获得该 MKV 文件信息,包括所有的对象及对应的序号。也可以使用播放器播放该 MKV 文件,然后在播放器中查找对应的音轨序号。

  1. 将英文音轨提取出来;

例如,我们在上一步骤中找到了对应的音轨的序号为 8,于是使用命令:mkvextract [源文件.mkv] tracks 8:audio 会将序号为 8 的对象从源文件中提取出来并保存至当前目录下,新创建的文件名称为 audio。

  1. 将视频提取出来;

同上面的步骤,我们将序号为 0 的对象提取出来并保存到文件名为 video 的文件中,使用命令:mkvextract [源文件.mkv] tracks 0.video

  1. 将英文音轨和视频以及字幕合并到新的 MKV 文件中;

上述的步骤已经将视频,音轨提取出来了,假设我们要合并的字幕文件为 subtitle.srt,可以执行命令来进行合并:mkvmerge --default-language chi -o [新的文件.mkv] video audio subtitle.srt。稍等片刻,合并好的 MKV 将可以直接拿到电视上播放,音轨,字幕和视频都被正确显示出来。

字幕格式

有些电视为了最大化兼容性,往往不支持 ass 字幕格式(比如我家那台),因为这种类型的字幕包括了富文本,有可能会指定字幕显示的位置,以及字体等。我们可以使用 ffmpeg 这个工具来将 ass 字幕转换成为 srt 字幕,使用命令:ffmpeg -i [原始字幕.ass] [转换后的字幕].srt 即可。若 srt 字幕中带有一些 HTML 的标签,可以使用文本编辑器将该 srt 文件打开并通过查找替换的方式来删除所有的标签信息。

封面预览图

使用 mkvpropedit 命令可以给视频添加上预览图像,这样在使用电视浏览的时候会在电影列表中显示缩略图。使用命令:mkvpropedit [要修改的MKV文件].mkv --attachment-name "cover" --attachment-mime-type "image/jpeg" --add-attachment "[封面图].jpeg"

字幕时间轴

有时候,在网上找到的字幕可能时间和视频不同步,会差几秒钟,这时可以使用命令ffsubsync来调整字幕的时间轴,一般来说只需要简单的对整体时间前移或者后移某个时间。命令的格式如下:

1
ffsubsync -i [源字幕.srt] -o [输出字幕.srt] --apply-offset-seconds=[移动秒数]

参数“移动秒数”的说明:当该值为正数时,全体字幕的出现时间延迟,当该值为负数时,全体字幕的出现时间提前。

MATTHEW
桂ICP备17005075号