提示

返回博客列表

自己编译一个静态 ffmpeg:从依赖地狱到 16MB 单文件,我把每一步都记下来了

起因是一次交付。我们给客户部署一套视频处理服务,对方给的是几台老机器:CentOS 7,glibc 2.17,没有 root 权限,只有我自己的一个普通账号,机器上预装的 ffmpeg 是 3.x 的残血版——ffmpeg -encoders 一查,libx264 有,libx265 没有,fdk_aac 没有,libvpx 没有,openssl 更是别想,下载 https 的流直接报 Protocol not found。

换机器不可能,装系统包也不可能(没权限,内网也没源)。最后能走的路只剩一条:自己编一个静态链接的 ffmpeg,编译完 scp 过去,chmod +x 就能跑。

这件事听起来简单,实际写了三天。第一天在跟依赖打架,第二天在跟链接器打架,第三天在跟体积打架。这篇文章把这三天的记录整理出来,包括完整的命令、每个参数的含义、报错原文和我的处理方式。

TL;DR:静态 ffmpeg 的核心是 --pkg-config-flags="--static" + --extra-ldflags="-static" + --disable-shared --enable-static,外加把依赖库(x264/x265/fdk-aac/openssl…)全部以静态库形式编到 $HOME/ffmpeg-build 下。三个高频坑:静态链接 glibc 时 getaddrinfo/dlopen 的告警(可用 musl 或放弃 openssl 规避);x265 需要 -lstdc++ -lnuma;体积失控要用 --disable-everything 按白名单开。最后拿 ldd 和干净容器验证,别只在编译机上跑通就交付。

目录

一、先想清楚:静态编译到底解决什么问题

在动手前,我先把"为什么非要静态"这件事想清楚,因为这决定了后面要不要吃这些苦。

所谓静态,就是把 libx264.a、libx265.a、libcrypto.a 这些 .a 文件在链接阶段直接塞进最终的可执行文件,运行的时候不再找系统的 .so。对比一下三种常见方案:

方案 优点 缺点 适合场景
系统包管理器装(apt/yum) 最省事 版本旧、编码器被砍、需要 root 自己的机器、有网有权限
官方 static build(johnvansickle 那种) 直接下载、省事 里面带了什么不受你控制,更新节奏看人家 快速验证、个人使用
Docker 镜像 环境最干净 客户环境不一定有 docker,运维不一定配合 自有服务器、K8s
自己编静态 编码器、协议、体积全可控,单文件丢过去就跑 折腾,编译链要求高 交付给第三方、老系统、无 root

我这次是第四种。判断标准其实就一条:目标机器的 glibc 版本比编译机老,或者目标机器你不能装东西。反过来,如果目标机器跟你编译机同系统同版本,直接把动态链接的 ffmpeg 连同它 ldd 出来的一堆 .so 打个 tar 一起丢过去,往往更省事——我后来给另一台 Ubuntu 22.04 就这么干的,5 分钟完事。

判断 glibc 版本:

ldd --version | head -1
# ldd (GNU libc) 2.17

黄金法则:在目标机器上,或者比目标机器更老的系统上编译。在 Ubuntu 24.04(glibc 2.39)上编出来的东西,拿到 CentOS 7(2.17)上大概率报:

./ffmpeg: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by ./ffmpeg)

我一开始就是在本机 Ubuntu 上编的,scp 过去直接报这个,白等了 40 分钟传输。后来找了台 CentOS 7 的虚拟机重编。

二、环境准备与目录约定

目录约定我沿用了 ffmpeg 官方编译文档的习惯,别乱改,后面所有命令都依赖它:

mkdir -p ~/ffmpeg-sources ~/ffmpeg-build ~/bin
  • ffmpeg-sources:放各个依赖的源码
  • ffmpeg-build:所有依赖的安装前缀(.a 和头文件都在这里)
  • bin:最终 ffmpeg/ffprobe 二进制落在这里

编译工具链(Ubuntu/Debian):

