1. 程式人生 > >FFMPEG轉碼音視訊不同步情況總結

FFMPEG轉碼音視訊不同步情況總結

使用FFMPEG轉碼一年半的時間,遇到了各種情況的音視訊不同步,下面我們就來根據問題出現的原因,對所遇到的音視訊不同步做一個分類。

1. 源本身音視訊不同步且無法播放

這種情況極為罕見,在A客戶東方衛視訊道轉碼時遇到過。

表現為輸出的音視訊嚴重不匹配,錄製下來的視訊源無法播放,要麼只有聲音沒有影象,要麼只有影象沒有聲音,且影象播放卡頓。

解決方案:轉碼器無法修復這種異常源,需要反饋給源提供方修復。

2. 源本身的時間戳問題,但源可正常播放

這種情況較少見,在M客戶湖南衛視直播源時出現過。

表現為轉碼出來的視訊影象播放正常,但是沒有聲音。錄製下來的視訊源能正常播放。

分析方法:打印出輸入AVPacket包的時間戳,發現音訊包的PTS正常,而DTS長時間不變。

解決方法:讀出音訊資料包後,如果判斷DTS != PTS,則強制將DTS設為PTS的值。

3. 一段時間內,只丟失一個流的資料

在M客戶的中國氣象頻道轉碼過程中遇到。

表現:輸入源有資料持續輸入的情況下,轉碼有一段時間沒有輸出,且恢復輸出後播放沒有聲音。

分析方法:錄製出問題時間段的視訊源,分析其中的音視訊資料包及時間戳。分析發現在一段時間之內,大概幾秒到十幾秒,輸入的音訊流丟失而視訊流正常,導致在輸出交織時一直等不到音訊流而不斷地buffer資料,直到音訊流恢復後,或者等待超時後才有資料輸出,而輸入音訊流恢復後,由於FFMPEG中執行了如下程式碼調整了原本正常的音訊時間戳,使得音訊時間戳錯亂,導致播放時只有畫面而沒有聲音。


解決方法:本段程式碼在已知場景中用處不大,可以登出掉;也可以將dts_delta_threshold閾值調至一個較大值(預設為10秒,可以調至100秒等等),使之不滿足閾值而不做時間戳調整。另外,為了防止長時間缺失一個流時沒有輸出,以及防止buffer溢位,引數max_interleave_delta值不能設定過大。

4.  源的部分視訊幀未設定時間戳

在一些客戶的直播轉碼過程中,輸入輸出幀率相同的情況下,會遇到log中大量列印“Past duration XXX too large”且伴有frame drop相關資訊的列印。

分析方法:將輸入視訊包的時間戳資訊打印出來,發現一些視訊幀未設定DTS/PTS,這些視訊幀攜帶的時間戳都是預設值為AV_NOPTS_VALUE,程式碼中對該值的定義如下:

#define AV_NOPTS_VALUE         ((int64_t)UINT64_C(0x8000000000000000))

而這些幀在編碼輸出之前會被Drop掉,為了滿足設定的幀率,後面的有效時間戳的幀會提前輸出,導致視訊提前而音訊滯後。

解決方法:由於我們為這些未設定時間戳的輸入幀填充有效時間戳不是一件很容易的事(需要結合輸入視訊是否採用B幀等),因此在輸入輸出幀率相同時,我們可以將這些攜帶無效時間戳的幀正常送至編碼器編碼並輸出,而不是丟棄。

5. "dts < pcr"

線上CBR轉碼時常遇到"dts < pcr, TS is invalid"的列印,時間久了也可能引起輸出碼流的音視訊失步。

首先我們先看看程式碼中PCR的計算,


可見PCR的值與muxrate和寫入到AVIOContext中的資料量有關係。

在保證封裝位元速率穩定的前提下,我們需要關注寫入到AVIOContext中的音視訊資料的速度。一般音訊編碼的速率較為穩定,而視訊編碼速度受B幀策略的影響較大,當視訊編碼使用較多的B幀時,由於是雙向預測,導致編碼速度慢於時間戳相近的音訊幀,而當視訊幀編碼完成並輸出時,AVIOContext中已經填充了較多的音訊幀,使得PCR值超過了當前輸出的視訊幀的DTS,即出現了“dts < pcr”的列印。

解決方法: 線上轉碼時,在對視訊質量沒有特別要求的前提下,優先保證編碼速度,就x264編碼器來說,可以使用zerolatency策略,禁掉B幀的使用並儘量降低編碼延遲。

6. 迴圈源與非單調時間戳

在M客戶電競直播與H客戶雲轉碼專案中都遇到了這種迴圈源與非單調時間戳問題。

FFMPEG預設只支援單調時間戳,一旦遇到非單調時間戳,FFMPEG會強制修改輸出時間戳,程式碼如下,


但修改後的時間戳是不正常的,導致輸出視訊播放異常。具體表現為,若為音視訊透傳,則輸出的音視訊均異常;若轉碼,輸出的視訊正常,而音訊異常,這是因為視訊編碼器會根據幀率和輸出的幀數重新計算時間戳,而音訊時間戳則是繼承了輸入時間戳,從而輸出的視訊時間戳為單調遞增的正常值,而音訊時間戳為FFMPEG強制修改後的值,導致播放沒有聲音。

解決方法:

包括三個方面,

1.  將以上截圖部分對時間戳的修改登出;

2. 取消由於非單調時間戳導致的轉碼退出:


3. 需要轉碼時,由於視訊轉碼輸出時間戳為單調遞增,為了使音訊時間戳與視訊時間戳同步,需要將音訊時間戳按照單調遞增的順序來說出,演算法設計時需要考慮時間戳跳變、丟幀等各種情況的處理。

7.長時間轉碼後出現輕微音視訊不同步

這種音視訊不同步暫時沒有找到根本原因,多見於網路不穩定時,對音視訊丟幀數量統計不精確導致網路恢復後時間戳出現輕微不對齊,且隨著轉碼時間的延長或者網路波動情況的增多,不同步程度會加重。由於暫時無法確定具體原因,且一般在轉碼幾天之後才出現,因此針對該情況的處理方案是,設計一套音視訊不同步檢測演算法來評估音視訊不同步的程度,當達到一定的閾值後,通知前端重啟轉碼器以達到重新同步。