1. Codec 描述符与能力查询
av.codec.Codec 用于查询系统中可用的编解码器信息及其固有能力,是创建 CodecContext 的前置步骤。
核心属性(视频相关)
属性 | 说明 |
|---|
name / long_name
| 编解码器短名/全名 |
type
| 媒体类型,视频为 'video' |
is_encoder / is_decoder
| 是否为编码器/解码器 |
video_formats
| 支持的像素格式列表 (list[VideoFormat]) |
frame_rates
| 支持的帧率列表 (list[Fraction]) 或 None |
properties
| 编解码器固有属性标志位 (Properties) |
capabilities
| 编解码器能力标志位 (Capabilities) |
关键视频 Properties & Capabilities
标志 | 含义 | 视频处理影响 |
|---|
INTRA_ONLY
| 仅帧内压缩 | 无 B/P 帧,PTS==DTS,Seek 极快 |
LOSSY / LOSSLESS
| 有损/无损 | 决定画质与码率权衡 |
REORDER
| 支持帧重排序 | 存在 B 帧,PTS≠DTS,解码输出顺序≠显示顺序 |
DELAY
| 需要 Flush | 编码结束或 Seek 后必须喂 None 排空延迟帧 |
FRAME_THREADS
| 帧级多线程 | 增加解码延迟(每线程+1帧),不适合超低延迟场景 |
SLICE_THREADS
| 切片级多线程 | 单帧内并行,不增加帧间延迟 |
HARDWARE
| 硬件加速实现 | GPU 解码标识,需配合 hwaccel 使用 |
EXPERIMENTAL
| 实验性编码器 | 生产环境慎用,可能被自动跳过 |
💡 实用技巧:通过 Codec('h264', 'r').capabilities & Capabilities.DELAY 可提前判断是否需要 flush 逻辑;用 properties & Properties.REORDER 判断是否需处理 DTS。
2. CodecContext 视频编解码上下文
CodecContext 是实际执行编解码的核心对象,封装了所有运行时参数。
生命周期管理
codec = Codec('libx264', 'w')
ctx = codec.create() # 或 CodecContext.create('libx264', 'w')
ctx.open() # 打开上下文(分配内部资源)
# ... encode/decode ...
ctx.close() # 释放资源
核心视频属性
属性 | 说明 |
|---|
time_base
| 时间基,决定 PTS/DTS 精度 |
bit_rate / max_bit_rate
| 目标码率 / 最大码率 |
profile
| 编码 Profile(如 High, Main) |
extradata / extradata_size
| 全局头信息(SPS/PPS 等) |
ticks_per_frame
| 每帧 tick 数(通常 H.264=2,其他=1) |
thread_count
| 线程数,0=自动 |
thread_type
| 多线程模式 (ThreadType) |
skip_frame
| 跳帧策略 (SkipType) |
编解码核心方法
方法 | 返回值 | 说明 |
|---|
encode(frame=None)
| list[Packet]
| 编码一帧,传 None 触发 flush |
decode(packet=None)
| list[Frame]
| 解码一包,传 None 触发 flush |
parse(raw_input=None)
| list[Packet]
| 纯字节流分割,不解码,将裸流切分为完整 Packet |
flush_buffers()
| - | 重置内部状态,Seek/切流前必调 |
⚠️ 关键警告:encode() 和 decode() 返回值始终是列表。具有 DELAY 或 REORDER 特性的编解码器可能一次返回 0~N 个结果,绝不可假设 1:1 映射。
3. 多线程策略 (ThreadType)
模式 | 值 | 适用场景 | 注意事项 |
|---|
NONE
| 0x0 | 调试、确定性输出 | 性能最低 |
FRAME
| 0x1 | 高吞吐离线转码 | 解码延迟 +N 帧(N=线程数),实时流慎用 |
SLICE
| 0x2 | 低延迟实时解码 | 要求编码器支持切片,单帧内并行 |
AUTO
| 0x3 | 推荐默认值 | 自动选择 FRAME + SLICE 最优组合 |
4. 关键 Flags 速查(视频常用)
Flags(基础标志)
标志 | 用途 |
|---|
GLOBAL_HEADER
| 将 SPS/PPS 放入 extradata 而非每个关键帧,减小文件体积 |
LOW_DELAY
| 强制低延迟模式,禁用帧重排序缓冲 |
GRAY
| 仅编解码灰度通道,节省带宽 |
OUTPUT_CORRUPT
| 即使帧损坏也输出,用于容错播放 |
DROPCHANGED
| 丢弃参数变化的帧,防止分辨率切换导致崩溃 |
BITEXACT
| 比特精确模式,用于测试验证 |
PASS1 / PASS2
| 两遍编码速率控制 |
Flags2(扩展标志)
标志 | 用途 |
|---|
FAST
| 允许非标准加速技巧,牺牲合规性换速度 |
EXPORT_MVS
| 导出运动向量到 Frame side data,用于视频分析 |
SHOW_ALL
| 显示首个关键帧之前的所有帧 |
IGNORE_CROP
| 忽略 SPS 中的裁剪信息,获取完整原始分辨率 |
NO_OUTPUT
| 跳过比特流编码,仅做分析 |
5. 跳帧策略 (SkipType)
适用于解码端快速预览、缩略图生成等场景:
策略 | 行为 | 典型用途 |
|---|
NONE
| 不跳过任何帧 | 正常播放 |
NONKEY
| 仅保留关键帧 | 极速预览 / 缩略图提取 |
BIDIR
| 丢弃所有 B 帧 | 降低解码负载,保持基本流畅度 |
NONREF
| 丢弃所有非参考帧 | 中等程度降载 |
NONINTRA
| 丢弃所有非 I 帧 | 比 NONKEY 更激进 |
ALL
| 丢弃全部 | 仅解析元数据 |
6. 开发排查备忘
问题 | 原因 | 解决方案 |
|---|
编码输出为空 | 未 flush 或未遍历返回列表 | 结束时 encode(None) + 遍历所有返回 Packet |
Seek 后花屏/绿屏 | 未重置解码器状态 | Seek 前调用 flush_buffers() |
解码延迟过高 | 使用了 FRAME 多线程 | 改用 SLICE 或 LOW_DELAY flag |
容器写入失败 | 缺少全局头 | 设置 `flags |
裸流转封装丢帧 | 直接 demux 未 parse | 先用 parse() 将裸流切分为完整 Packet |
运动向量分析无数据 | 未开启导出标志 | 设置 flags2 |= Flags2.EXPORT_MVS |
硬件解码回退软解无感知 | 未检查 capability | 初始化前检查 capabilities & Capabilities.HARDWARE |
💡 核心原则:始终将 encode()/decode() 视为 1:N 操作;涉及 Seek/切流必先 flush_buffers();生产环境优先用 ThreadType.AUTO;转封装前确认 Codec Properties 以预判帧重排和延迟行为。