Building FFmpeg from source for iOS on macOS
This page explains how to configure and build FFmpeg for iOS as frameworks. Compilation for iOS is a cross-compilation and presumes using macOS as a host system. The required steps are:
- Preparing build environment
- Getting the FFmpeg source code
- Configuring FFmpeg from the command line
- Building dynamic libraries
- Creating iOS frameworks from FFmpeg libraries
- Creating XCFrameworks
- Embedding frameworks
Note: The following documentation assumes that you work with FFmpeg libraries and code under ~/ffmpeg
.
Preparing build environment
The build environment for iOS is provided by Apple's Xcode application, which includes the toolchain (compiler, linker, and other tools), and the iOS platform-SDK (headers and libraries) that you build and link against.
Getting the FFmpeg source code
You can get the FFmpeg source code in these ways:
- Download from the FFmpeg download page.
- Clone from git. For example, these commands clone the version 7.1 of the FFmpeg sources to
~/ffmpeg/ffmpeg_src
.% cd ~/ffmpeg/ % git clone --branch n7.1 https://git.ffmpeg.org/ffmpeg.git ffmpeg_src
Note: It is recommended to use the same FFmpeg version as documented in the Qt Multimedia main page.
Configuring and building FFmpeg
Create a build
and installed
directories inside the ~/ffmpeg
directory and navigate into build
:
% mkdir ~/ffmpeg/build % mkdir ~/ffmpeg/installed % cd ~/ffmpeg/build
To configure FFmpeg, run:
% ../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-ldflags="-miphoneos-version-min=16.0" \ --install-name-dir='@rpath' \ --disable-audiotoolbox
The command line programs and documentation are not needed; network features should be enabled. We build shared libraries and don't need static libraries (omit --disable-static
to build static libraries). --sysroot
specifies the root of cross-build tree. The --prefix
argument specifies a path where the FFmpeg libraries are installed after building. We build on macOS host for iOS target so we enable cross compilation. --extra-ldflags
set the minimum version of iOS. --install-name-dir
is a string specifying the directory portion of the "install_name" field of shared libraries on Apple platforms for installed targets. AudioToolBox is disabled, since FFmpeg is using parts of AudioToolBox framework which are not available on iOS.
Note: In the example above, replacing 'iphoneos' with 'iphonesimulator', and 'miphoneos-version' with 'mios-simulator-version-min', configures FFmpeg to be built as libraries suitable for iOS simulator.
To get help on other configuration options, run:
% ../ffmpeg_src/configure --help
After configuration is complete, build FFmpeg libraries:
% make -j install
Creating iOS frameworks from FFmpeg libraries
To work in iOS applications, FFmpeg dynamic libraries have to be converted into frameworks and embedded into application bundles. A framework is a hierarchical directory that encapsulates resources such as a dynamic library, image files, localized strings, header files, and reference documentation in a single package. In our case, FFmpeg frameworks only contain dynamic libraries and corresponding Info.plist files. For example, libavcodec converted to framework becomes libavcodec.framework
directory with these contents:
- Info.plist (containing the description of the framework)
- libavcodec (dynamic library)
Unlike dynamic libraries we built in the previous step, dynamic libraries inside iOS frameworks are unversioned and have no 'dylib' extensions. This requires fixing library identification names and dependencies in our dynamic libraries. The otool
utility helps us to find such names. For example:
%otool -L ../installed/lib/libavcodec.dylib
gives us these names (we only show FFmpeg-related names):
@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)
To fix these names, use the install_name_tool
utility. The utility options are:
-id
- allows changing the shared library identification name.-change
- allows changing the dependent shared library install name.
This script converts the previously built dynamic libraries to frameworks. The code assumes that you run it from the build
directory and the frameworks are located in ~/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>7.0.2</string> <key>CFBundleVersion</key> <string>7.0.2</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
Creating a multiplatform binary framework bundle
An XCFramework bundle is a package that includes frameworks and libraries necessary to build for multiple platforms, for example, iOS and iOS simulator. To create such a framework, use the xcodebuild
utility. For example, if you have frameworks for iOS and simulator located in ~/ffmpeg/installed/arm64
and ~/ffmpeg/installed/arm64-simulator
directories, the utility arguments look like follows:
%xcodebuild -create-xcframework -framework ../installed/arm64/libavcodec.framework -framework ../installed/arm64-simulator/libavcodec.framework -output ../installed/framework/libavcodec.xcframework
Embedding frameworks
Embed the FFmpeg frameworks into an application bundle. For information on how to embed frameworks using XCode, refer to
© 2025 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.