🎬 第一章 FFmpeg入门简介
📄 一句话概括

官网有一页叫 Hall of Shame,专门挂「用了 FFmpeg 却不履行 LGPL 义务」的产品。 这一页的存在,说明 FFmpeg 的许可证不是一句「开源免费」能说清的。

📝 本节和前面几节的关系

1.1.1 讲了去哪儿查,这一节讲「查到了也不能随便用」。 1.1.3 讲这个项目自己历史上闹过的一次分裂。

一、耻辱柱上挂的到底是什么行为

LGPL 允许你闭源使用,但要求两件事:

义务 具体要做什么 违反了会怎样


声明 在文档里写明用了 FFmpeg 及版本 被挂上耻辱柱 回馈 改过 FFmpeg 源码就要公开改动 被要求开源或下架 可替换 动态链接,让别人能换掉这份库 被认定为衍生作品

三条里最容易踩的是第三条:静态链接。 把 libav*.a 直接编进自己的 exe,用户就没法换库了,这在 LGPL 下算衍生作品。

所以商业播放器的常规做法是:动态链接 libav*.dll,随包附上许可证文本, 在「关于」里写一句「本产品使用 FFmpeg」。这三件事做完,才算干净。

二、从代码里能看见的那条边界

FFmpeg 自己的代码和它调用的外部库,在名字上就分开了:

名字长什么样 谁写的 许可证归谁


h264、aac、vp8 FFmpeg 自己写 LGPL libx264、libx265 外部项目,FFmpeg 去调 GPL libvpx、libopus 外部项目,FFmpeg 去调 BSD libfdk_aac 外部项目,协议不兼容 通常不编进来

这条分界线非常好用:看到名字以 lib 开头,就去看那个项目自己的许可证; 没有 lib 前缀的,是 FFmpeg 自己的,归 LGPL。

所以「FFmpeg 是什么许可证」这个问题的正确答案是: 看你装的这一份 configure 怎么写的。裸装是 LGPL,加了 --enable-gpl 就整体变 GPL。

三、为什么商业产品绕不开这个坑

因为最好的 H.264 编码器就是 x264,而 x264 是 GPL。

选择 编码质量 许可证代价


用 libx264 最好 整个产品要 GPL 用 openh264 够用 BSD,但要另装 用硬件编码 看芯片 驱动自带的,通常没这个问题 付钱买授权 最好 花钱,但能闭源

四条路的取舍很清楚:要么开源、要么换实现、要么买授权。 耻辱柱上的产品,基本都是选了第一条路却不想承担后果。

顺带说一句:个人用完全不用管这些。 GPL 约束的是「分发」,你自己编一个放自己机器上用,怎么折腾都行。

四、同一份源码,编出不同能力

这一点在本机的构建上能直接看到:有些滤镜有,有些没有。

滤镜 依赖什么 很多构建里没有


scale 无,纯算法 一定有 overlay 无,纯算法 一定有 drawtext freetype 与 harfbuzz 常见缺 subtitles libass 常见缺

这跟许可证是同一件事的两面: 每多接一个外部库,就多背一份许可证义务和多一层依赖。 打包的人为了省事,能关就关。

所以你手上这份 FFmpeg 的能力,是别人替你做的取舍。 知道自己缺什么,比抱怨「教程里的命令跑不通」有用得多。

五、动手 Demo:谁在偷偷用它,又不想认

这一段把「外挂」与「自研」两类编解码器数出来, 再看一个「同一份源码、不同构建」的实例。

import av
import av.filter

libs = sorted([c for c in av.codecs_available if c.startswith(u"lib")])
print(u"外挂组件", len(libs), libs)
print(u"自研组件", len(av.codecs_available) - len(libs))

for n in (u"scale", u"overlay", u"drawtext", u"subtitles"):
    print(n, n in av.filter.filters_available)

实跑输出:

--------------------------------------------------------------------
FFmpeg 耻辱柱——谁在偷偷用它,又不想认
--------------------------------------------------------------------

**① 耻辱柱上挂的不是「盗版」,是「违反 LGPL 却不改」**

**FFmpeg 的核心是 LGPL:你可以闭源用,但两个义务必须尽到——**
**一是声明用了它,二是把对它的修改也开源。**
**大量商业播放器两样都不做,被挂到官网的 Hall of Shame 页。**

