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

科技 · 實用指南

FFmpeg 串接提示 DTS 非單調?接受成片前先檢查封包時間

成功完成串流複製串接,可能保留每一個解碼畫面,卻壓縮播放時間。選擇修復方法前,先比較串流參數、片段長度與兩種時間戳記。

原創示意圖區分串流參數、封包邊界及內容與時間兩項驗證
原創概念插圖:比較對應串流、查看兩種時間戳記,分別驗證解碼內容與播放時間。 Watch at Ease

FFmpeg 的 DTS 非單調警告本身不能證明畫面影格被刪除;命令成功結束也不能證明輸出可靠。串接工作可能保留解碼後的畫面內容,卻分配錯誤的播放時間軸。

先保留輸入、串接清單、完整命令與紀錄。確認警告實際對應哪條串流,再區分參數不相容、片段長度錯誤與真正缺失的時間戳記。取代工作副本前,分別核對內容與時間。

保留證據並確認實際串流

保持原片段不變,把實驗輸出寫入新檔案。保存完整 FFmpeg 版本、串接清單、命令、stderr 與串流對應。警告的輸出索引取決於對應;不能預設 0:1 永遠是音訊,也不能只檢查第一條視訊串流。

對每個輸入執行 ffprobe -v error -show_streams -show_format -of json input.mp4,將範例改為實際路徑。比較對應串流數量、類型、編碼、time_base、畫面尺寸、像素格式、取樣率與聲道配置。額外音軌、字幕或資料須明確保留;自動選擇的命令成功,不證明所有必要串流均已包含。

加入時間戳記參數前定位邊界

針對有問題的視訊串流執行 ffprobe -v error -select_streams v:0 -show_packets -show_entries packet=pts_time,dts_time,duration_time -of json input.mp4;另行檢查 a:0 或實際對應的串流。JSON 可能省略無法取得的值。將它們記為未知而非零,並比較時間欄位,別直接比較不同時間基準的原始計數。

檢查相關尾端封包,以及串接清單的 duration、inpoint、outpoint 指令。解多工器以長度偏移後續檔案;猜測的長度可能在參數一致時仍讓下段提早開始。影格間編碼的剪輯也可能產生要求邊界附近的額外封包。容器標稱長度不一定等於精確剪輯點。

區分缺失戳記與既有錯誤時間軸

目前格式參考把 +genpts 定義為:解碼時間戳記存在時,產生缺失的呈現時間戳記。分別檢查 PTS 與 DTS。只列 DTS 的報告出現 N/A,不能證明 PTS 不存在;欄位缺失或既有倒退,都不能直接推出通用修復命令。

同樣,avoid_negative_ts 會平移時間戳記,不能證明時間基準相容或串接長度正確。降低紀錄層級隱藏警告只會改變可見性。測試參數時保留原紀錄,將新封包時間、長度與必要內容和基準比較。

依測量結果修復並確認範圍

若測量證據顯示只有串接長度錯誤,在副本上測試修正的 duration;別為了消除警告而編一個數字。串流不相容時,可先製作相容副本,或使用解碼後的 concat 濾鏡再編碼。濾鏡要求對應串流及從零開始的片段戳記,解析度須明確統一。

同步的視訊與音訊應一起處理。濾鏡對非最後片段採用最長串流的長度,必要時替較短音訊補靜音;不同影格率可能形成可變影格率輸出。應明確選擇預期結果。歷史使用者改用 MKV 成功,只證明該個案,不保證換容器能修復所有輸入。

分別驗證內容與播放時間

我們用 Ubuntu FFmpeg 6.1.1 測試四種隔離的純視訊情況:兩個兩秒 H.264 片段正常串接為四秒。首段 duration 設成 0.5 秒,產生 37 條警告與 2.5 秒輸出;加入 +genpts 未改變結果。另一次時間基準不一致測試產生 50 條警告與 1.967031 秒輸出。全部成功結束,且有序的 100 個解碼影格雜湊仍相同。

合成實驗沒有重現你的片段、音訊或內容遺失故障。SWGDE 說明解碼影格與取樣雜湊可核對內容;時間欄位仍須另行比較。檢查實際輸出的接縫、可辨認的首尾內容、同步及預期總長度。雜湊相同或編碼無警告,都不能單獨證明播放時間正確,也不能恢復來源中不存在的位元組。

原創示意圖比較影格雜湊相同但輸出長度不同的合成串接實驗
原創概念插圖:Ubuntu FFmpeg 6.1.1 純視訊實驗保留 100 個影格,卻把四秒壓成 2.5 秒;genpts 未修復錯誤長度。 Watch at Ease