科技 · 实用指南
在 Linux 上移动了 mpv 视频?恢复能匹配的续播记录
从 watch_later 备份生成独立恢复目录,检查未匹配的路径,并在保留唯一记录的前提下验证续播。

视频移动后,mpv 保存的播放位置可能仍在备份中,却无法在打开新路径时被找到。对于普通的完整路径记录,查找记录所用的名称取决于媒体路径。如果你知道原位置和新位置,本文的辅助程序可以批量匹配这些记录,再把它们复制到独立的恢复目录。
这是适用范围有限的 Linux 恢复流程,已使用 mpv 0.41.0 和 Python 3.12.14 验证;辅助程序要求 Python 3.9 或更新版本,并拒绝在其他操作系统上运行。你需要保留下来的 watch_later 目录,以及能可靠指向同一批视频的路径对应关系。旧名称未知、录像已删除或视频剪辑版本不同的情况,仍无法由此解决。
1. 确认路径是否真的改变
关闭 mpv 后,把整个原始 watch_later 目录复制到新的备份位置,并保留文件修改时间。按照第 7 步的 cp -a 命令形式操作,使用新的备份目标;普通复制若重置了时间,可能改变后续 mtime 检查的结果。应使用实际配置中的目录,包括任何 --watch-later-directory 覆盖设置。当前 Linux 文档规定,状态默认位于 ~/.local/state/mpv/watch_later;较旧的安装可能使用 ~/.config/mpv/watch_later。新安装中的目录为空,不代表旧记录已丢失。
如果媒体仍使用完全相同的路径,先确认已经启用续播,并且 mpv 正在读取复制后的目录。有一例 IINA 支持问题通过复制和配置得到解决;这不能证明每次重装都需要重建记录键。下面的流程适用于已知的移动或重命名,而且必须先保存原记录。不要把改用仅文件名存储当作迁移捷径:它不会转换现有的完整路径键,不同视频若文件名相同,还可能共用一个键。
2. 确定旧路径与新路径的对应关系
对于结构未变的目录树,记下准确的旧媒体根目录和新根目录。例如,/media/old-drive/Shows 现在可能变为 /mnt/media/Shows,而各文件名和子目录保持不变。旧根目录不必仍然存在,但你必须知道其准确写法。使用 mpv 当时看到的路径,包括大小写和符号链接的路径写法;猜测出来的挂载名称不能作为可靠的对应关系。
辅助程序接受规范的 Linux 绝对路径,不允许其中出现 ./、../、重复分隔符、NUL、回车或换行。它不会推测旧版本的路径规范化方式、逆向还原匿名哈希值,也不会凭文件内容寻找重命名的电影。确认某个路径能生成备份中的哈希值是必要条件,但你还必须知道新路径对应的是同一录像和同一剪辑版本。若影片被替换或剪辑过,原来的时间位置可能已不再对应同一场景。
3. 保存并检查完整辅助程序
在新的工作文件夹中打开终端,检查 python3 --version。请使用 Linux 上的 Python 3.9 或更新版本。以下命令只下载完整源代码,不运行它;如果没有 curl,也可以用浏览器打开同一地址,将文件另存为 recover-mpv-watch-later-v1.py。
curl --fail --location "https://watchatease.com/guide-tools/recover-mpv-watch-later-v1.py" --output "recover-mpv-watch-later-v1.py"
阅读源代码后,运行 sha256sum "recover-mpv-watch-later-v1.py"。本版本的 SHA-256 必须为 e9b71043f6e0f1600387cf3b4760c84c1df673b866e62725ec5f5b93331d1d78。如果哈希值不同,说明本文尚未验证这些字节;请停止并检查下载文件。辅助程序不会启动 mpv,也不会编辑备份。
4. 预览整棵目录树迁移或明确的重命名
把下面所有示例路径替换为自己的路径。backup 参数指向保留下来的状态副本;recovered-state 是位于备份之外、尚不存在的新目录。先创建输出目录的父目录,但不要创建 recovered-state。在规划和复制过程中保持备份与现有媒体不变。下面的根目录模式命令会枚举当前目录树,并构造相应的旧路径;不带 --write 时只输出 JSON 报告。在已验证的 Python 运行环境中,自动扫描不会进入符号链接指向的目录;对于通过这些目录访问的已知文件,请使用明确的路径映射。
python3 "recover-mpv-watch-later-v1.py" --backup "/home/you/mpv-backup/watch_later" --output "/home/you/mpv-recovery/recovered-state" --old-root "/media/old-drive/Shows" --new-root "/mnt/media/Shows"
对于确实发生重命名的文件,创建名为 mapping.json 的 UTF-8 文件,其中包含这样的数组:[{"oldPath":"/media/old-drive/Shows/old-name.mkv","newPath":"/mnt/media/Shows/new-name.mkv"}]。每一组已知路径对应关系添加一个对象,必要时按正常 JSON 规则转义。使用下面这条替代命令;--mapping 不能与任一根目录参数同时使用。
python3 "recover-mpv-watch-later-v1.py" --backup "/home/you/mpv-backup/watch_later" --output "/home/you/mpv-recovery/recovered-state" --mapping "mapping.json"
5. 应用前先阅读报告
ready 行表示旧路径匹配到一个普通 UTF-8 状态文件,其中只有一个有限、非负的 start 值。检查该行的 oldPath、newPath 和 position。no-matching-position-record 表示没有匹配到可用的位置记录;current-media-missing 表示明确映射中的目标文件不存在。unmatchedBackupHashNames 列出其余以哈希值命名的记录,其中有些可能是目录或播放列表重定向标记。不要把每个未匹配的名称都理解为丢失的视频。
把 mtimeGateWouldMatch 视为一项独立、可选的策略检查。mpv 的 --resume-playback-check-mtime 默认值为 no;按此默认方式保存的记录,不必带有媒体文件的修改时间。因此,false 本身不意味着损坏或迁移出错。辅助程序保留记录原有的时间,即使此字段为 false,也会复制 ready 行。它不会修改媒体时间来制造匹配。
测试前先选择续播策略。如果原来的工作流程会检查 mtime,请保留 yes 并要求检查通过;结果为 false 时,应暂停这条正常恢复路径。只有独立确认目标是同一个未经剪辑的视频后,才可在另一个可丢弃的副本上使用 no,诊断保存的位置。这样做不会修复时间一致性,也不会让以后的 yes 会话正常工作。下面默认的 no 分支同样要求满足第 2 步中已知媒体身份的条件。重复来源、竞争同一目标键、格式错误的输入和不支持的状态条目,都应通过检查错误或未匹配行来处理,而非随意挑选一条记录。
6. 写入一套独立的恢复记录
确认预览中的对应关系符合预期后,在同一条命令后加上 --write 再运行。保持路径和映射方式不变。根目录模式的示例如下:
python3 "recover-mpv-watch-later-v1.py" --backup "/home/you/mpv-backup/watch_later" --output "/home/you/mpv-recovery/recovered-state" --old-root "/media/old-drive/Shows" --new-root "/mnt/media/Shows" --write
运行成功时会报告 APPLIED_TO_NEW_DIRECTORY,并在复制的记录旁写入 recovery-report.json。每条接受的记录都会保留原有字节和修改时间。若没有可用记录、输出目录已经存在或预检查出错,程序会停止。复制期间发生 I/O 错误,可能留下不完整的新目录;保留错误信息,在修正后改用另一个尚未使用的目标重新运行。不要合并不完整的结果,也不要仅凭目录存在就认定完成。
7. 使用可丢弃的副本测试,再保存新状态
使用下面的命令,将 recovered-state 另复制为 resume-test,并保留修改时间;目标目录必须尚不存在。以后创建任何工作副本或测试副本,也都应保留修改时间。保持 recovered-state 和原始备份不变。下面的 mpv 命令采用第 5 步默认的 no-mtime 分支,前提是你已经确认目标为同一个未经剪辑的视频。如果原工作流程检查 mtime,请将该选项改成 yes,并要求检查通过。测试会禁用普通配置和自动脚本载入,并明确启用续播。替换全部示例路径。
cp -a -- "/home/you/mpv-recovery/recovered-state" "/home/you/mpv-recovery/resume-test"
mpv --no-config --load-scripts=no --ytdl=no --resume-playback=yes --resume-playback-check-mtime=no --watch-later-directory="/home/you/mpv-recovery/resume-test" "/mnt/media/Shows/episode.mkv"
确认打开的是预期录像,并且从预期场景开始续播。测试应包括有代表性的重命名文件,以及不同目录中同名的文件。mpv 在播放初始化时会消耗已载入的续播记录,因此第二次测试需要另一个副本或新保存的位置。所选分支验证成功后,使用 Shift+Q 按同一策略保存新状态;普通退出并不是同一操作,除非已配置退出时保存。
受控检查成功后,再用正常 mpv 配置测试一个工作副本,并明确通过 --watch-later-directory 指向该副本。保留所选的 mtime 策略:以 no 保存,不会让该记录自动适用于以后的 yes 会话。配置、脚本和已保存选项都可能影响正常播放。在所需位置均已检查、且新保存操作正常工作之前,保留恢复报告和原始备份。这套流程不会自动将结果合并到现有的实时状态目录。
8. 明确何时停止,以及测试证明了什么
如果播放从零开始,先核对测试路径、选择的状态目录、报告和修改时间结果。路径写法改变或启用了 mtime 检查,都可能解释未命中的原因;不匹配不能证明备份损坏。旧路径未知、仅文件名模式的记录、缺少 start 值和剪辑版本改变,都不在此辅助程序的恢复范围内。复制的旧文件名注释和其他已保存选项不会被重写,因此它不会恢复观看历史菜单、g-w 选择、播放列表顺序或外部字幕路径。
我们在 Linux 上运行了这一精确版本的辅助程序,所用第三方二进制程序报告 mpv 0.41.0,并非 mpv 官方认可的软件包。原生生成的记录让一个已知被重命名的视频从第 4 秒续播。另一套双文件测试使用人为构造的第 2 秒和第 8 秒位置;两个同名视频分别从各自的位置续播。13 项辅助程序断言全部通过,包括预览行为、冲突、已占用输出目录和备份哈希不变。另有 12 项播放器断言检查了记录查找、mtime 和记录消耗。这些都是使用生成媒体进行的受控测试,不是对原求助者安装环境的复现,也不构成 Windows/macOS 兼容性承诺。
