MPV 播放远程视频时加载本地字幕

起因

最近在 Linux 上使用 PikPak,遇到了一个体验上的小问题。它没有原生的 Linux 客户端,网页端的播放器又不是万能的,偶尔会遇到一些视频因为编码问题无法解码。

我的解决方法是使用本地播放器 MPV,它可以直接播放 PikPak 文件的远程链接,非常方便。但问题随之而来,很多视频的外挂字幕并不会被自动加载。因为 MPV 在处理一个远程 URL 的时候,并不会去探测同一个远端路径下是否存在同名的字幕文件。于是,我开始寻找一个合适的解决方案。

解决思路

我的核心思路是区别对待视频和字幕文件,利用 rclone 的不同功能来达成目的:

  1. 视频:用 rclone serve http 将远程视频文件以 HTTP 流的形式提供给 MPV。我发现这是保证流畅播放和快速拖动进度条的最佳方式。
  2. 字幕:用 rclone mount 将远程的字幕文件夹整个挂载到本地。字幕文件体积很小,挂载成虚拟的本地文件,能让 MPV 轻松地进行查找和匹配,且不会有任何性能负担。

具体操作步骤

第一步:用 rclone serve http 提供视频流

这里不推荐用 rclone mount 直接挂载视频目录。根据我的测试,通过 mount 挂载的远程大文件在进行流式播放时性能不佳,尤其在拖动进度条后,会有明显的卡顿和缓冲。而 HTTP 流则没有这个问题。

假设我的视频文件存放在名为 PikPak 的 rclone 远程配置下的 videos 目录里,我需要运行这条命令:

rclone serve http PikPak:videos --addr localhost:8080

执行后,rclone 会在本地 localhost:8080 端口上建立一个 HTTP 服务。现在,PikPak:videos/ 目录下的所有视频,都可以通过 http://localhost:8080/文件名 的方式来访问了。

第二步:用 rclone mount 挂载字幕目录

字幕文件非常小,直接用 mount 挂载是最简单高效的,如果选择直接下载到本地也是可以的。

假设我的字幕文件在 PikPak 远程的 subtitles 目录下。首先,在本地创建一个用于挂载的空文件夹(比如 /mnt/subtitles),然后执行挂载命令:

# 创建挂载点
mkdir -p /mnt/subtitles

# 执行挂载,--daemon 参数让它在后台运行
rclone mount PikPak:subtitles /mnt/subtitles --daemon

现在,远程的字幕文件就已经出现在本地的 /mnt/subtitles 目录中了,MPV 可以像访问本地文件一样访问它们。

第三步:创建一个播放列表

为了避免每次都去复制粘贴视频的 URL,我选择创建一个简单的文本文件来作为播放列表。

比如,创建一个 playlist.txt 文件,将视频的 HTTP 链接一行一个地放进去:

http://localhost:8080/电视剧/S01E01.mp4
http://localhost:8080/电视剧/S01E02.mp4

第四步:启动 MPV

所有准备工作就绪,最后用这条命令启动播放:

mpv --playlist=/path/to/playlist.txt --sub-file-paths=/mnt/subtitles
  • --playlist 参数指向我刚刚创建的播放列表文件。
  • --sub-file-paths 参数则告诉 MPV,去 /mnt/subtitles 这个目录里寻找字幕。

这样一来,MPV 播放列表中的每个视频时,都会自动去字幕目录里寻找同名的字幕文件并加载。

补充技巧:应对不规范的字幕文件名

有时候下载到的字幕文件名并不标准,可能多了语言代码或其他后缀,导致 MPV 无法按默认规则精确匹配。

针对这种情况,可以给 MPV 加一个额外的参数 --sub-auto=all--sub-auto=fuzzy

  • --sub-auto=all 会加载字幕路径下的所有字幕文件。
  • --sub-auto=fuzzy 加载所有包含视频文件名的字幕文件。

例如:

mpv --playlist=/path/to/playlist.txt --sub-file-paths=/mnt/subtitles --sub-auto=all

总结

虽然问题解决了,但是可以说非常费事,总是要运行多个命令,我还在寻找更好的解决方案。

0%