sudo apt-get update && sudo apt-get install -y \
  build-essential cmake git pkg-config yasm nasm \
  autoconf automake libtool meson ninja-build \
  python3 python3-pip texinfo wget curl

CentOS 7 上对应的是:

sudo yum groupinstall -y "Development Tools"
sudo yum install -y cmake3 git yasm nasm pkgconfig autoconf automake libtool

CentOS 7 的 cmake 是 2.8,编 x265 会失败,要用 cmake3,或者自己装新版 cmake(我选了后者,从 cmake 官网下了 3.28 的 binary tarball 解压到 ~/tools 然后加 PATH,比跟 yum 源较劲快)。

有个小建议:编译目录放 SSD,且保证至少 10GB 剩余。x265 和 aom 编起来临时文件不小,我有一次在还剩 3GB 的盘上编到一半 No space left on device,重来了一遍。

三、把依赖一个个编成静态库

按我的需求,最终要带的是:x264、x265、libvpx(VP9)、fdk-aac、mp3lame、opus、openssl(https)。下面是逐个的命令和坑点。

x264

cd ~/ffmpeg-sources && \
git clone --depth 1 https://code.videolan.org/videolan/x264.git && \
cd x264 && \
PKG_CONFIG_PATH="$HOME/ffmpeg-build/lib/pkgconfig" \
  ./configure --prefix="$HOME/ffmpeg-build" --bindir="$HOME/bin" \
  --enable-static --disable-opencl --disable-cli && \
make -j$(nproc) && make install

--disable-cli 很关键。默认它会编出一个 x264 命令行工具,那玩意儿是动态链接的,编到一半可能因为找不到 .so 报错;我们只要 libx264.a。

x265

cd ~/ffmpeg-sources && \
git clone --depth 1 https://bitbucket.org/multicoreware/x265_git.git && \
cd x265_git/build/linux && \
cmake -G "Unix Makefiles" ../../source \
  -DCMAKE_INSTALL_PREFIX="$HOME/ffmpeg-build" \
  -DENABLE_SHARED=OFF \
  -DENABLE_CLI=OFF \
  -DENABLE_PIC=ON && \
make -j$(nproc) && make install

两个坑:

  1. ENABLE_SHARED=OFF 必须显式写,默认它是 ON,会编出 libx265.so,我们要的是 .a。
  2. x265 是 C++ 写的,后面链接 ffmpeg 的时候必须额外给 -lstdc++,否则一堆 undefined reference to std::xxx。这个后面第五节会再提一次,因为它坑了我半天。

libvpx(VP8/VP9)

cd ~/ffmpeg-sources && \
git clone --depth 1 https://chromium.googlesource.com/webm/libvpx.git && \
cd libvpx && \
./configure --prefix="$HOME/ffmpeg-build" --disable-examples \
  --disable-unit-tests --disable-shared --enable-static \
  --enable-vp9-highbitdepth --as=yasm && \
make -j$(nproc) && make install

--enable-vp9-highbitdepth 是我自己加的,因为要处理 10bit 的源。用不到可以去掉,能省一点体积。

fdk-aac

cd ~/ffmpeg-sources && \
git clone --depth 1 https://github.com/mstorsjo/fdk-aac.git && \
cd fdk-aac && \
autoreconf -fiv && \
./configure --prefix="$HOME/ffmpeg-build" --disable-shared --enable-static && \
make -j$(nproc) && make install

许可证提醒:fdk-aac 是 Fraunhofer 的 AAC 编码器,ffmpeg 把它归类为 nonfree。你一旦 --enable-libfdk-aac,编出来的 ffmpeg 二进制在法律上不允许分发给第三方(GPL 不兼容)。我这次是交付给客户内网自己用,属于"给对方编译",我跟客户明确说明了这一点,并给了一个不带 fdk-aac 的备用版本,用它自带的原生 aac 编码器。这个事情第十节还会讲,别嫌我啰嗦,真出事是法务来找你。

如果不想碰 nonfree,把 --enable-libfdk-aac 换成 ffmpeg 原生 aac(--enable-encoder=aac),质量差一点点,但省心。

mp3lame / opus

