在 macOS 上从源代码构建适用于 iOS 的 FFmpeg
本页面介绍了如何配置并构建适用于 iOS 的FFmpeg框架。iOS 版本的编译属于交叉编译,且假定使用 macOS 作为主机系统。所需步骤如下:
- 获取 FFmpeg 源代码。
- 安装所需的依赖项。
- 通过命令行配置 FFmpeg。
- 构建开发库。
- 基于 FFmpeg 库创建 iOS 框架。
- 创建 XCFrameworks。
- 将框架嵌入到应用程序包中。
获取 FFmpeg 源代码
您可以通过以下方式获取 FFmpeg 源代码:
- 从FFmpeg 下载页面下载。
- 从 Git 克隆。例如,以下命令将 FFmpeg 9.0.1 版本的源代码克隆到
~/ffmpeg。git clone --branch n9.0.1 https://git.ffmpeg.org/ffmpeg.git ffmpeg
建议使用与Qt Multimedia 主页中所述相同的 FFmpeg 版本。
下文假设您将 FFmpeg 源代码存储在~/ffmpeg 目录下。
先决条件
要构建 FFmpeg,需要以下工具和软件包:
- Xcode,它提供了工具链(编译器、链接器及其他工具)以及用于构建和链接的 iOS 平台 SDK(头文件和库)。
配置和构建 FFmpeg
在~/ffmpeg 目录下创建build 和installed 目录,然后进入build 目录:
mkdir ~/ffmpeg/build
mkdir ~/ffmpeg/installed
cd ~/ffmpeg/build要配置 FFmpeg,请运行:
../ffmpeg_src/configure --disable-programs --disable-doc --enable-network --enable-shared --disable-static \
--sysroot="$(xcrun --sdk iphoneos --show-sdk-path)" \
--enable-cross-compile \
--arch=arm64 \
--prefix=../installed \
--cc="xcrun --sdk iphoneos clang -arch arm64" \
--cxx="xcrun --sdk iphoneos clang++ -arch arm64" \
--extra-cflags="-miphoneos-version-min=16.0" \
--extra-cxxflags="-miphoneos-version-min=16.0" \
--extra-objcflags="-miphoneos-version-min=16.0" \
--extra-ldflags="-miphoneos-version-min=16.0" \
--install-name-dir='@rpath' \
--disable-audiotoolbox不需要命令行程序和文档;应启用网络功能。我们构建共享库,不需要静态库(若要构建静态库,请省略--disable-static )。--sysroot 指定了交叉构建树的根目录。--prefix 参数指定了构建完成后 FFmpeg 库的安装路径。 我们是在 macOS 主机上为 iOS 目标进行构建,因此启用了交叉编译。--extra-ldflags 设置了 iOS 的最低版本。--install-name-dir 是一个字符串,用于指定在 Apple 平台上已安装目标的共享库的“install_name”字段中的目录部分。 AudioToolBox 已被禁用,因为 FFmpeg 使用了 AudioToolBox 框架中某些在 iOS 上不可用的部分。
注意:在上例中,将 'iphoneos' 替换为 'iphonesimulator',将 'miphoneos-version' 替换为 'mios-simulator-version-min',即可将 FFmpeg 配置为构建适用于 iOS 模拟器的库。
如需获取其他配置选项的帮助,请运行:
../ffmpeg_src/configure --help配置完成后,构建 FFmpeg 库:
make -j install从 FFmpeg 库创建 iOS 框架
要在 iOS 应用程序中使用,必须将 FFmpeg 动态库转换为框架并嵌入到应用程序包中。框架是一个分层目录,它将动态库、图像文件、本地化字符串、头文件和参考文档等资源封装在一个单一包中。 在本例中,FFmpeg 框架仅包含动态库和相应的 Info.plist 文件。例如,转换为框架后的 libavcodec 将形成名为libavcodec.framework 的目录,其中包含以下内容:
- Info.plist(包含框架的描述)
- libavcodec(动态库)
与上一步中构建的动态库不同,iOS 框架内的动态库没有版本号,且不带 'dylib' 扩展名。这要求我们修正动态库中的库标识名和依赖关系。otool 工具可帮助我们查找这些名称。例如:
otool -L ../installed/lib/libavcodec.dylib会返回以下名称(此处仅展示与 FFmpeg 相关的名称):
@rpath/libavcodec.61.dylib (compatibility version 61.0.0, current version 61.19.100)
@rpath/libswresample.5.dylib (compatibility version 5.0.0, current version 5.3.100)
@rpath/libavutil.59.dylib (compatibility version 59.0.0, current version 59.39.100)要修正这些名称,请使用install_name_tool 工具。该工具的选项包括:
-id- 允许更改共享库的标识名称。-change- 允许更改依赖的共享库安装名称。
该脚本将先前构建的动态库转换为框架。代码假设您从 `build ` 目录运行该脚本,且框架位于 `~/ffmpeg/installed/framework` 中:
#!/usr/bin/env bash
# Creates an Info.plist file for a given framework:
build_info_plist() {
local file_path="$1"
local framework_name="$2"
local framework_id="$3"
# Minimum version must be the same we used when building FFmpeg.
local minimum_version_key="MinimumOSVersion"
local minimum_os_version="16.0"
local supported_platforms="iPhoneOS"
info_plist="<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${framework_name}</string>
<key>CFBundleIdentifier</key>
<string>${framework_id}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${framework_name}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>9.0.1</string>
<key>CFBundleVersion</key>
<string>9.0.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>${minimum_version_key}</key>
<string>${minimum_os_version}</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>${supported_platforms}</string>
</array>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>"
echo $info_plist | tee ${file_path} 1>/dev/null
}
dylib_regex="^@rpath/.*\.dylib$"
# Creates framework from a dylib file:
create_framework() {
local framework_name="$1"
local ffmpeg_library_path="../installed"
local framework_complete_path="${ffmpeg_library_path}/framework/${framework_name}.framework/${framework_name}"
# Create framework directory and copy dylib file to this directory:
mkdir -p "${ffmpeg_library_path}/framework/${framework_name}.framework"
cp "${ffmpeg_library_path}/lib/${framework_name}.dylib" "${ffmpeg_library_path}/framework/${framework_name}.framework/${framework_name}"
# Change the shared library identification name, removing version number and 'dylib' extension;
# \c Frameworks part of the name is needed since this is where frameworks will be installed in
# an application bundle:
install_name_tool -id @rpath/Frameworks/${framework_name}.framework/${framework_name} "${framework_complete_path}"
# Add Info.plist file into the framework directory:
build_info_plist "${ffmpeg_library_path}/framework/${framework_name}.framework/Info.plist" "${framework_name}" "io.qt.ffmpegkit."${framework_name}
otool -L "$framework_complete_path" | awk '/\t/ {print $1}' | egrep "$dylib_regex" | while read -r dependency_path; do
found_name=$(tmp=${dependency_path/*\/}; echo ${tmp/\.*})
if [ "$found_name" != "$framework_name" ]
then
# Change the dependent shared library install name to remove version number and 'dylib' extension:
install_name_tool -change "$dependency_path" @rpath/Frameworks/${found_name}.framework/${found_name} "${framework_complete_path}"
fi
done
}
ffmpeg_libs="libavcodec libavformat libavutil libswresample libswscale"
for name in $ffmpeg_libs; do
create_framework $name
done创建多平台二进制框架包
XCFramework 包是一个包含构建多平台(例如 iOS 和 iOS 模拟器)所需框架及库的软件包。要创建此类框架,请使用xcodebuild 实用程序。例如,如果 iOS 和模拟器的框架分别位于~/ffmpeg/installed/arm64 和~/ffmpeg/installed/arm64-simulator 目录中,则该实用程序的参数如下所示:
xcodebuild -create-xcframework -framework ../installed/arm64/libavcodec.framework -framework ../installed/arm64-simulator/libavcodec.framework -output ../installed/framework/libavcodec.xcframework嵌入框架
将 FFmpeg 框架嵌入应用程序包中。有关如何使用 Xcode 嵌入框架的信息,请参阅
《在应用程序中嵌入框架》。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.