以下是基于 PyAV Video 模块整理的视频处理核心速查手册。该文档专为视频开发者设计,聚焦于帧操作、像素格式转换、色彩空间管理及性能优化,是进行视频解码分析、AI 预处理及编码合成的基础。
1. 视频流 (VideoStream):关键属性与陷阱
属性 | 类型 | 说明 | ⚠️ 注意事项 |
|---|
average_rate
| Fraction/None
| 基于前几帧计算的平均帧率 | 仅适用于 CFR;VFR 文件可能不准 |
guessed_rate
| Fraction/None
| FFmpeg 多策略猜测的“标称帧率” | ✅ 推荐用于 UI 显示/进度条 |
base_rate
| Fraction/None
| 能精确表示所有 PTS 的最低帧率 | VFR 分析/时间戳对齐时使用 |
display_aspect_ratio
| Fraction/None
| 显示宽高比 (DAR) | 由 SAR + 分辨率推导,渲染/UI 必备 |
sample_aspect_ratio
| Fraction/None
| 像素宽高比 (SAR) | 非正方形像素时必须补偿,否则画面拉伸 |
decode()
| list[VideoFrame]
| 解码 Packet → 帧列表 | 一个 Packet 可能产出 0~N 帧(B帧重排) |
encode()
| list[Packet]
| 编码帧 → Packet 列表 | 可能有延迟输出,flush 时传 None |
💡 帧率选择指南
UI/进度估算 → guessed_rate
时间戳同步/PTS 计算 → base_rate 或直接用 stream.time_base
编码输出设定 → codec_context.framerate(需手动设置)
永远不要假设 average_rate 就是真实帧率
2. VideoFrame:核心操作速查
构造与转换
方法 | 用途 | 依赖 | 备注 |
|---|
VideoFrame(w, h, fmt)
| 创建空白帧 | - | 如 VideoFrame(1920, 1080, 'yuv420p') |
.to_ndarray(**kw)
| → numpy 数组 | numpy | AI/CV 预处理首选;uint16 为系统字节序 |
.to_image(**kw)
| → PIL Image | Pillow | 可视化/缩略图生成 |
.to_rgb(**kw)
| → RGB VideoFrame | - | 内部调用 reformatter,链式操作更方便 |
.reformat(...)
| 缩放/转格式/色彩空间转换 | - | ✅ 核心方法,详见下方 Reformatter |
from_ndarray(arr, fmt)
| numpy → Frame | numpy | pal8 需传 (image, palette) 元组 |
from_image(img)
| PIL → Frame | Pillow | 自动推断尺寸和格式 |
帧类型判断
属性 | 说明 | 典型用途 |
|---|
.key_frame
| 是否为关键帧 (I帧) | Seek 定位、GOP 分析、缩略图提取 |
.pict_type
| PictureType 枚举 (I/P/B/S...)
| 码率分析、编码质量诊断 |
.interlaced_frame
| 是否隔行扫描 | 去隔行滤镜触发条件 |
⚠️ pal8 特殊处理:to_ndarray() 返回 (image, palette) 元组;from_ndarray() 也需传入元组,palette shape 为 (256, 4) ARGB 格式。
frame.reformat() 每次调用都会重新配置内部 swscale 上下文。复用同一个 VideoReformatter 实例可避免重复初始化开销,在批量处理时性能提升显著。
# ✅ 高性能批量转换
reformatter = av.video.reformatter.VideoReformatter()
for frame in container.decode(video=0):
rgb_frame = reformatter.reformat(frame, format='rgb24', width=640, height=360)
process(rgb_frame.to_ndarray())
参数 | 说明 | 默认值 |
|---|
width / height
| 目标尺寸,None 保持不变 | None |
format
| 目标像素格式 (str 或 VideoFormat) | None |
src_colorspace / dst_colorspace
| 源/目标色彩空间矩阵 | 帧自身 / UNSPECIFIED |
src_color_range / dst_color_range
| 源/目标色域范围 (Limited/Full) | UNSPECIFIED |
interpolation
| 插值算法 (Interpolation 枚举) | BILINEAR |
插值算法选择
算法 | 速度 | 质量 | 适用场景 |
|---|
FAST_BILINEAR
| ⚡⚡⚡ | ★★☆ | 实时预览、低延迟流 |
BILINEAR
| ⚡⚡ | ★★★ | 通用默认选择 |
BICUBIC
| ⚡ | ★★★★ | 高质量缩放、截图 |
LANCZOS
| 🐢 | ★★★★★ | 归档级下采样、缩略图生成 |
POINT
| ⚡⚡⚡ | ★☆☆ | 像素艺术、整数倍缩放 |
AREA
| ⚡⚡ | ★★★★ | 大幅下采样抗锯齿 |
4. 色彩空间与像素格式
VideoCodecContext 色彩四件套
属性 | 含义 | 常见值 |
|---|
colorspace
| YUV↔RGB 转换矩阵 | BT.709, BT.601, BT.2020 |
color_primaries
| RGB 色域 primaries | sRGB, DCI-P3, Rec.2020 |
color_trc
| 光电传递函数 (Gamma/EOTF) | Gamma 2.4, PQ, HLG |
color_range
| 信号电平范围 | Limited (16-235), Full (0-255) |
⚠️ 色彩管理警告:reformat() 中若不显式指定 src/dst_colorspace 和 color_range,swscale 可能使用错误的默认值导致色彩偏移/灰阶压缩。HDR→SDR 转换时必须正确设置 TRC 和 Primaries。
属性 | 用途 |
|---|
.is_planar
| 是否平面格式(YUV420p=yes, RGB24=no) |
.is_rgb
| 是否 RGB 类格式 |
.bits_per_pixel
| 每像素位数(含填充) |
.components
| 分量列表,可查 .is_alpha, .is_chroma, .plane |
.chroma_width(luma_w)
| 给定亮度宽度时的色度宽度(处理 4:2:0/4:2:2) |
5. 开发排查备忘
症状 | 可能原因 | 解决方案 |
|---|
画面拉伸/压扁 | 忽略 SAR/DAR | 渲染时用 display_aspect_ratio 校正 |
色彩发灰/过饱和 | color_range 不匹配 | reformat 时显式指定 src/dst_color_range |
HDR 转 SDR 颜色异常 | 未设置 color_trc/primaries | 完整传递色彩四件套到 reformatter |
批量 reformat 慢 | 每帧新建 reformatter | 复用 VideoReformatter 实例 |
to_ndarray 形状不对 | 误判 planar vs packed | 检查 format.is_planar;planar 格式为 (H,W,C) 或分 plane |
pal8 转换报错 | 未传 palette 元组 | from_ndarray((img, pal), 'pal8')
|
decode 返回空列表 | B帧重排/缓冲 | 正常现象,继续送包或 flush |
编码输出帧数少于输入 | 编码器延迟 | 编码结束后 encode(None) flush |
uint16 ndarray 数值异常 | 字节序不匹配 | PyAV 使用系统原生字节序,必要时 .byteswap() |
💡 核心记忆点
帧率三选一:UI 用 guessed,同步用 base,编码用 codec_context.framerate
复用 Reformatter:批量处理性能关键,避免逐帧重建 swscale
色彩四件套必传:colorspace + primaries + trc + range,缺一不可
pal8 是特例:ndarray 交互始终需要 (image, palette) 元组
decode 返回 list:永远遍历返回值,不要假设一包一帧
SAR ≠ 1 是常态:DVD/广播素材几乎都有非方像素,必须补偿