活到老学到老之用 ffprobe 查看视频中的 I/P 帧分布

前提条件

  • 安装了 FFmpeg 套件(包含 ffprobe)
  • 支持读取的视频格式(如 .mp4, .ts, .mkv 等)

查看视频帧类型(I/P/B 帧)

ffprobe -select_streams v:0 -show_frames -show_entries frame=pict_type -of csv output.mp4
  • -select_streams v:0:选择第一个视频流
  • -show_frames:显示每一帧信息
  • -show_entries frame=pict_type:只显示帧类型(pict_type)
  • -of csv:输出为 CSV 格式(也可以用 json 或 default)

输出示例

frame,I
frame,P
frame,B
frame,B
frame,P
frame,B
frame,B
frame,I
...
  • I:关键帧(Intra-frame)
  • P:预测帧(Predicted frame)
  • B:双向预测帧(Bi-predictive frame)

业务中的云录视频分析

testmanzhang@TestMandeMBP 1751597753950 % ffprobe -select_streams v:0 -show_frames -show_entries frame=pict_type -of csv output.mp4
ffprobe version 7.1.1 Copyright (c) 2007-2025 the FFmpeg developers
  built with Apple clang version 16.0.0 (clang-1600.0.26.6)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/7.1.1_2 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox
  libavutil      59. 39.100 / 59. 39.100
  libavcodec     61. 19.101 / 61. 19.101
  libavformat    61.  7.100 / 61.  7.100
  libavdevice    61.  3.100 / 61.  3.100
  libavfilter    10.  4.100 / 10.  4.100
  libswscale      8.  3.100 /  8.  3.100
  libswresample   5.  3.100 /  5.  3.100
  libpostproc    58.  3.100 / 58.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf61.7.100
  Duration: 00:00:12.65, start: 0.000000, bitrate: 1290 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 2304x1296, 1251 kb/s, 20 fps, 20 tbr, 90k tbn (default)
      Metadata:
        handler_name    : VideoHandler
        vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 38 kb/s (default)
      Metadata:
        handler_name    : SoundHandler
        vendor_id       : [0][0][0][0]
frame,I
frame,P
frame,P
frame,P
frame,P
frame,P
frame,P
frame,P
frame,P
frame,P
frame,P
frame,P
frame,P
frame,P
frame,P
[h264 @ 0x7f89bc3064c0] cabac decode of qscale diff failed at 43 66
[h264 @ 0x7f89bc3064c0] error while decoding MB 43 66, bytestream 141
[h264 @ 0x7f89bc3064c0] concealing 2166 DC, 2166 AC, 2166 MV errors in P frame
frame,P
frame,P
frame,P
frame,P
frame,P

这种情况常见于 实时编码的视频(如监控流、直播流),通常只使用 I 和 P 帧,不使用 B 帧,来减少延迟。

中间出现的报错

[h264 @ 0x7f89bc3064c0] cabac decode of qscale diff failed at 43 66
[h264 @ 0x7f89bc3064c0] error while decoding MB 43 66, bytestream 141
[h264 @ 0x7f89bc3064c0] concealing 2166 DC, 2166 AC, 2166 MV errors in P frame

这是 FFmpeg 解码器尝试读取某个 P 帧时出现了解码错误。原因可能有:

  • 视频某个片段损坏(例如下载中断、网络丢包)
  • 原始码流中存在编码错误
  • 有些设备编码时生成了不标准的 H.264 数据

这类错误通常不会导致 ffprobe 整体失败,但说明这一帧的数据解码可能有问题或丢失画面。

frame,P
[h264 @ 0x7f89bc3064c0] concealing 1274 DC, 1274 AC, 1274 MV errors in P frame
frame,P

这是 FFmpeg 的解码器(H.264 解码模块)输出的 警告日志,意思是:

