FFmpeg Cross-Platform Build System (iOS, macOS, tvOS, Android) - FFmpeg 7.1 Technical Manual
中文版 (Chinese Version)
Acknowledgement: This project is based on and improved from kewlbear/FFmpeg-iOS-build-script, deeply adapted and refactored for modern Xcode, Apple Silicon, and FFmpeg 7.0+.
This is an enterprise-level collection of Shell scripts designed to solve the complexity of cross-compiling FFmpeg for iOS, tvOS, macOS, and Android on macOS. It is not just a compilation script, but a complete solution for dependency management and artifact packaging.
Based on the FFmpeg 7.1 core, this project integrates mainstream codec libraries such as x264, x265, fdk-aac, dav1d, lame, opus, vpx, vorbis, and theora, and provides the ability to generate a Framework with one click, perfectly supporting Swift and Objective-C projects.
📚 Table of Contents
- System Architecture & Workflow
- Prerequisites & Dependencies
- Build Guide
- Integration Guide
- Technical Deep Dive
- Configuration & Customization
- Dependency Management & Build Internals
- Directory Structure
- Script Reference
- Licensing & Compliance
🏗 System Architecture & Workflow
This build system adopts a modular design, following the workflow of "Compile dependencies first, then compile the core, and finally package".
graph TD
subgraph "Phase 1: Dependencies Build"
A[Dependency Source<br/>x264/lame/...] -->|build-xxx.sh| B(Single Arch Lib<br/>thin/arm64/libxxx.a)
B -->|lipo| C(Universal Static Lib<br/>fat-xxx/lib/libxxx.a)
end
subgraph "Phase 2: FFmpeg Core Build"
D[FFmpeg Source<br/>ffmpeg-7.1]
E[Fake pkg-config<br/>tools_bin/] -->|Path Injection| D
C -->|pkg-config discovery| D
D -->|build-ffmpeg.sh| F(FFmpeg Single Arch Lib<br/>thin/arm64/libavcodec.a)
F -->|lipo| G(FFmpeg Universal Lib<br/>FFmpeg-iOS/lib/...)
end
subgraph "Phase 3: Packaging"
G -->|build-ffmpeg-iOS-framework.sh| H{Final Artifact<br/>FFmpeg.framework}
C -->|libtool static merge| H
end
style H fill:#f96,stroke:#333,stroke-width:2px
🛠 Prerequisites & Dependencies
Ensure your macOS development environment is complete before starting.
1. Xcode & Command Line Tools
Ensure the latest version of Xcode is installed and run the following command to install command line tools:
xcode-select --install
2. Build Tools (Homebrew)
FFmpeg and its dependencies require a set of build tools. Install them using Homebrew:
# Basic compilation tools
brew install yasm nasm cmake pkg-config
# Build systems for specific 3rd-party libs
brew install meson ninja # for dav1d
brew install autoconf automake libtool # for fdk-aac, lame, etc.
- yasm/nasm: Assemblers, crucial for x264/x265 performance.
- cmake/meson: Build systems for modern C++ projects.
- pkg-config: Dependency management tool, core to this script for discovering compiled libraries.
- gas-preprocessor.pl: (Automatically downloaded) Converts GNU assembly syntax to Apple Clang compatible syntax.
🚀 Build Guide
iOS (iPhone/iPad)
iOS builds are the most complex as they usually involve the most 3rd-party libraries.
Step 1: Compile Dependency Libraries (Optional)
The scripts are designed to be loosely coupled. If you don't need a library (e.g., x265), simply skip the corresponding script. build-ffmpeg.sh automatically detects which libraries have been compiled.
Recommended build order:
# 1. Basic Codecs
./build-x264.sh # H.264 (GPL)
./build-fdk-aac.sh # AAC (Non-Free)
./build-lame.sh # MP3
# 2. Advanced Codecs (On Demand)
./build-x265.sh # H.265 (GPL, takes longer to compile)
./build-dav1d.sh # AV1 Decoding
./build-opus.sh # Opus Audio
./build-vpx.sh # VP8/VP9
# 3. Ogg Ecosystem (Must follow order)
./build-ogg.sh # Base layer
./build-vorbis.sh # Depends on Ogg
./build-theora.sh # Depends on Ogg
Step 2: Compile FFmpeg Core
./build-ffmpeg.sh
This step performs the following:
- Downloads FFmpeg 7.1 source code.
- Scans for
fat-* folders in the current directory.
- Configures
pkg-config paths to inject 3rd-party libraries into the FFmpeg build configuration.
- Compiles for
arm64 (Device) and x86_64 (Simulator) separately.
- Uses
lipo to merge and generate the FFmpeg-iOS directory.
Step 3: Package Framework
./build-ffmpeg-iOS-framework.sh
This script is extremely important. It merges all compiled static libraries (including libx264.a, libmp3lame.a, etc.) into a single binary within FFmpeg.framework. This means you do not need to manually add dozens of .a files in Xcode.
macOS (Apple Silicon/Intel)
./build-ffmpeg-macos.sh
- Features: Enables
VideoToolbox (Hardware Acceleration) and AudioToolbox.
- Archs: Includes
arm64 and x86_64, the generated Framework is ready for macOS App development.
tvOS (Apple TV)
./build-ffmpeg-tvos.sh
- Strategy: tvOS App Store reviews are strict, and device performance is uniform. The script defaults to not integrating 3rd-party libraries to ensure maximum stability and pass review. Relies solely on FFmpeg internal software decoding and VideoToolbox hardware decoding.
Android
# Set NDK path first
export ANDROID_NDK_HOME=/path/to/ndk
./build-ffmpeg-android.sh
- Artifacts:
.so dynamic libraries in FFmpeg-Android/jniLibs/.
- Archs:
arm64-v8a, armeabi-v7a, x86, x86_64.
🔌 Integration Guide
Xcode Integration
-
Import Framework: Drag FFmpeg.framework into your project.
-
Set Embed: In General -> Frameworks, Libraries, and Embedded Content, set it to Do Not Embed (since it's a statically linked framework).
-
Add System Libraries: In Build Phases -> Link Binary With Libraries, add the following system libraries to avoid Undefined symbol errors:
libz.tbd (Compression)
libbz2.tbd (Compression)
libiconv.tbd (Character Encoding)
AudioToolbox.framework (Audio Processing)
VideoToolbox.framework (Hardware Decoding)
CoreMedia.framework
AVFoundation.framework
libc++.tbd (If C++ libraries like x265/dav1d are integrated)
-
Header Search Paths:
In Build Settings, find Header Search Paths and add:
$(PROJECT_DIR)/FFmpeg.framework/Headers
This allows you to use #include "libavcodec/avcodec.h".
Fixing Linker Errors
- Error:
Undefined symbol: _VTDecompressionSessionCreate
- Fix: Missing
VideoToolbox.framework.
- Error:
Undefined symbol: _inflate
- Error:
Undefined symbol: operator new(unsigned long)
- Fix: Missing
libc++.tbd (Usually because x265 or dav1d are written in C++).
🔬 Technical Deep Dive
This set of scripts is more than just simple configure and make calls; it includes a series of "black magic" fixes and optimizations for the iOS/tvOS compilation environment.
1. Intelligent Dependency Injection (pkg-config Hijacking)
FFmpeg's build system relies heavily on pkg-config to find 3rd-party libraries (like x264, x265). In a cross-compilation environment, making FFmpeg correctly find our locally compiled iOS static libraries (instead of the system-installed macOS libraries) is a major pain point.
Script Solution (build-ffmpeg.sh):
- Virtual Environment: The script dynamically creates a fake
pkg-config script in the tools_bin/ directory.
- Path Redirection: When FFmpeg requests the path for
x264, this fake script intercepts the request and forcibly returns the header and library paths from our local fat-x264/ directory.
- Advantage: Completely solves "Package xxxxx was not found" issues without polluting system environment variables.
2. Assembly Code Compatibility (Assembly & Bitcode)
FFmpeg contains a large amount of assembly code optimized for specific CPUs, but this often causes errors with the iOS Clang compiler.
- Gas-Preprocessor: The script automatically detects and downloads
gas-preprocessor.pl, a Perl script that converts GNU Assembler (GAS) syntax into Apple Clang compatible syntax.
- VVC Module Masking: The VVC (H.266) decoder introduced in FFmpeg 7.1 contains a large amount of new AArch64 assembly that currently has compatibility issues with the iOS cross-compilation toolchain. The script automatically avoids this compilation error via
--disable-vvc to ensure overall build success.
- Bitcode Support: Enabled by default with
-fembed-bitcode flag, ensuring compiled static libraries contain Bitcode segments (although deprecated in Xcode 14, retained for compatibility with older projects).
3. Modern Framework Encapsulation
Traditional scripts usually only generate .a files. This project's build-ffmpeg-iOS-framework.sh script does more:
- All-in-One Binary: Uses
libtool -static to merge all compiled static libraries (including FFmpeg core and enabled 3rd-party libraries like x264, LAME, etc.) into a single executable file within the Framework. This means you don't need to link multiple .a files in your project.
- Module Map: Automatically generates
module.modulemap file, allowing direct use of import FFmpeg in Swift projects.
- Umbrella Header: Automatically generates
FFmpeg.h umbrella header.
4. Special Handling for tvOS
The tvOS version aims for maximum stability and follows a minimalist principle:
- No 3rd-party Libraries: To avoid complex