
目錄一、先建立心智模型FFmpeg 為什么難調試二、第一層命令行級調試80% 問題止步于此1?. 把日志等級拉滿必會2?. 用 ffprobe先排除「輸入源問題」高頻坑3?. 拆解 filtergraphfilter 調試核心技巧三、第二層API 級調試libav* 項目必看1?. 接管 FFmpeg 日志別用 printf2?. 打印時間戳90% 音畫不同步的根因3?. AVERROR一定要轉成可讀字符串四、第三層GDB / 崩潰級調試真·硬核1?. 編譯 FFmpeg必須帶符號2?. GDB 啟動 斷點套路3?. SIGSEGV / Assertion failed 標準流程五、第四層性能調試卡頓 / CPU 100%1?. 先確認瓶頸在哪一層2?. 性能三件套看 filter 成本Linux 神器 perf硬件加速快速驗證六、GUI / Overlay / Qt 場景的特殊坑你這個場景重點線程模型一定要對overlay filter 調試參數七、FFmpeg 調試 Checklist覺得有用就請您幫忙點贊轉發收藏吧您的鼓勵是我創作的動力多謝看官。由于能力水平有限文中的錯誤或不嚴謹的地方在所難免還請批評指正。本文面向中高級開發者系統梳理 FFmpeg 調試的 4 個層級命令行級 → 日志級 → 源碼/GDB 級 → 性能 崩潰級。你將掌握為什么 FFmpeg 報錯信息總是「語焉不詳」以及如何讓它開口說話-v、-report、AV_LOG_DEBUG的正確打開方式用 GDB core dump 定位SEGV/Assertion failed的完整流程filtergraph尤其是 overlay / scale調試的專用技巧性能問題卡頓、掉幀、CPU 飆高如何用ffprobe perf VTune拆解一套可直接復用的「FFmpeg 調試 Checklist」一、先建立心智模型FFmpeg 為什么難調試FFmpeg 調試難本質不是工具問題而是架構問題CLI (ffmpeg.c) └── libavformat (demux / mux) └── libavcodec (decode / encode) └── libavfilter (filtergraph) └── 硬件加速 / 線程池 / 內部 buffer 池典型痛點現象真實原因只說Error while filteringfiltergraph 某節點 init 失敗但錯誤信息被吞卡住不動線程池死鎖 / muxer 等 B-frame 緩存花屏時間基不一致 / width/height 對齊問題偶發崩多線程 use-after-free結論不要只盯著最后一行 Error要順著「模塊邊界」查。二、第一層命令行級調試80% 問題止步于此1?. 把日志等級拉滿必會ffmpeg -v debug -i in.mp4 -vf scaleiw/2:ih/2 out.mp4日志等級優先級由低到高quiet panic fatal error warning info verbose debug trace實戰建議場景推薦看 filter 初始化-v verbose看時間戳 / PTS-v debug看內存分配/refcount-v trace非常吵黃金組合ffmpeg -v verbose -report -i in.mp4 ...-report會自動生成ffmpeg-YYYYMMDD-hhmmss.log包含完整命令行 環境變量 所有日志線上問題必開。2?. 用ffprobe先排除「輸入源問題」高頻坑原則ffmpeg 崩 ≠ ffmpeg 的鍋先證偽輸入文件ffprobe -v debug -show_streams -show_frames -select_streams v in.mp4重點看codec_typevideo width1920 height1080 pix_fmtyuv420p r_frame_rate30/1 start_time1.4 ← 很多花屏/卡頓的根因 time_base1/90000經典信號ffprobe 輸出含義start_time 0 concatPTS 漂移pix_fmtnv12但 filter 只認 yuv420pswscale 自動插入隱式慢nb_framesunknownVBR 缺索引3?. 拆解 filtergraphfilter 調試核心技巧錯誤姿勢-vf scale1080:-2,overlay10:10,drawtexttexttest,formatyuv420p正確姿勢二分法拆 graph# Step1 只跑 scale -vf scale1080:-2,formatyuv420p # Step2 加 overlay -vf scale1080:-2,formatyuv420p,overlay10:10 # Step3 加 drawtext高級技巧dump filter 中間結果ffmpeg -i in.mp4 -vf scaleiw/2:ih/2,split2[a][b];[a]null[aout] \ -map [aout] step1.yuv或直接輸出 rawvideoffmpeg -i in.mp4 -vf scale -f rawvideo -pix_fmt yuv420p out.yuv用ffplay看中間幀ffplay -f rawvideo -pix_fmt yuv420p -s 960x540 out.yuv三、第二層API 級調試libav* 項目必看1?. 接管 FFmpeg 日志別用 printfav_log_set_level(AV_LOG_DEBUG); av_log_set_callback(my_log_cb); void my_log_cb(void *ptr, int level, const char *fmt, va_list vl) { if (level av_log_get_level()) return; fprintf(stderr, [FFmpeg][%s] , av_default_item_name(ptr)); vfprintf(stderr, fmt, vl); }小技巧av_default_item_name(ptr)會打出模塊名[h264 0x55...] [Parsed_overlay_0]一眼知道是哪個模塊在說話。2?. 打印時間戳90% 音畫不同步的根因av_log(NULL, AV_LOG_INFO, pts%s dts%s tb%d/%d\n, av_ts2str(pkt-pts), av_ts2str(pkt-dts), st-time_base.num, st-time_base.den);推薦宏#define PTS_LOG(pkt, st) \ av_log(NULL, AV_LOG_DEBUG, %s pts:%s dts:%s\n, \ st-codecpar-codec_type AVMEDIA_TYPE_VIDEO ? V : A, \ av_ts2timestr(pkt-pts, st-time_base), \ av_ts2timestr(pkt-dts, st-time_base))3?.AVERROR一定要轉成可讀字符串新手寫法if (ret 0) printf(error %d\n, ret);正確寫法char errbuf[AV_ERROR_MAX_STRING_SIZE]; av_strerror(ret, errbuf, sizeof(errbuf)); fprintf(stderr, avcodec_send_packet failed: %s\n, errbuf);四、第三層GDB / 崩潰級調試真·硬核1?. 編譯 FFmpeg必須帶符號./configure \ --enable-debug3 \ --disable-stripping \ --disable-optimizations \ --extra-cflags-O0 -fno-omit-frame-pointer make -jRelease 優化下 GDB backtrace 基本不可讀調試時必須關 O22?. GDB 啟動 斷點套路gdb --args ./ffmpeg -i in.mp4 out.mp4常用斷點break avcodec_send_packet break av_buffersink_get_frame break avfilter_graph_config break report_and_exit看 filter 初始化失敗b avfilter_graph_config run bt3?. SIGSEGV / Assertion failed 標準流程ulimit -c unlimited ./ffmpeg ... gdb ./ffmpeg coreGDB 三板斧bt full # 看完整調用棧 frame N # 切到 ffmpeg / 你的 frame p *ctx p *frame p frame-buf[0] # 看 buffer ref 是否懸空FFmpeg 常見崩潰模式速查backtrace 特征結論libavfilter/avfilter.c:144filter 沒 unref frameff_thread_decode_frame線程 unsafe 的 codecav_malloc - abortOOM / 內存池被吃光五、第四層性能調試卡頓 / CPU 100%1?. 先確認瓶頸在哪一層ffmpeg -v verbose -benchmark -i in.mp4 out.mp4看結尾輸出bench: utime12.34s stime1.2s rtime5.6s現象瓶頸rtime ≈ utime單線程 CPUutime 很低但 rtime 很長IO / mux 阻塞filtergraph 吃滿scale / overlay 太重2?. 性能三件套看 filter 成本-vf scale1920:1080,setptsPTS,null加/減 filter 對比時間一測一個準。Linux 神器 perfperf top -p $(pidof ffmpeg)看到swscale/hscale_fast→ 換zscale或 hwaccel硬件加速快速驗證ffmpeg -hwaccel cuda -i in.mp4 -vf hwupload,scale_nppw1280:h720 out.mp4六、GUI / Overlay / Qt 場景的特殊坑你這個場景重點你在 Qt 里畫 OverlayWidget FFmpeg典型問題線程模型一定要對解碼線程 → AVFrame (YUV) → 拷貝 → UI 線程 → QImage/QPainter常見錯在avcodec_receive_frame里直接QImage::loadFromDataAVFrame被 filter 自動 unref 后 UI 還在畫安全模式av_frame_ref(ui_frame, frame); // 或 copy 到 cv::Mat / QImage buffer emit frameReady();overlay filter 調試參數overlayxW-w-10:yH-h-10:formatyuv420p:eof_actionpass調試時加-vf formatyuv420p,overlay...,formatyuv420p避免swscale 在 graph 里偷偷插 3 次七、FFmpeg 調試 Checklist是否先用 ffprobe 確認輸入文件 是否開了 -v verbose -report filtergraph 是否二分法拆解過 AVERROR 是否 av_strerror 打印 崩潰是否用帶符號版本 gdb bt full 性能問題是否確認 scale/filter 成本 多線程是否保證 AVFrame 生命周期