🎬 第七章 流媒体开源库简介
📄 一句话概括

FFmpeg 不是「一个程序」,而是一组库加三个命令行工具。 库干活,工具只是壳。

📝 本节和前面几节的关系

前面六章全是协议,从这一章开始换视角:看现成的实现有哪些。 7.1.2 讲命令行怎么写,7.1.3 讲怎么用库。

一、库才是主体

实测这套环境里链着七个库: libavcodec、libavformat、libavfilter、libavdevice、 libavutil、libswresample、libswscale。 libavcodec 管编解码、libavformat 管封装与解封装、 libavfilter 管滤镜、libswscale 管像素格式、libswresample 管重采样。 libavutil 是地基——其它库都要用它,编不过它什么都干不了。

版本号能看出年代: libavcodec 已经是 62,libavutil 是 60。 这些主版本号加起来反映的是 API 的演进,跟「FFmpeg 版本号」不是一回事。

二、三个命令行工具

① ffmpeg:转码、转封装、切流、推流,一个工具全包。 ② ffprobe:只看不写——读流信息、读包信息。 ③ ffplay:一个极简播放器,主要用来验证「这条流能不能播」。

三个工具的代码量加起来不到这些库的一成。 它们做的事只有三件:解析命令行、按参数串起库调用、处理错误。 真正的工作量全在库里。

所以「会写 ffmpeg 命令行」离「会用 FFmpeg」还有一段距离。 命令行覆盖不到的场景(比如自定义滤镜链、逐帧控制)只能写代码。

三、为什么它是事实标准

① 格式覆盖最全:能想到的容器与编码基本都支持。 ② 命令行足够表达复杂流程:一条命令能串起解码、滤镜、编码、封装四步。 ③ 被大量项目内嵌:VLC、Chrome、各家媒体服务器都在用它。

第 ③ 条是它真正的护城河: 当所有流媒体软件都链着同一套库时, 「支持哪些格式」这个问题就变成了「FFmpeg 支不支持」。 于是大家更愿意直接用 FFmpeg,而不是自己写一套。

四、动手 Demo:FFmpeg 的模块——一组库,各管一摊

真读一遍这套环境里的库版本,再列清每个库的职责。 看清一件事:命令行工具只是这些库的壳。

import av

print("PyAV", av.__version__)
for k in sorted(av.library_versions):
    print("  %-14s %d.%d.%d" % ((k,) + av.library_versions[k]))
print("共 %d 个库" % len(av.library_versions))

print()
duty = {
    "libavformat": "封装与解封装",
    "libavcodec": "编码与解码",
    "libavfilter": "滤镜与缩放",
    "libswscale": "像素格式转换",
    "libswresample": "重采样",
    "libavutil": "公共工具,其它库的地基",
}
for k, v in duty.items():
    print("  %-14s %s" % (k, v))

实跑输出:

--------------------------------------------------------------------
FFmpeg 的模块——一组库,各管一摊
--------------------------------------------------------------------
**① 真读一遍这套环境里的库版本**

  **PyAV 18.1.0,绑定的是 libav* 系列。**

  库                版本
  -------------------------------
  libavcodec        62.28.102
  libavdevice       62.3.102
  libavfilter       11.14.102
  libavformat       62.12.102
  libavutil         60.26.102
  libswresample     6.3.102
  libswscale        9.5.102

  **一共 7 个库,这就是「FFmpeg 其实是一组库」的直接证据。**

**② 各管一摊**

  库                职责             少了它会怎样
  ---------------------------------------------------------
  libavformat       封装与解封装     打不开文件
  libavcodec        编码与解码       拿到帧也解不出
  libavfilter       滤镜与缩放       只能原样进原样出
  libswscale        像素格式转换     YUV 与 RGB 转不了
  libswresample     重采样           采样率与声道改不了
  libavutil         公共工具         其它库都编不过

**③ 命令行工具只是这些库的壳**

  **ffmpeg 做转码、ffprobe 看信息、ffplay 播放。**
  **三个工具加起来不到这些库的一成代码量——**
  **真正的工作全在库里,工具只负责解析参数、串起调用。**
  **所以「会写命令行」离「会用库」还有一段距离。**

七个库里 libavdevice 最容易忽略,它负责摄像头、屏幕这些采集设备。 libavcodec 是 62,而 libavutil 只有 60——主版本号各走各的,不代表强弱。 PyAV 只是把这些库包了一层 Python 接口,底层还是同一批 .dll。

30 秒实验

  1. 打印 av.library_versions 的键,数一数有几个——七个,这就是「FFmpeg 是一组库」的直接证据。
  2. 加一行 av.open 打开一个文件,看它报错提到哪个库——打不开文件是 libavformat 的错,解不出帧是 libavcodec 的错。
  3. 把 libswscale 那一行去掉,想想会少什么能力——YUV 与 RGB 之间就转不了,截图功能会直接失效。

常见误区

  1. 「FFmpeg 就是一个命令行程序」——主体是七个库。
  2. 「ffmpeg 版本号就是库版本号」——两套编号,不能混。
  3. 「会写命令行就够了」——自定义滤镜、逐帧控制只能写代码。
自测三问(点开对答案) 1. FFmpeg 的主体是什么? —— **七个 libav* 库**;三个命令行工具只是它们的壳。 2. libavformat 与 libavcodec 各管什么? —— **封装解封装**与**编解码**,前者错在打不开,后者错在解不出。 3. 为什么它成了事实标准? —— **格式覆盖最全、命令行能表达复杂流程、被大量项目内嵌。**

相关笔记