1. 核心设计理念
PyAV 采用双重继承策略:FFmpeg 错误既继承自 av.FFmpegError,也映射到 Python 内置异常(如 ValueError, OSError)。这意味着你可以用任一方式捕获。
# ✅ 两种等价捕获方式
try:
container.decode(video=0)
except av.InvalidDataError: # PyAV 专用异常
handle_corrupt_frame()
try:
container.decode(video=0)
except ValueError as e: # Python 内置异常(同样可捕获)
if e.errno == av.error.INVALIDDATA:
handle_corrupt_frame()
💡 推荐风格:优先使用
av.*Error专用异常类,语义更清晰;仅在需要统一处理多种底层 OS 错误时才回退到OSError/ValueError。
2. FFmpegError 基类属性
所有 PyAV FFmpeg 异常均继承自 av.FFmpegError,提供以下诊断信息:
诊断最佳实践
except av.FFmpegError as e:
print(f"[{e.type.name}] {e.strerror}")
print(f"File: {e.filename}")
if e.log:
print(f"FFmpeg Log: {e.log}")
3. 视频高频异常速查表
🔴 编解码相关
🟡 容器与 I/O 相关
🌐 网络流相关
⚙️ 其他
4. ErrorType 枚举用法
当需要精确匹配错误码而非异常类型时(如在通用 OSError 处理器中区分 FFmpeg 错误):
import av.error
try:
do_video_processing()
except OSError as e:
# 精确匹配 FFmpeg 错误码
if e.errno == av.error.BSF_NOT_FOUND:
fallback_without_bsf()
elif e.errno == av.error.INVALIDDATA:
skip_and_continue()
else:
raise # 非目标错误,重新抛出
⚠️ 注意:
e.errno是 FFmpeg 内部错误码,不等于 POSIX errno。不要与errno.ENOENT等混用。
5. 视频处理异常处理模式
模式一:容错解码循环
for packet in container.demux(video=0):
try:
frames = packet.decode()
for frame in frames:
process(frame)
except av.InvalidDataError:
logger.warning(f"Corrupt packet at PTS={packet.pts}, skipping")
continue
except av.EOFError:
break
模式二:编码器安全初始化
try:
ctx = Codec('libx265', 'w').create()
ctx.open()
except av.EncoderNotFoundError:
logger.warning("libx265 unavailable, falling back to libx264")
ctx = Codec('libx264', 'w').create()
ctx.open()
except av.ExperimentalError:
ctx.flags2 |= 'FAST'
ctx.open()
模式三:网络流重试
from time import sleep
for attempt in range(3):
try:
container = av.open(stream_url, timeout=5)
break
except (av.HTTPServerError, av.HTTPForbiddenError) as e:
logger.warning(f"Attempt {attempt+1} failed: {e.strerror}")
sleep(2 ** attempt)
else:
raise RuntimeError("Stream unavailable after retries")
6. ⚠️ 常见陷阱
💡 核心原则:视频处理是"脏数据"密集型任务,永远假设输入可能损坏。对
InvalidDataError做降级而非崩溃;对网络错误做重试而非放弃;对所有 FFmpeg 错误保留log用于事后诊断。优先使用av.*Error专用异常类保持代码可读性。