Watch at Ease看見世界,讀懂生活。

科技 · 實用指南

在 Linux 上移動了 mpv 影片?恢復能配對的續播記錄

從 watch_later 備份建立獨立恢復目錄,檢查未配對的路徑,並在保留唯一記錄的前提下驗證續播。

原創編輯示意圖:已知的舊影片路徑配對到儲存記錄,新路徑取得一份獨立複製的記錄。
原創編輯插畫,展示已驗證的 Linux 路徑對應流程;記錄鍵配對不能證明兩個檔案包含同一錄影。 Watch at Ease

影片移動後,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 相容性承諾。

原創編輯示意圖,將未改動的備份、恢復記錄集與可捨棄的續播測試複本分開。
原創編輯插畫:測試應使用可捨棄的複本,因為 mpv 會消耗已載入的續播記錄。複製完成與播放成功需要分別驗證。 Watch at Ease