**② 耻辱柱的判据,在代码里能直接验证:库的边界在哪个符号上**

**本机这 13 个编解码器是「外挂」的,名字以 lib 开头:**

  外挂组件(上半)      外挂组件(下半)
  ------------------------------------------
  libdav1d              libvpx-vp9
  libmp3lame            libwebp
  libopencore_amrnb     libwebp_anim
  libopencore_amrwb     libx264
  libopus               libx264rgb
  libsvtav1             libx265
  libvpx

**名字里带 lib 的,是 FFmpeg 去调别人的库;不带 lib 的,是 FFmpeg 自己写的。**
**这一条分界线,就是许可证的分界线。**

**③ 自己写的那些,才是 LGPL 覆盖的范围**

  类别             数量     许可证归谁
  -------------------------------------------------------
  FFmpeg 自写      544      LGPL 2.1 起
  外挂第三方库     13       看各家,多半是 GPL 或 BSD

**所以「FFmpeg 是什么许可证」这个问题没有单一答案:**
**裸装是 LGPL,一旦 configure 时加了 --enable-gpl 去接 x264,整个产物就变 GPL。**

**④ 一个能亲手验证的例子:这个构建里没有 drawtext**

  滤镜         本机有没有     为什么
  -----------------------------------------------------------------
  scale        有             纯算法,不需要外部库
  overlay      有             纯算法,不需要外部库
  drawtext     没有           要 freetype 与 harfbuzz,没编进来

**同一份 FFmpeg 源码,别人编出来有 drawtext,这个构建没有——**
**差别不在版本,在 configure 时开了哪些开关。**
**耻辱柱上的产品,很多就是在这个环节把 GPL 组件编进了闭源程序。**

第一张表把 13 个外挂组件摊开,两列排。 名字里带 lib 的,是 FFmpeg 去调别人;不带的,是 FFmpeg 自己写的。

第二张表是这条分界线的量化:557 个里 544 个自研、13 个外挂。 LGPL 覆盖的只是那 544 个的代码,不包括 x264 那三个。

第三张表最有意思:drawtext 不在这个构建里。 同一份源码,官方完整版编得出 drawtext,这个构建编不出来—— 差别不在版本,在 configure 时开没开 freetype。

所以「耻辱柱」这件事往深了看,其实是个很朴素的道理: 每个外部组件都带着一份义务,编进去容易,甩掉难。

30 秒实验

  1. 数外挂:ffmpeg -encoders | grep lib(Linux/Mac)或 ffmpeg -encoders | findstr lib(Windows),看你的构建挂了几个外部库。
  2. 查 GPL:ffmpeg -version 第二行里搜 --enable-gpl。有这一项,你这个构建就是 GPL 的,别拿它做闭源产品。
  3. 找一个缺失的:ffmpeg -filters | grep drawtext,如果没输出,说明你的构建也没编 freetype,第六章的文字水印得换机器做。

常见误区

  1. 以为「开源」等于「随便用」。LGPL 只是允许闭源,不是允许不认账。声明、回馈、可替换三条义务,少一条就算违反。
  2. 以为 GPL 会传染到「用了 FFmpeg 的网站」。GPL 约束的是分发软件,你搭个网站在服务器上跑,不构成分发,没有开源义务。
  3. 以为静态链接更省事。在 LGPL 下静态链接反而更麻烦——用户换不了库,就得按衍生作品处理。省的那点部署成本,往往要用许可证风险来还。
自测三问(点开对答案) 1. 一个商业播放器动态链接了 libavcodec.dll,没改源码,需要在「关于」里写什么? —— 写明使用了 FFmpeg、给出许可证文本、说明怎么获取源码。三件事都做了,就不算违反 LGPL。 2. 为什么 libfdk_aac 常常不在开源构建里? —— 它的许可证与 GPL 不兼容,而很多构建同时开了 GPL 组件。两者放一起会冲突,所以打包者干脆不带它。 3. 「FFmpeg 是 LGPL 的」这句话在什么情况下是错的? —— 当这个构建 configure 时加了 --enable-gpl(比如为了接 x264)时,整个产物按 GPL 分发,这句话就错了。

相关笔记