# lame
cd ~/ffmpeg-sources && \
curl -L -O https://downloads.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz && \
tar xzvf lame-3.100.tar.gz && cd lame-3.100 && \
./configure --prefix="$HOME/ffmpeg-build" --disable-shared --enable-static --enable-nasm && \
make -j$(nproc) && make install

# opus
cd ~/ffmpeg-sources && \
git clone --depth 1 https://github.com/xiph/opus.git && cd opus && \
./autogen.sh && \
./configure --prefix="$HOME/ffmpeg-build" --disable-shared --enable-static && \
make -j$(nproc) && make install

openssl(https/tls 协议)

cd ~/ffmpeg-sources && \
curl -L -O https://www.openssl.org/source/openssl-3.0.15.tar.gz && \
tar xzvf openssl-3.0.15.tar.gz && cd openssl-3.0.15 && \
./config --prefix="$HOME/ffmpeg-build" --openssldir="$HOME/ffmpeg-build/ssl" \
  no-shared no-tests && \
make -j$(nproc) && make install_sw

no-shared 是重点,要 .a。install_sw 比 install 快,跳过文档。

openssl 是静态链接时最容易出事的一环,因为它会用到 dlopen、getaddrinfo 这些 glibc 里"静态链接不干净"的东西。具体的报错和处理在第五节。

想再加 dav1d / SVT-AV1?

我这次没编,理由是客户机器上的源全是 H.264/H.265,AV1 解码用不上,编进去白白多 6MB。如果确实需要:

# dav1d(AV1 解码,meson 构建)
cd ~/ffmpeg-sources && git clone --depth 1 https://code.videolan.org/videolan/dav1d.git && \
cd dav1d && meson setup build --prefix="$HOME/ffmpeg-build" \
  --default-library=static --libdir=lib && \
ninja -C build && ninja -C build install

四、configure ffmpeg:参数逐条解释

依赖齐了,轮到主角:

cd ~/ffmpeg-sources && \
curl -L -O https://ffmpeg.org/releases/ffmpeg-7.1.tar.xz && \
tar xf ffmpeg-7.1.tar.xz && cd ffmpeg-7.1 && \
PKG_CONFIG_PATH="$HOME/ffmpeg-build/lib/pkgconfig" ./configure \
  --prefix="$HOME/ffmpeg-build" \
  --pkg-config-flags="--static" \
  --extra-cflags="-I$HOME/ffmpeg-build/include" \
  --extra-ldflags="-L$HOME/ffmpeg-build/lib -static" \
  --extra-libs="-lpthread -lm -ldl -lstdc++" \
  --bindir="$HOME/bin" \
  --enable-gpl --enable-nonfree \
  --enable-libx264 --enable-libx265 --enable-libvpx \
  --enable-libfdk-aac --enable-libmp3lame --enable-libopus \
  --enable-openssl \
  --disable-shared --enable-static \
  --disable-doc --disable-debug && \
make -j$(nproc) && make install

逐条说明我为什么这么写:

参数 作用 不写会怎样
PKG_CONFIG_PATH=... 让 pkg-config 找到我们自己编的 .pc 文件 找不到 x264,configure 报 ERROR: libx264 not found
--pkg-config-flags="--static" 让 pkg-config 输出静态链接所需的 -lxxx 全集 链接时缺符号
--extra-ldflags="... -static" 强制全静态链接 编出来是动态链接,ldd 一堆 .so
--extra-libs="-lpthread -lm -ldl -lstdc++" 补齐 pthread、数学库、dl 系列、C++ 标准库 openssl 的 dlopen 未定义;x265 的 std:: 未定义
--enable-gpl x264/x265 是 GPL configure 直接拒绝
--enable-nonfree fdk-aac 是 nonfree ERROR: libfdk_aac is nonfree
--disable-doc 不编文档 多花几分钟,多几十 MB 中间产物
--disable-debug 关调试符号 二进制大一圈

configure 跑完会打印一大段 "External libraries" 清单,务必扫一眼,确认你要的都在里面:

