QT使用FFMpeg编译安卓程序.md

一、准备工作:下载所需资源

资源 版本/说明 下载地址
FFmpeg 源码 7.1.5(与 Qt 6.11 内置版本一致) https://ffmpeg.org/releases/ffmpeg-7.1.5.tar.gz
Android NDK Windows 版 r26b (26.1.10909125) 或 r26d (26.3.11579264) https://developer.android.com/ndk/downloads
MSYS2 提供 Windows 下的类 Unix 编译环境 https://www.msys2.org/

⚠️ 关键点 :NDK 必须下载 Windows 版 (android-ndk-r26d-windows.zip),不能使用 Linux 版。

这只下载了FFmpeg 7.1.5源码和MSYS2,Android NDK使用QT自带的,目录位于/e/Android/android-sdk/ndk/27.2.12479018

二、配置 MSYS2 编译环境

  1. 安装 MSYS2 后,打开 MSYS2 MINGW64 终端(不是普通 MSYS2 终端)。

  2. 安装编译依赖:

    bash 复制代码
    pacman -S --noconfirm make yasm diffutils
  3. 设置环境变量(根据实际路径修改):

    bash 复制代码
    export PATH=/e/Qt/Tools/mingw1310_64/bin:$PATH
    export ANDROID_NDK_ROOT=/e/Android/android-sdk/ndk/27.2.12479018

