Docker 构建流程
本文档描述了用于将 FFmpeg 及其依赖项编译为 ffmpeg.wasm WebAssembly 模块的基于 Docker 的构建系统。该构建过程创建了可在 Web 浏览器中运行的单线程和多线程版本的 FFmpeg 核心。
概述
ffmpeg.wasm 项目使用 Docker 来提供一致且可重复的构建环境,以便将 FFmpeg 及其相关库编译为 WebAssembly。此过程对于创建 @ffmpeg/core 和 @ffmpeg/core-mt 包至关重要,这些包包含驱动 ffmpeg.wasm 的编译后的 WebAssembly 模块。
该构建被设计为一个多阶段 Dockerfile,将库的编译与最终的链接阶段隔离开来,确保对某一编解码器的修改不需要对整个堆栈进行完全重建。
构建流水线图示
Title: Docker Build Pipeline Flow
构建环境 (emsdk-base)
构建过程从 emsdk-base 阶段开始,该阶段使用官方的 Emscripten 镜像并配置交叉编译环境。
| 组件 | 版本 / 值 | 文件引用 |
|---|---|---|
| 基础镜像 | emscripten/emsdk:3.1.40 | |
| FFmpeg 版本 | n5.1.4 | |
| 安装前缀 | /opt | |
| 工具链文件 | $EMSDK/.../Emscripten.cmake |
关键环境变量如 CFLAGS 和 LDFLAGS 在此处初始化,以包含 /opt/include 和 /opt/lib 路径,确保后续库阶段能够找到其依赖项
库编译阶段
每个依赖项都在其自己的 FROM emsdk-base AS <lib>-builder 阶段中进行编译。这使得 Docker 可以缓存像 x264 或 libvpx 这样重型库的编译结果。
Title: Code Entity Mapping: Library Builders
依赖链示例
- libass: 需要
freetype2、fribidi和harfbuzz。Dockerfile 使用COPY --from将这些依赖聚合到libass-builder阶段,然后再运行build/libass.sh - theora/vorbis: 两者都依赖于
ogg,因此它们通过COPY --from=ogg-builder访问libogg的头文件和二进制文件
FFmpeg 编译 (ffmpeg-builder)
ffmpeg-base 阶段将之前所有已编译的库聚合到 /opt 目录中。ffmpeg-builder 阶段随后运行 build/ffmpeg.sh 来编译实际的 FFmpeg 源代码。
配置标志
build/ffmpeg.sh 脚本使用 emconfigure 来设置 WebAssembly 的构建:
--target-os=none和--arch=x86_32- 禁用硬件功能,如
asm和runtime-cpudetect - 分配 Emscripten 工具链别名:
emcc、emar、emnm - 条件化线程支持:如果定义了
FFMPEG_ST,则传递--disable-pthreads
ffmpeg.wasm 最终链接 (ffmpeg-wasm-builder)
这是最关键的阶段,Emscripten 编译器 (emcc) 在此阶段将 FFmpeg 目标文件与 JavaScript 绑定链接在一起,生成最终的 .js 和 .wasm 文件。
Emscripten 链接标志
脚本 build/ffmpeg-wasm.sh 定义了用于最终 emcc 调用的 CONF_FLAGS :
| 标志 | 用途 | 引用 |
|---|---|---|
-sMODULARIZE | 将输出包装在工厂函数 (createFFmpegCore) 中 | |
-sEXPORT_NAME | 设置全局工厂名称 | |
-sENVIRONMENT=worker | 针对 Web Worker 执行进行优化 | |
-sPTHREAD_POOL_SIZE=32 | (仅 MT) 预启动 32 个工作线程以处理并行任务 | |
-sALLOW_MEMORY_GROWTH | (仅 ST) 允许 WASM 堆动态扩展 | |
--pre-js | 注入 src/bind/ffmpeg/bind.js,其中包含 JS API 粘合代码 |
导出的函数
构建过程使用辅助脚本来确定哪些 C 函数对 JavaScript 可见:
src/bind/ffmpeg/export.js: 定义核心函数,如_ffmpeg、_ffprobe、_malloc和_abortsrc/bind/ffmpeg/export-runtime.js: 导出 Emscripten 运行时方法
单线程与多线程逻辑
Dockerfile 通过向构建脚本传递不同的参数来处理两种构建。
Title: Threading Logic in build/ffmpeg-wasm.sh
请注意,在多线程 (MT) 构建中明确避免了 ALLOW_MEMORY_GROWTH,因为它在某些环境中与 SharedArrayBuffer 不兼容或性能不佳,从而导致巨大的 1024MB 初始分配
工件导出 (exportor)
最后阶段使用 scratch 镜像以最小化输出大小。仅将包含 UMD 和 ESM 格式的编译后 JS 和 WASM 的 /dist 目录复制出来。
要获取这些资源,用户需执行:docker buildx build -o . .