External libraries:
  libfdk_aac   libmp3lame   libopus   libvpx   libx264   libx265   openssl

如果某个库显示为 no 或者直接进了 "External libraries providing hardware acceleration" 之外的地方,说明 pkg-config 没找到,去 $HOME/ffmpeg-build/lib/pkgconfig 看看对应的 .pc 在不在。我第一次 x265 就漏了,原因是忘了 make install。

五、链接阶段:那些让人怀疑人生的报错

编译到最后一步 ld 的时候,我遇到了三个报错,贴原文和解法。

报错 1:getaddrinfo / dlopen 告警

WARNING: /usr/bin/ld: ... warning: Using 'getaddrinfo' in statically linked
applications requires at runtime the shared libraries from the glibc version
used for linking

这个不是致命错误,链接会成功,但运行时在 glibc 版本不同的机器上可能炸。我当时硬着头皮用了,在目标机上测 https 下载,确实能跑,但我心里不踏实。

三条路:

  1. 接受它,但保证编译机 glibc 不高于目标机(我这次的做法);
  2. 不要 openssl,用 --disable-openssl,只支持 http(省事,但 https 就废了);
  3. 换 musl 静态编译(第八节)。

报错 2:undefined reference to dlclose

/usr/bin/ld: libavformat.a(tls_openssl.o): undefined reference to symbol 'dlclose@@GLIBC_2.2.5'
/usr/bin/ld: /lib/x86_64-linux-gnu/libdl.so.2: error adding symbols: DSO missing from command line

缺 -ldl。加进 --extra-libs 里解决。这个报错很典型:它不告诉你少了什么库,只说 "DSO missing from command line",第一次看真的懵。

报错 3:x265 的 C++ 符号

/usr/bin/ld: libavcodec.a(libx265.o): undefined reference to `std::__cxx11::basic_string...'
/usr/bin/ld: undefined reference to `operator new(unsigned long)'

缺 -lstdc++。同理加进 --extra-libs。另外某些系统上 x265 还依赖 numa,会报 undefined reference to numa_alloc_onnode,两个办法:编 x265 时关掉(cmake 时不带 numa,或源码里 --disable-numa),或者加 -lnuma。

我的 --extra-libs 最终形态:

--extra-libs="-lpthread -lm -ldl -lstdc++ -lnuma"

报错 4(如果你用的是老 gcc):-fPIC 相关

/usr/bin/ld: libavcodec.a(x86/...o): relocation R_X86_64_32S against ... can not be used when making a PIE object

静态链接到非 PIE 时常见。加 --extra-ldflags="-no-pie" 或者 --extra-cflags="-fno-pie"。我在 CentOS 7 上遇到过一次,加上就好了。

六、从 78MB 裁到 16MB

第一版编出来我一看:ls -lh ~/bin/ffmpeg → 78MB。scp 到内网机器慢得要死,而且里面塞了一堆我用不到的东西(几百个 demuxer、几十个 encoder、一堆我从没听说过的协议)。

裁剪的核心思路是白名单:先 --disable-everything 全关,再一个个把要的打开。

PKG_CONFIG_PATH="$HOME/ffmpeg-build/lib/pkgconfig" ./configure \
  --prefix="$HOME/ffmpeg-build" \
  --pkg-config-flags="--static" \
  --extra-cflags="-I$HOME/ffmpeg-build/include" \
  --extra-ldflags="-L$HOME/ffmpeg-build/lib -static -no-pie" \
  --extra-libs="-lpthread -lm -ldl -lstdc++ -lnuma" \
  --bindir="$HOME/bin" \
  --enable-gpl --enable-nonfree \
  --enable-libx264 --enable-libx265 --enable-libvpx \
  --enable-libfdk-aac --enable-libmp3lame --enable-libopus \
  --enable-openssl \
  --disable-shared --enable-static --disable-doc --disable-debug \
  --disable-everything \
  --enable-protocol=file,http,https,tls,tcp,udp,pipe \
  --enable-demuxer=mov,mp4,m4v,mpegts,matroska,webm,flv,hls,aac,mp3,wav,image2,concat \
  --enable-muxer=mp4,mov,mpegts,matroska,webm,flv,mp3,null,image2 \
  --enable-decoder=h264,hevc,vp8,vp9,aac,mp3,opus,vorbis,flac,png,mjpeg \
  --enable-encoder=libx264,libx265,libvpx_vp9,libfdk_aac,libmp3lame,libopus,aac,png,mjpeg \
  --enable-parser=h264,hevc,vp8,vp9,aac,mpegaudio,opus \
  --enable-bsf=h264_mp4toannexb,hevc_mp4toannexb,aac_adtstoasc,extract_extradata \
  --enable-filter=scale,crop,overlay,concat,trim,format,null,fps,setpts,subtitles,amix,volume \
  --enable-swscale --enable-swresample --enable-avformat --enable-avcodec --enable-avutil

