2. H.264 与 H.265 码流基本信息解析

任务说明

用 ffprobe 分别读取一个 H.264 码流和一个 H.265 码流,提取编码格式、分辨率、帧率、码率、像素格式,并整理成对比表。核心思路:调用 ffprobe -show_streams 输出 JSON,解析出视频流字段,再打印成表格。

环境与依赖

  • 已安装 FFmpeg(含 ffprobe),命令行可执行 ffprobe -version。
  • Python 3.8+,仅用标准库(subprocess、json)。
  • 准备两个码流文件:sample_h264.mp4、sample_h265.mp4(或任意含对应编码的容器文件)。

解析流程

码流文件 h264 / h265 ffprobe -show_streams -of json 解析 JSON 取 codec/宽高/帧率 对比表 打印输出

完整代码

import subprocess, json, sys

FIELDS = [
    ("编码格式", "codec_name"),
    ("分辨率",   None),          # 由 width x height 组合
    ("帧率",     "r_frame_rate"),
    ("码率",     "bit_rate"),
    ("像素格式", "pix_fmt"),
]

def probe(path):
    """调用 ffprobe 读取第一个视频流的关键信息。"""
    cmd = ["ffprobe", "-v", "error", "-select_streams", "v:0",
           "-show_entries", "stream=codec_name,width,height,r_frame_rate,bit_rate,pix_fmt",
           "-of", "json", path]
    out = subprocess.run(cmd, capture_output=True, text=True, check=True).stdout
    streams = json.loads(out).get("streams", [])
    if not streams:
        raise RuntimeError(f"未找到视频流: {path}")
    return streams[0]

def fmt_fps(rate):
    """把 '30000/1001' 形式的帧率转成小数。"""
    if not rate or "/" not in rate:
        return rate or "N/A"
    num, den = rate.split("/")
    return f"{int(num)/int(den):.3f}"

def fmt_bitrate(bps):
    if not bps:
        return "N/A"
    return f"{int(bps)/1000:.0f} kbps"

def extract(stream):
    row = {}
    for label, key in FIELDS:
        if key is None:
            row[label] = f"{stream.get('width','?')}x{stream.get('height','?')}"
        elif key == "r_frame_rate":
            row[label] = fmt_fps(stream.get(key))
        elif key == "bit_rate":
            row[label] = fmt_bitrate(stream.get(key))
        else:
            row[label] = stream.get(key, "N/A")
    return row

def print_table(h264, h265):
    labels = [l for l, _ in FIELDS]
    w = max(len(l) for l in labels) + 2
    print(f"{'字段':<{w}}{'H.264':<22}{'H.265':<22}")
    print("-" * (w + 44))
    for l in labels:
        print(f"{l:<{w}}{h264[l]:<22}{h265[l]:<22}")

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("用法: python probe_compare.py <h264文件> <h265文件>")
        sys.exit(1)
    h264 = extract(probe(sys.argv[1]))
    h265 = extract(probe(sys.argv[2]))
    print_table(h264, h265)

运行方式

python probe_compare.py sample_h264.mp4 sample_h265.mp4

验证方法与通过条件

  • 命令正常退出,无 ffprobe 报错,输出一张含 5 行字段的对比表。
  • H.264 行的“编码格式”应为 h264,H.265 行应为 hevc。
  • 分辨率、帧率、码率、像素格式均与源文件实际属性一致(可用 ffprobe -show_streams sample_h264.mp4 单独核对)。
  • 若某字段缺失(如无码率信息),表中显示 N/A,不报错。

常见问题

  • 报 FileNotFoundError:ffprobe 未加入 PATH,需安装 FFmpeg 或使用绝对路径。
  • 报“未找到视频流”:文件不含视频轨,或 -select_streams v:0 未匹配到流。
  • 码率为 N/A:部分容器/裸流不写 bit_rate,属正常现象。