3. H.264 与 H.265 关键帧提取与对比
任务说明
本案例对同一段原始视频分别用 H.264 和 H.265 编码,然后从两路码流中提取所有 I 帧(关键帧)保存为 PNG 图片,最后对比两种编码下关键帧的数量、时间分布和图像质量。核心工具是 FFmpeg,通过 -skip_frame nokey 只解码关键帧,再用 select 滤镜导出图片。
环境与依赖
- FFmpeg(含 libx264、libx265 编码器),命令行执行
ffmpeg -version确认。 - 一段原始视频
input.mp4(建议 5~10 秒、含明显运动,便于观察关键帧分布)。 - Python 3(仅用于统计关键帧数量与计算 PSNR,非必需但便于对比)。
处理流程
完整实现
以下脚本完成:编码两路码流 → 提取 I 帧 → 统计数量与时间戳 → 计算两路 I 帧的 PSNR。将 input.mp4 放在脚本同目录后运行。
#!/usr/bin/env bash
# extract_keyframes.sh —— H.264 / H.265 关键帧提取与对比
set -e
IN="input.mp4"
[ -f "$IN" ] || { echo "缺少 $IN"; exit 1; }
# 1. 分别用 H.264 和 H.265 编码,固定 GOP=48 便于观察关键帧分布
ffmpeg -y -i "$IN" -c:v libx264 -g 48 -keyint_min 48 -sc_threshold 0 \
-pix_fmt yuv420p -an out_h264.mp4
ffmpeg -y -i "$IN" -c:v libx265 -g 48 -keyint_min 48 -sc_threshold 0 \
-pix_fmt yuv420p -an out_h265.mp4
# 2. 提取所有 I 帧为 PNG,文件名带帧序号
mkdir -p kf_h264 kf_h265
ffmpeg -y -skip_frame nokey -i out_h264.mp4 -vsync 0 \
-frame_pts 1 kf_h264/i_%04d.png
ffmpeg -y -skip_frame nokey -i out_h265.mp4 -vsync 0 \
-frame_pts 1 kf_h265/i_%04d.png
# 3. 统计关键帧数量
echo "H.264 I 帧数量: $(ls kf_h264/*.png | wc -l)"
echo "H.265 I 帧数量: $(ls kf_h265/*.png | wc -l)"
# 4. 打印每路码流的关键帧时间戳(pts_time)
echo "--- H.264 关键帧时间戳 ---"
ffprobe -v error -select_streams v:0 -skip_frame nokey \
-show_entries frame=pts_time -of csv=p=0 out_h264.mp4
echo "--- H.265 关键帧时间戳 ---"
ffprobe -v error -select_streams v:0 -skip_frame nokey \
-show_entries frame=pts_time -of csv=p=0 out_h265.mp4
质量对比用 PSNR 衡量两路码流相对原始视频的差异(数值越高越接近原始):
ffmpeg -i out_h264.mp4 -i "$IN" -lavfi psnr -f null - 2>&1 | grep "PSNR"
ffmpeg -i out_h265.mp4 -i "$IN" -lavfi psnr -f null - 2>&1 | grep "PSNR"
运行与验证
- 执行
bash extract_keyframes.sh,确认无报错并生成kf_h264/、kf_h265/两个目录。 - 终端会打印两路 I 帧数量与时间戳列表。因两路都设了
-g 48且关闭场景切换,关键帧数量应相同,时间戳也应基本一致——这验证了 GOP 结构对关键帧分布的决定作用。 - 打开两个目录中的 PNG,对比同一时间点 I 帧的清晰度与块效应。H.265 在相同码率下通常细节保留更好。
- 查看 PSNR 输出:
average值越大质量越高。若 H.265 的 PSNR 高于 H.264,说明同等条件下 H.265 压缩效率更优。
常见问题
- 若
libx265未安装,编码会失败,需安装带 libx265 的 FFmpeg 构建。 -skip_frame nokey必须放在-i之前才生效。- 若关键帧数量与预期不符,检查是否被
-sc_threshold 0关闭了场景切换插入 I 帧。