体积变化实测(我那台机器上):

版本 大小 说明
默认全量静态 78.4 MB 什么都能干
全量 + strip 71.9 MB strip 掉符号表,省 6MB
白名单裁剪 21.6 MB 只保留业务要的
白名单 + strip 16.3 MB 最终交付版

strip 别忘了:

strip -s ~/bin/ffmpeg
cp ~/bin/ffmpeg ~/bin/ffmpeg-debug  # 建议先留一份带符号的,方便日后 gdb

裁剪最大的风险是漏项,而且它不会在编译期报错,只会在运行时报。我第一版裁剪完,测 HLS 的时候直接:

[hls @ 0x...] Unable to find a suitable output format

查了半天才发现 hls 我只在 demuxer 里开了,muxer 忘了。所以裁剪完一定要跑一遍你所有的真实业务命令,别只测一条。

顺手记一下我常用的"查到底要开哪些组件"的方法:不裁剪的时候用 ffmpeg -formats、-codecs、-protocols、-filters 看全量名字,再从业务命令里反推要哪些。或者直接看编译时 config.h 里的 CONFIG_XXX。

七、验证:别只在编译机上跑通就交付

我吃过这个亏:在编译机上 ffmpeg -version 一切正常,交付过去客户一跑就报缺库。原因是编译机上系统本来就有那些 .so,掩盖了问题。

验证清单(按顺序做):

1. 看是不是真的静态

ldd ~/bin/ffmpeg
# 期望输出:不是动态可执行文件 / not a dynamic executable

如果 ldd 列出一堆 .so,说明没静态成功,回去检查 --disable-shared --enable-static 和 --extra-ldflags。

2. file 看一眼

file ~/bin/ffmpeg
# ffmpeg: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, ...

3. 在干净容器里跑真命令

这是我最信任的一招。编译机上装个 docker 或者用目标系统的最小镜像:

docker run --rm -v ~/bin:/ff -w /ff centos:7 ./ffmpeg -version
docker run --rm -v ~/bin:/ff -v /tmp/media:/m -w /ff centos:7 \
  ./ffmpeg -y -i /m/in.mp4 -c:v libx265 -crf 28 -c:a libfdk_aac -vbr 4 /m/out.mp4

能转码出文件且退出码为 0,才算真的过。顺带一提,这个容器测试还能验证 glibc 兼容性——centos:7 镜像的 glibc 就是 2.17。

4. 检查编码器清单

~/bin/ffmpeg -hide_banner -encoders 2>/dev/null | grep -E 'libx264|libx265|libfdk|libvpx'

5. 跑一遍 HTTPS 拉流(验证 openssl)

~/bin/ffmpeg -hide_banner -i "https://example.com/stream.m3u8" -t 5 -f null -

报 Protocol not found 说明 openssl/tls 协议没进去;报证书问题(内网自签证书)需要 -tls_verify 0 或者给 CA。

6. 别忘了 ffprobe

make install 会一起编出 ffprobe。我一开始就忘了测它,结果客户那边调 ffprobe 报缺库——它也是静态的,但链接参数跟 ffmpeg 不完全一样,务必一起测。

八、musl 路线:什么时候该换赛道

