4. H.264 与 H.265 不同 CRF 质量参数对比
任务说明
对同一段输入视频,分别用 H.264(libx264)和 H.265(libx265)以多组 CRF 值编码,采集每组的码率与 PSNR,观察质量随 CRF 变化的趋势,并对比两种编码器在相同 CRF 下的差异。
环境与依赖
- FFmpeg(需包含 libx264、libx265,可用
ffmpeg -encoders | findstr 264确认) - Python 3(仅用标准库,负责批量调用与结果汇总)
- 一段测试视频
input.mp4,放在脚本同目录
实现思路
脚本对每个编码器遍历 CRF 列表,调用 ffmpeg 编码并同时用 psnr 滤镜输出质量指标,从 ffmpeg 日志中解析实际码率与平均 PSNR,最后打印对比表。
完整代码
import subprocess, re, os
INPUT = "input.mp4"
CRF_LIST = [18, 23, 28, 33]
ENCODERS = {"H.264": "libx264", "H.265": "libx265"}
def run(enc, crf):
out = f"out_{enc}_{crf}.mp4"
cmd = ["ffmpeg", "-y", "-i", INPUT,
"-c:v", enc, "-crf", str(crf), "-preset", "medium",
"-c:a", "copy", out,
"-lavfi", f"psnr=stats_file=psnr_{enc}_{crf}.log"]
# 用 -f null 单独跑一次 PSNR,避免与编码输出冲突
cmd = ["ffmpeg", "-y", "-i", INPUT,
"-c:v", enc, "-crf", str(crf), "-preset", "medium",
"-c:a", "copy", out]
subprocess.run(cmd, capture_output=True)
psnr_cmd = ["ffmpeg", "-i", INPUT, "-i", out,
"-lavfi", "psnr", "-f", "null", "-"]
r = subprocess.run(psnr_cmd, capture_output=True, text=True)
log = r.stderr
m = re.search(r"average:([\d.]+)", log)
psnr = float(m.group(1)) if m else float("nan")
size = os.path.getsize(out)
# 用 ffprobe 取时长算码率
dur = float(subprocess.run(
["ffprobe", "-v", "error", "-show_entries", "format=duration",
"-of", "default=nk=1:nw=1", out],
capture_output=True, text=True).stdout.strip())
kbps = size * 8 / dur / 1000
return kbps, psnr
print(f"{'编码器':<8}{'CRF':<6}{'码率(kbps)':<14}{'PSNR(dB)':<10}")
for name, enc in ENCODERS.items():
for crf in CRF_LIST:
kbps, psnr = run(enc, crf)
print(f"{name:<8}{crf:<6}{kbps:<14.1f}{psnr:<10.2f}")
运行方式
python compare_crf.py
脚本会在当前目录生成 out_H.264_*.mp4 与 out_H.265_*.mp4 文件,并打印对比表。
验证与判定
- 表格中每个编码器应有 4 行,CRF 越大码率越低、PSNR 越低,趋势单调即符合预期。
- 相同 CRF 下,H.265 通常码率更低、PSNR 略高或相当;若某组异常,检查 ffmpeg 是否支持对应编码器。
- 主观质量:用播放器打开同 CRF 的 H.264 与 H.265 输出,对比细节保留与块效应,H.265 在低码率下应更平滑。