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 → 重新构建。

相关推荐
Cx330❀3 小时前
深入浅出 Qt 绘图机制:从 QPainter 到四大图像类解析
开发语言·qt·ui·性能优化·图形渲染
Maxwin4 小时前
Manim 竖屏画布选 9×16 还是 4.5×8?从 font_size 和每单位像素数说起
python·ffmpeg
Littlehero_1215 小时前
QT自定义控件之水泥厂组态(源码开源)
开发语言·qt
FlightYe6 小时前
音视频修炼之容器与协议(一):MP4和MOV的box剖析
android·linux·c++·ffmpeg·音视频
/**书香门第*/7 小时前
Cocos Creator 3.8 配置如何直接运行白包到模拟器
安卓·cocos creator·白包
代钦塔拉8 小时前
【C++/Qt 进阶】设计模式系列(6):桥接模式——把“两个独立变化的维度“拆开
c++·qt·设计模式
156082072199 小时前
银河麒麟 Qt 可执行文件打包说明
开发语言·驱动开发·qt
Quz9 小时前
QML GridView 布局:网格排布与排列方向
qt
Quz9 小时前
QML GridView 动态:增删过渡与滚动定位
qt
沫璃染墨1 天前
《Qt从零入门系列(十四):QThread多线程详解——从线程创建到客户端阻塞处理》
开发语言·c++·笔记·qt·ui·交互·线程