如果你遇到的情况符合下面任意一条,我建议别在 glibc 上死磕:

  • 目标机器 glibc 版本比你能拿到的编译机还老;
  • 你必须要 openssl/tls,又不想被 getaddrinfo 告警悬着心;
  • 你要编的是真的"一个文件走天下",可能扔到各种发行版上跑。

换 musl/ Alpine:

docker run -it --rm -v ~/ffmpeg-out:/out alpine:3.20 sh
# 容器内
apk add --no-cache build-base cmake git pkgconf yasm nasm autoconf automake libtool \
  meson ninja python3 linux-headers openssl-dev openssl-libs-static zlib-static \
  libstdc++ argp-standalone

musl 下静态链接干净很多,几乎没有 getaddrinfo 那套告警。代价是:

对比项 glibc 静态 musl 静态
链接告警 有(getaddrinfo/dlopen) 基本没有
兼容性 依赖编译机 glibc 版本 极好,扔哪都能跑
性能 略好(尤其多线程 malloc) 部分场景 malloc 稍慢
踩坑成本 高 中(要适应 apk 和 musl 特性)

我在第二个项目(给一台嵌入式盒子编译)上走的 musl 路线,同样的需求,一天搞定,比第一次省了两天。所以我的建议是:如果目标机器不确定,直接用 musl;如果目标机器明确是某个老 RHEL/CentOS,且你手上有同版本系统,那 glibc 静态也够用。

九、想带 NVENC 硬件加速怎么办

这是另一个高频需求,而且跟"静态"有点冲突,得单独说。

硬件编码要加这些:

--enable-nonfree --enable-cuda --enable-cuda-nvcc --enable-nvenc --enable-cuvid \
--nvccflags="-gencode arch=compute_75,code=sm_75" \
--extra-cflags="-I/usr/local/cuda/include" \
--extra-ldflags="-L/usr/local/cuda/lib64"

arch=compute_75 要按你的显卡架构改:T4/RTX20 系是 75,RTX30 系是 86,A100 是 80,V100 是 70。写错了编得出来但跑不起来,报 no NVIDIA device found 之类。查自己卡的算力:

nvidia-smi --query-gpu=compute_cap,name --format=csv

关键结论:NVENC 这条路不可能做到完全静态。原因有二:

  1. CUDA runtime 官方早就不提供静态库(libcudart_static.a 虽然还在,但不推荐且兼容坑多);
  2. 更致命的是显卡驱动:NVENC 需要运行时的 libnvidia-encode.so,这个库由驱动提供,版本号必须跟驱动匹配。你把它静态编进去,等于把驱动版本焊死,换台机器驱动版本不对直接 Cannot load libnvidia-encode.so.1。

所以带 NVENC 的版本,我的做法是:ffmpeg 本体静态,CUDA/NVENC 部分动态。也就是不写 -static,让它链接系统的 libcudart 和运行时加载 libnvidia-encode。交付的时候附带说明:目标机器必须装 ≥ 某版本的 NVIDIA 驱动。

# 验证 NVENC 可用
ffmpeg -hide_banner -f lavfi -i testsrc=size=1920x1080:rate=30:duration=5 \
  -c:v h264_nvenc -preset p4 /tmp/nvenc_test.mp4

跑通不代表生产可用。我一般会再压一段真实素材,对比 h264_nvenc 和 libx264 在相同码率下的质量(用 VMAF 测,这篇不讲,是另一个话题了),确认客户能接受画质损失再上。

十、我踩过的坑清单