三、在 Windows 下编译 FFmpeg for Android

  1. 解压 FFmpeg 源码到不含中文和空格的路径,例如 /e/ffmpeg/ffmpeg-7.1.5/ffmpeg-7.1.5。

  2. 在源码目录下创建 build_android.sh:

    bash 复制代码
    #!/bin/bash
    # 设置目标架构(这里以 arm64-v8a 为例)
    ARCH=aarch64
    CPU=armv8-a
    TOOLCHAIN_ARCH=aarch64-linux-android
    
    # NDK 工具链路径
    TOOLCHAIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/windows-x86_64
    # 最低支持的 Android API 级别,建议与你的 Qt 项目一致
    API=28
    
    # 进入源码目录
    cd /e/ffmpeg/ffmpeg-7.1.5/ffmpeg-7.1.5
    # 配置 FFmpeg
    ./configure \
      --prefix=./install-android/$ARCH \
      --target-os=android \
      --arch=$ARCH \
      --cpu=$CPU \
      --enable-cross-compile \
      --cross-prefix=$TOOLCHAIN/bin/llvm- \
      --cc=$TOOLCHAIN/bin/${TOOLCHAIN_ARCH}${API}-clang \
      --cxx=$TOOLCHAIN/bin/${TOOLCHAIN_ARCH}${API}-clang++ \
      --sysroot=$TOOLCHAIN/sysroot \
      --enable-shared \
      --disable-static \
      --disable-doc \
      --disable-programs \
      --enable-network
    
    # 开始编译,-j 后面的数字建议设为 CPU 核心数
    make -j8
    make install
  3. 其他编译方式

    3.1 build_x86.sh

    bash 复制代码
    #!/bin/bash
    # =========================================
    # FFmpeg for Android - x86
    # =========================================
    set -e
    
    export ANDROID_NDK_ROOT=/e/Android/android-sdk/ndk/27.2.12479018
    API=28
    ABI_NAME="x86"
    ARCH="x86"
    CPU="i686"
    TOOLCHAIN_ARCH="i686-linux-android"
    
    case "$(uname -s)" in
        MINGW*|MSYS*|CYGWIN*) HOST_TAG=windows-x86_64 ;;
        Linux*) HOST_TAG=linux-x86_64 ;;
        *) echo "不支持的主机平台"; exit 1 ;;
    esac
    
    TOOLCHAIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/$HOST_TAG
    SYSROOT=$TOOLCHAIN/sysroot
    SOURCE_DIR=$(pwd)
    PREFIX=$SOURCE_DIR/android/$ABI_NAME
    
    echo "=========================================="
    echo "  编译 FFmpeg for $ABI_NAME"
    echo "=========================================="
    
    cd "$SOURCE_DIR"
    rm -rf "$PREFIX"
    make distclean 2>/dev/null || true
    
    ./configure \
        --prefix=$PREFIX \
        --target-os=android \
        --arch=$ARCH \
        --cpu=$CPU \
        --enable-cross-compile \
        --cross-prefix=$TOOLCHAIN/bin/llvm- \
        --cc=$TOOLCHAIN/bin/${TOOLCHAIN_ARCH}${API}-clang \
        --cxx=$TOOLCHAIN/bin/${TOOLCHAIN_ARCH}${API}-clang++ \
        --ar=$TOOLCHAIN/bin/llvm-ar \
        --nm=$TOOLCHAIN/bin/llvm-nm \
        --strip=$TOOLCHAIN/bin/llvm-strip \
        --ranlib=$TOOLCHAIN/bin/llvm-ranlib \
        --sysroot=$SYSROOT \
        --enable-shared \
        --disable-static \
        --disable-doc \
        --disable-programs \
        --enable-network \
        --enable-jni \
        --enable-mediacodec \
        --disable-asm
    
    make -j$(nproc 2>/dev/null || echo 8)
    make install
    
    echo ""
    echo "? $ABI_NAME 编译完成:$PREFIX"
    ls -la $PREFIX/lib

    3.2 build_arm64_v8a.sh

    bash 复制代码
    #!/bin/bash
    # =========================================
    # FFmpeg for Android - arm64-v8a
    # =========================================
    set -e
    
    # ---------- 配置 ----------
    export ANDROID_NDK_ROOT=/e/Android/android-sdk/ndk/27.2.12479018
    API=28
    ABI_NAME="arm64-v8a"
    ARCH="aarch64"
    CPU="armv8-a"
    TOOLCHAIN_ARCH="aarch64-linux-android"
    
    # 判断主机平台
    case "$(uname -s)" in
        MINGW*|MSYS*|CYGWIN*) HOST_TAG=windows-x86_64 ;;
        Linux*) HOST_TAG=linux-x86_64 ;;
        *) echo "不支持的主机平台"; exit 1 ;;
    esac
    
    TOOLCHAIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/$HOST_TAG
    SYSROOT=$TOOLCHAIN/sysroot
    SOURCE_DIR=$(pwd)
    PREFIX=$SOURCE_DIR/android/$ABI_NAME
    
    echo "=========================================="
    echo "  编译 FFmpeg for $ABI_NAME"
    echo "=========================================="
    echo "NDK:  $ANDROID_NDK_ROOT"
    echo "API:  $API"
    echo "输出: $PREFIX"
    echo "=========================================="
    
    # ---------- 清理 ----------
    cd "$SOURCE_DIR"
    rm -rf "$PREFIX"
    make distclean 2>/dev/null || true
    
    # ---------- 配置 ----------
    ./configure \
        --prefix=$PREFIX \
        --target-os=android \
        --arch=$ARCH \
        --cpu=$CPU \
        --enable-cross-compile \
        --cross-prefix=$TOOLCHAIN/bin/llvm- \
        --cc=$TOOLCHAIN/bin/${TOOLCHAIN_ARCH}${API}-clang \
        --cxx=$TOOLCHAIN/bin/${TOOLCHAIN_ARCH}${API}-clang++ \
        --ar=$TOOLCHAIN/bin/llvm-ar \
        --nm=$TOOLCHAIN/bin/llvm-nm \
        --strip=$TOOLCHAIN/bin/llvm-strip \
        --ranlib=$TOOLCHAIN/bin/llvm-ranlib \
        --sysroot=$SYSROOT \
        --enable-shared \
        --disable-static \
        --disable-doc \
        --disable-programs \
        --enable-network \
        --enable-jni \
        --enable-mediacodec
    
    # ---------- 编译 ----------
    make -j$(nproc 2>/dev/null || echo 8)
    make install
    
    echo ""
    echo "? $ABI_NAME 编译完成:$PREFIX"
    ls -la $PREFIX/lib
  4. 赋予执行权限并运行:

    bash 复制代码
    # 4. 首次使用前赋权
    chmod +x build_*.sh
    
    # 5. 编译 arm64-v8a
    ./build_arm64_v8a.sh
    
    # 6. 编译其他架构(可选)
    ./build_armv7.sh
    ./build_x86.sh
    ./build_x86_64.sh
  5. 编译成功后,库文件位于 ./android/aarch64/。

