城市便條技術筆記

技術筆記 #018|H.265 攝影機為什麼會抓到灰色雪花圖?原來和 Keyframe 有關

強迫自己每天輸出且(儘量)不用 AI 寫文章 Day029

今天的筆記和 AI 沒什麼關係,但最近專案剛好碰到一個問題,查完覺得蠻有趣的,所以想記一下。

前陣子換了一台攝影機之後,程式開始抓到灰色雪花、像雜訊一樣的圖片。

H.264 換成 H.265 後,串流有畫面,程式卻輸出灰色雪花。
I-frame 是可以單獨還原的關鍵影格;P-frame 只記錄與前一張不同的地方。
串流從兩個 I-frame 中間接入時,先收到的 P-frame 缺少參考畫面,可能解碼成灰色雪花。
讓 FFmpeg 跳過非關鍵影格、等待下一張 I-frame;測試中的灰色畫面由 10/10 降為 0/10。
1 / 4

一路查下去才發現,新舊攝影機用的影片編碼不一樣:

舊的是 H.264,新的是 H.265。

以前看到 H.264、H.265,我大概只知道「H.265 比較新、壓縮效率比較好」,這次才真的去理解它的影格是怎麼回事 🤣。

影片裡不是每一幀都能自己還原成完整畫面。

像 P-frame、B-frame 這類預測幀,需要參考其他影格;Keyframe 則可以自己作為解碼的起點。

剛好我們原本的程式除了 OpenCV,本來就有留一套 FFmpeg 的取圖方式,所以我就直接切過去測。

結果居然就正常了。

後來進一步測試:

  • OpenCV:10/10 灰圖
  • FFmpeg:0/10 灰圖
  • FFmpeg + skip_frame nokey:0/10 灰圖

再往下看才發現,這支 H.265 串流的 Keyframe 間隔大約是 2.5 秒,但原本 OpenCV 的流程連上之後只讀前 3 幀。

如果剛好從兩個 Keyframe 中間接進去,前幾幀可能需要參考更早的影格才能完整還原,但程式手上根本沒有。

當時 log 也剛好出現過:

Could not find ref with POC

意思就是 decoder 想解這一幀,卻找不到它需要的 reference frame。

最後我們改成 FFmpeg,並加上 -skip_frame nokey,直接跳過非 Keyframe,只取關鍵影格,灰色雪花圖也沒有再出現。

這次才知道,換攝影機時除了 FPS、解析度這些比較直覺的設定,H.264/H.265、GOP、Keyframe 間隔和程式怎麼取幀,也可能影響最後拿到的圖片。

如果之後也有人碰到 RTSP 串流明明讀得到,卻一直出現灰圖、雪花,甚至看到 Could not find ref with POC,可以順便往這幾個方向查。

原本只是想解一張灰圖,最後莫名其妙上了一堂影片編碼課 🤣。

大家還有遇過哪些「修一個 bug,結果被迫學了一整個新領域」的經驗?