按"浪费时间多少"排序,全是真金白银换来的:

  1. 在高版本系统上编、拿到低版本系统跑 → GLIBC_2.28 not found。浪费一晚。解法:编译机系统版本 ≤ 目标机。
  2. 忘了 --disable-cli,x264 编出动态命令行工具报错 → 加 --disable-cli。
  3. x265 用默认参数编出 .so → 加 -DENABLE_SHARED=OFF。
  4. 链接时缺 -lstdc++ → x265 的 C++ 符号全未定义。
  5. 链接时缺 -ldl → openssl 的 dlopen 未定义,报错信息完全不提示是哪个库。
  6. 裁剪漏了 muxer/demuxer → 编译不报错,运行才报 Unable to find a suitable output format。裁剪后必须全量测一遍业务命令。
  7. make -j$(nproc) 在内存小的机器上把编译进程干掉 → 4GB 内存机器编 x265 时 OOM,signal: killed。改 -j2 或者加 swap。
  8. 改了 configure 参数没 make clean → 出来一个半新半旧的二进制,行为诡异。改参数后先 make distclean(注意 distclean 会清掉 config,得重新 configure,这是对的)。
  9. 只测 ffmpeg -version 就交付 → 客户一跑真实命令就挂。必须跑真实业务命令。
  10. 忘了 ffprobe → 它要单独测。
  11. 没留带符号的版本 → strip 之后出问题没法 gdb。先 cp 一份再 strip。
  12. fdk-aac 的许可证没提前说 → 客户法务后来问了一轮。现在我会主动在交付文档里写清楚哪些组件是 nonfree。

十一、交付与合规

最后说说交付这件事,因为技术之外这块最容易翻车。

交付物清单(我现在的固定格式):

ffmpeg              # 静态二进制
ffprobe             # 静态二进制
BUILD_INFO.txt      # 编译命令 + configure 参数原文
VERSION.txt         # ffmpeg 版本、依赖版本、编译机系统/glibc 版本
LICENSE_NOTICE.txt  # 组件许可证说明

BUILD_INFO.txt 里我把 configure 那条命令原样贴进去,方便半年后有人问"这个 ffmpeg 到底开了啥"时能一秒回答。这个习惯是踩过坑之后养成的——有次线上出奇怪的编码问题,翻了半天才搞清楚是当初少编了一个 bsf。

许可证相关(不是法律建议,是我自己的处理原则):

  • libx264、libx265 是 GPL。开了 --enable-gpl 编出来的二进制,如果你把它分发给外部,理论上需要提供源码或编译说明。给客户内网部署、自己在服务器上用,一般不构成分发,但我会在文档里附上完整的编译脚本,对方要源码就能复现。
  • libfdk-aac 是 nonfree,跟 GPL 不兼容,不能分发。我的做法是默认不带它,除非客户明确要 AAC 的高码率质量,且我确认是他们自己内部使用。
  • 视频编码本身涉及专利池(H.264/H.265 的 MPEG-LA / HEVC Advance 那套)。商用产品里内置编码器要不要交专利费,这不是技术问题,交给法务判断。

给目标机器的部署建议:

sudo mkdir -p /opt/ffmpeg
sudo cp ffmpeg ffprobe /opt/ffmpeg/
sudo chmod +x /opt/ffmpeg/*
# 不要覆盖系统 ffmpeg,用 alternatives 或者显式 PATH
sudo update-alternatives --install /usr/bin/ffmpeg ffmpeg /opt/ffmpeg/ffmpeg 50

我一般不会直接覆盖 /usr/bin/ffmpeg,因为机器上可能有别的服务依赖系统版本。用 alternatives 或者干脆在业务脚本里写全路径 /opt/ffmpeg/ffmpeg,最省事也最不容易背锅。


回过头看,编译静态 ffmpeg 这件事本身没什么高深技术,绝大部分时间花在了"报错信息看不懂 → 猜 → 试 → 验证"的循环上。真正的收益不是那个 16MB 的二进制,而是我把整条依赖链摸清楚了:现在再遇到"这个格式不支持""那个协议找不到",我基本能立刻判断是 configure 少开了什么,而不是像第一次那样去网上瞎搜。

如果你也在做类似的事,我的建议只有一条:先把目标机器的约束(glibc 版本、有没有 root、要不要 https、要不要硬件编码)写下来,再决定编译策略。这四件事决定了你走 glibc 静态、musl 静态还是干脆上容器,选错了就是几天的返工。

想亲手试试?用 VidDown 一键解析下载

粘贴视频链接即可解析,多平台支持、网页端即用;下载桌面客户端解锁海外平台本地解析,开通会员更享不限次下载。

顶部