NDK r26+ 注意 :--cross-prefix 必须为 llvm-,编译器名格式为 aarch64-linux-android28-clang。显式指定 --android-api 可避免 "Defaulting to target API 21" 警告。

四、复制库文件到 Qt 项目

将编译生成的 include 和 lib 目录复制到 Qt 项目下:

text

复制代码
D:\Desktop\WifiUAV_MY\WifiUAV_MY\libs\android\arm64-v8a\
├── include\
│   ├── libavcodec\
│   ├── libavformat\
│   ├── libavutil\
│   └── libswscale\
└── lib\
    ├── libavcodec.so
    ├── libavcodec.so.61
    ├── libavformat.so
    ├── libavformat.so.61
    ├── libavutil.so
    ├── libavutil.so.59
    ├── libswscale.so
    └── libswscale.so.8

重要 :.so 和 .so.xx 软链接指向的实际文件都要复制,缺一不可

五、修改 .pro 文件

不要使用 $$ANDROID_ABI (它在 qmake 解析阶段为空),直接硬编码 arm64-v8a:

增加自行匹配

bash 复制代码
# 2. 区分平台配置
android {
    FFMPEG_DIR = $$PWD/libs/android

    # 根据目标 ABI 选择对应的 FFmpeg 库
    contains(ANDROID_TARGET_ARCH, arm64-v8a) {
        FFMPEG_ANDROID_DIR = $$FFMPEG_DIR/arm64-v8a
    }
    contains(ANDROID_TARGET_ARCH, armeabi-v7a) {
        FFMPEG_ANDROID_DIR = $$FFMPEG_DIR/armeabi-v7a
    }
    contains(ANDROID_TARGET_ARCH, x86) {
        FFMPEG_ANDROID_DIR = $$FFMPEG_DIR/x86
    }
    contains(ANDROID_TARGET_ARCH, x86_64) {
        FFMPEG_ANDROID_DIR = $$FFMPEG_DIR/x86_64
    }

    # 兜底:如果没匹配到,默认用 arm64
    isEmpty(FFMPEG_ANDROID_DIR) {
        FFMPEG_ANDROID_DIR = $$FFMPEG_DIR/arm64-v8a
        message("Warning: Unknown ABI, fallback to arm64-v8a")
    }

    INCLUDEPATH += $$FFMPEG_ANDROID_DIR/include
    LIBS += -L$$FFMPEG_ANDROID_DIR/lib \
            -lavcodec -lavformat -lavutil -lswscale
} else:win32 {
    # Windows 平台:使用项目内置的 Windows FFmpeg
    FFMPEG_DIR = $$PWD/lib/ffmpeg
    INCLUDEPATH += $$FFMPEG_DIR/include
    LIBS += -L$$FFMPEG_DIR/lib \
            -lavcodec \
            -lavformat \
            -lavutil \
            -lswscale
} else:unix {
    # Linux/Ubuntu 平台:使用系统 FFmpeg 开发包
    CONFIG += link_pkgconfig
    PKGCONFIG += libavcodec libavformat libavutil libswscale
}

修改后执行:清理项目 → 执行 qmake → 重新构建。

相关推荐
胡家伟++2 小时前
从一段经文到 5 分半水墨动画短片:全 AI 流水线完整实录(即梦 + TTS 克隆 + ffmpeg + 思维链重构)
人工智能·ffmpeg·aigc
程序员-珍3 小时前
关于协程相关问题
android·安卓
励志不掉头发的内向程序员6 小时前
【从零写一个CAD 03】三个 double 值得单独一个类吗:把视图变换抽成 View
开发语言·c++·qt·学习·系统架构
allnlei12 小时前
Opus In-Band FEC 详解:原理、实现与开源方案
ffmpeg·音视频·gstreamer
sycmancia18 小时前
Qml——第一个qml的程序
qt
实心儿儿19 小时前
Qt — Qt 多线程
开发语言·qt
沫璃染墨1 天前
《Qt从零入门系列(十一):Qt事件机制详解——从QEvent到鼠标、键盘与定时器事件》
c++·qt·ui·硬件工程·交互·个人开发·qt5
实心儿儿1 天前
Qt — Qt 窗口
开发语言·qt
VidDown1 天前
从一堆脚本到能维护的系统:视频处理管道的工程化
服务器·ffmpeg·音视频·视频编解码