MPV 播放远程视频时加载本地字幕
起因
最近在 Linux 上使用 PikPak,遇到了一个体验上的小问题。它没有原生的 Linux 客户端,网页端的播放器又不是万能的,偶尔会遇到一些视频因为编码问题无法解码。
我的解决方法是使用本地播放器 MPV,它可以直接播放 PikPak 文件的远程链接,非常方便。但问题随之而来,很多视频的外挂字幕并不会被自动加载。因为 MPV 在处理一个远程 URL 的时候,并不会去探测同一个远端路径下是否存在同名的字幕文件。于是,我开始寻找一个合适的解决方案。
解决思路
我的核心思路是区别对待视频和字幕文件,利用 rclone
的不同功能来达成目的:
- 视频:用
rclone serve http
将远程视频文件以 HTTP 流的形式提供给 MPV。我发现这是保证流畅播放和快速拖动进度条的最佳方式。 - 字幕:用
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
总结
虽然问题解决了,但是可以说非常费事,总是要运行多个命令,我还在寻找更好的解决方案。