术语 解释
concealing FFmpeg 自动“掩盖”或“修复”了错误数据
1274 DC 有 1274 个块在亮度(直流)分量上有错误
1274 AC 同样有 1274 个块在细节(交流)分量上有错误
1274 MV 有 1274 个块的 运动矢量(Motion Vector) 有问题

这些错误通常说明:
这一帧(P帧)在编码或传输过程中 数据损坏或不完整,导致 FFmpeg 解码器在尝试还原画面时发现数据异常,因此用“掩盖”(concealing)技术来尽力还原该帧,以避免解码失败。

Concealing(掩盖)
FFmpeg 在解码 H.264 视频时,如果遇到帧数据不完整或损坏,它不会直接失败,而是使用 前一帧的图像内容 或 用 预测运动补偿算法,来“猜测”并填补出画面内容,从而 最大限度保证播放不中断,即使某些细节会丢失。

这种错误可能由以下原因引起

原因 说明
文件部分损坏 文件下载或存储不完整,TS/MP4 结构中丢失数据块
实时编码不稳定 设备端编码不标准或写入不完整
网络传输丢包 如果是流媒体(如摄像头/推流),中间传输过程丢包或错帧
硬件编码器 bug 部分嵌入式设备或廉价编码芯片常见编码瑕疵

如果在实际播放中没有肉眼可见的画面花屏或跳帧,那么这类 concealing 是可接受的。但:

  • 如果频繁出现,说明码流质量或设备编码有问题,建议检查摄像头、编码器固件或网络传输链路。

用 ffmpeg -err_detect 更严格地验证损坏程度
ffmpeg -err_detect 是一个非常有用的参数,主要用于在处理或转码视频时,检测并应对输入流中的错误或损坏的帧。

-err_detect
这是一个输入选项,用于告诉 ffmpeg 在解析输入流时开启额外的错误检测机制。
它不是单独运行的命令,而是 配合转码命令或分析命令一起使用的选项。

检测视频中的损坏帧并输出日志

ffmpeg -err_detect explode -i input.mp4 -f null -
参数 说明
-err_detect explode 启用严格的错误检测(遇错直接报错)
-i input.mp4 指定输入文件
-f null - 丢弃输出,只做分析,不保存任何文件

输出样式:

[h264 @ 0x...] concealing errors in P frame
[h264 @ 0x...] corrupted macroblock at 23 34
[h264 @ 0x...] error while decoding MB...

这些表示视频确实存在结构性损坏。

支持的错误检测选项,可以组合使用以下 -err_detect 参数(多个用 + 连接):

参数 说明
crccheck 启用 CRC 校验
bitstream 启用比特流错误检测
buffer 检测解码缓冲区错误
explode 遇到任何错误立即报错退出(最严格)
ignore_err 忽略所有错误(不推荐长期用)

例如:

ffmpeg -err_detect explode+crccheck+bitstream -i input.mp4 -f null -

注意:

  • -err_detect 只影响 解码阶段,主要用于输入时的健壮性控制
  • 对于直播流、监控视频、或者设备直接录制的 .ts、.mp4 等视频非常有用
  • 如果看到大量错误日志,说明码流可能由编码器问题或网络传输异常导致

总结:
ffmpeg -err_detect 是帮助我们 检测视频流错误、定位破损帧、或在必要时容错跳过错误帧 的利器。

下面是业务中云录视频的解析输出:

[h264 @ 0x7f8c57a30700] cabac decode of qscale diff failed at 43 66
[h264 @ 0x7f8c57a30700] error while decoding MB 43 66, bytestream 141
[h264 @ 0x7f8c57a30700] concealing 2166 DC, 2166 AC, 2166 MV errors in P frame
[vist#0:0/h264 @ 0x7f8c57a04b00] [dec:h264 @ 0x7f8c57a07180] Error submitting packet to decoder: Invalid data found when processing input
[h264 @ 0x7f8c578053c0] concealing 11469 DC, 11469 AC, 11469 MV errors in P frame
[vist#0:0/h264 @ 0x7f8c57a04b00] [dec:h264 @ 0x7f8c57a07180] corrupt decoded frame
[h264 @ 0x7f8c57819f00] concealing 11469 DC, 11469 AC, 11469 MV errors in P frame
[vist#0:0/h264 @ 0x7f8c57a04b00] [dec:h264 @ 0x7f8c57a07180] corrupt decoded frame
[h264 @ 0x7f8c578053c0] concealing 11469 DC, 11469 AC, 11469 MV errors in P frame
[vist#0:0/h264 @ 0x7f8c57a04b00] [dec:h264 @ 0x7f8c57a07180] corrupt decoded frame
[h264 @ 0x7f8c57a1c6c0] concealing 11469 DC, 11469 AC, 11469 MV errors in P frame
[vist#0:0/h264 @ 0x7f8c57a04b00] [dec:h264 @ 0x7f8c57a07180] corrupt decoded frame
[out#0/null @ 0x7f8c57a09780] video:108KiB audio:346KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: unknown
frame=  252 fps=0.0 q=-0.0 Lsize=N/A time=00:00:11.07 bitrate=N/A speed=20.2x    
  1. 起始报错:CABAC 解码失败
[h264 @ 0x7f8c57a30700] cabac decode of qscale diff failed at 43 66
  • cabac:一种 H.264 的熵编码方式(更高压缩率,但更复杂)
  • qscale diff:解码量化参数差值失败
  • at 43 66:出错的位置是宏块(Macroblock)坐标 (43,66)
  • 说明该位置的数据被破坏或不合法,导致解码器无法正常恢复该块内容。
  1. 明确指出宏块解码失败
[h264 @ 0x7f8c57a30700] error while decoding MB 43 66, bytestream 141
  • 解码第 43 列、第 66 行的宏块失败
  • bytestream 141:说明 H.264 字节流在这块时只剩 141 字节(很可能不完整)
  1. 尝试掩盖损坏帧
[h264 @ 0x7f8c57a30700] concealing 2166 DC, 2166 AC, 2166 MV errors in P frame
  • 解码器使用 concealment(掩盖)机制 尝试修复损坏
  • 具体有:
    (1)**2166 个 DC(直流亮度值)**出错
    (2)**2166 个 AC(高频细节值)**出错
    (3)**2166 个 MV(运动矢量)**出错
  • 通常表示该 P 帧(预测帧)大面积损坏
  1. 提交 packet 到解码器失败
[vist#0:0/h264 @ 0x7f8c57a04b00] [dec:h264 @ 0x7f8c57a07180] Error submitting packet to decoder: Invalid data found when processing input
  • 表示 FFmpeg 尝试将一帧送入解码器时,数据结构无效或已损坏
  • 解码器拒绝继续解析该帧
  1. 接连多个帧损坏
[h264 @ 0x7f8c578053c0] concealing 11469 DC, 11469 AC, 11469 MV errors in P frame
...
corrupt decoded frame
  • 多次出现:
    (1)P 帧数据损坏
    (2)大范围掩盖(11469 个宏块错误)
    (3)结果是 帧解码失败(corrupt decoded frame)

说明视频 多个连续的 P 帧都严重损坏,几乎整帧都靠“猜测”出来,极有可能播放时出现花屏、卡顿或黑帧。

  1. 最终处理完成
[out#0/null @ 0x7f8c57a09780] video:108KiB audio:346KiB ...
frame=  252 fps=0.0 q=-0.0 Lsize=N/A time=00:00:11.07 bitrate=N/A speed=20.2x
  • FFmpeg 成功跑完整个文件(共 252 帧,约 11 秒)
  • -f null 表示没有输出文件,仅分析或预处理
  • 虽然报错很多,但程序没有崩溃,说明错误被“容忍”了

你可能感兴趣的:(活到老学到老之用 ffprobe 查看视频中的 I/P 帧分布)