MNN TTS Android Demo 构建实战:从 NDK 环境配置到 CMake 原生库链接的全流程解析
【免费下载链接】MNNMNN: A blazing-fast, lightweight inference engine battle-tested by Alibaba, powering high-performance on-device LLMs and Edge AI.项目地址: https://gitcode.com/GitHub_Trending/mn/MNN
本文基于 MNN 仓库中 MNN TTS Android Demo 构建文档 展开,完整覆盖 Demo 的工具链前置要求、Gradle/CMake 双层构建配置、MNN 核心库依赖链与安装运行验证方法。读完本文,你可以独立完成该 TTS 演示应用的编译、安装、启动与常见故障排查,并理解构建配置背后与源码的直接对应关系。
一、项目概述与模块结构
MNN TTS Android Demo 是基于 MNN(Mobile Neural Network)推理引擎的文本转语音(Text-to-Speech)演示应用,位于apps/frameworks/mnn_tts/目录下。它展示了如何在 Android 平台上调用 MNN TTS SDK 完成语音合成,当前内置了 BertVits2 与 Supertonic 两套 TTS 引擎实现(PIPER 为可选构建)。
整个mnn_tts模块由三部分构成:
mnn_tts/ ├── android/ # MNN TTS Android 库模块(Gradle library module) │ ├── build.gradle # 库模块构建配置 │ ├── java/ # Java/Kotlin 源代码 │ └── src/ │ └── main/java/com/alibaba/mnn/tts/ │ └── MNNTTS.kt # SDK 的 Kotlin 封装入口 ├── demo/android/ # Android Demo 应用 │ ├── build.gradle # 应用构建配置 │ ├── settings.gradle # Gradle 项目设置(挂载 :mnn_tts 模块) │ ├── src/main/ │ │ ├── java/ # Kotlin 源代码 │ │ └── res/ # Android 资源文件 │ └── build/ # 构建输出目录 ├── include/ # C++ 头文件(mnn_tts_sdk.hpp 等) ├── src/ # C++ 源代码实现 └── CMakeLists.txt # CMake 构建配置两个 Gradle 模块之间通过 settings.gradle 完成装配:根工程名为MNNTTSDemo,其中include ':mnn_tts'一行将库模块的projectDir指向上级../../android目录,因此只需打开demo/android一个目录,即可同时构建库与应用:
rootProject.name = "MNNTTSDemo" include ':mnn_tts' project(':mnn_tts').projectDir = new File('../../android')该文件同时通过pluginManagement统一声明了 AGP 与 Kotlin 插件版本(com.android.application/com.android.library均为 8.7.3,应用侧 Kotlin 插件为 1.9.22)。
二、前置要求:工具链版本与 MNN 核心库依赖
2.1 必需的工具与版本
以下版本信息来自构建文档,并与仓库中的 Gradle 配置逐一核对一致:
| 工具 | 要求版本 | 仓库中的依据 |
|---|---|---|
| Android Studio | Arctic Fox 或更高 | 构建文档推荐 |
| Android SDK | Compile SDK 35 / Min SDK 21(Android 5.0)/ Target SDK 35 | demo build.gradle 中compileSdk 35、minSdk 21、targetSdk 35 |
| Android NDK | 27.2.12479018(推荐) | 库模块 build.gradle 中ndkVersion "27.2.12479018" |
| JDK | 17 或更高(Gradle 构建) | 构建文档要求 |
| Gradle | 8.9(由 Wrapper 自动管理) | gradle-wrapper.properties 中distributionUrl指向gradle-8.9-bin.zip |
| CMake | 3.22.1 或更高 | 库模块 build.gradle 中version '3.22.1' |
此外,gradle.properties 中开启了 AndroidX、Jetifier 与nonTransitiveRClass,并将 Gradle JVM 堆内存设为 2048m。
2.2 依赖预编译的 MNN 核心库
该 Demo 的 C++ 层并非从零编译 MNN,而是链接一份预编译的libMNN.so。这一点在 CMakeLists.txt 中有明确体现:
set(MNN_SOURCE_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../) set(MNN_INSTALL_ROOT "${MNN_SOURCE_ROOT}/project/android/build_64") set(LIB_PATH "${MNN_INSTALL_ROOT}/lib") set(MNN_EXPRESS_PATH "${LIB_PATH}/libMNN_Express.so") add_library(MNN SHARED IMPORTED) set_target_properties(MNN PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNN.so")从源码结构看,MNN_SOURCE_ROOT以apps/frameworks/mnn_tts/向上回溯三层定位到仓库根目录,因此 MNN 库的期望位置为仓库内的project/android/build_64/lib/libMNN.so(构建文档中写作作者本机的绝对路径,实际均以仓库根目录为准)。如果该库不存在,需要先执行仓库提供的 Android 构建脚本:
cd project/android ./build_64.sh另外两处值得注意的实现细节:
- 可选的
libMNN_Express.so:CMake 会检查build_64/lib/libMNN_Express.so是否存在,若存在则一并声明为MNNExpress导入目标并链接(注释为 "legacy split runtime"),不存在时自动降级为只链接libMNN.so; - Android 专属链接选项:
BUILD_ANDROID开启时会追加-Wl,-z,max-page-size=16384链接选项,用于适配 16KB 内存页大小的 Android 设备。
BUILD_ANDROID标志无需手动指定,CMake 在检测到ANDROID平台变量后会自动强制置为 ON:
option(BUILD_ANDROID "Build for Android" OFF) if(ANDROID) set(BUILD_ANDROID ON CACHE BOOL "Build for Android" FORCE) endif()三、构建步骤
3.1 方法一:Gradle 命令行(推荐)
在apps/frameworks/mnn_tts/demo/android目录下依次执行:
cd apps/frameworks/mnn_tts/demo/android # 1. 清理之前的构建(可选) ./gradlew clean # 2. 构建 Debug APK ./gradlew assembleDebug # 3. 构建 Release APK ./gradlew assembleRelease # 4. 查看构建输出 ls -lh build/outputs/apk/debug/生成的 APK 文件:
- Debug:
build/outputs/apk/debug/MNNTTSDemo-arm64-v8a-debug.apk(约 15 MB) - Release:
build/outputs/apk/release/MNNTTSDemo-arm64-v8a-release-unsigned.apk(约 8 MB)
QUICKREF.md 中给出了构建耗时的参考:Clean 约 5 秒、首次构建约 2~3 分钟、增量构建约 30~60 秒、安装到设备约 10 秒。
一个实操细节:当前仓库的 demo build.gradle 在preBuild之前挂接了一个downloadAndUnzipNativeLibs任务,当src/main/jniLibs/arm64-v8a/中缺少libsherpa-mnn-jni.so时,会从 CDN 自动下载并解压 arm64-v8a 原生库包,因此首次构建需要网络可用。
3.2 方法二:Android Studio
- 打开项目:选择 "Open an Existing Project",导航到
apps/frameworks/mnn_tts/demo/android目录并确认; - Gradle 同步:Android Studio 会自动开始同步;若未触发,点击 "File" → "Sync Project with Gradle Files";
- 配置构建变体:在左下角 "Build Variants" 中选择
debug或release; - 构建 APK:点击 "Build" → "Build Bundle(s) / APK(s)" → "Build APK(s)",或使用快捷键 Ctrl+Shift+A(Windows/Linux)/ Cmd+Shift+A(Mac);
- 查看构建结果:构建成功后点击通知中的 "locate" 查看 APK 位置。
四、构建配置详解
4.1 应用配置(demo/android/build.gradle)
应用 build.gradle 的关键配置:
android { namespace 'com.alibaba.mnn.tts.demo' compileSdk 35 // 编译 SDK 版本 defaultConfig { applicationId "com.alibaba.mnn.tts.demo" minSdk 21 // 最低支持 Android 5.0 targetSdk 35 // 目标 SDK versionCode 1 // 应用版本号 versionName "1.0" // 应用版本名称 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } splits { abi { enable true reset() include 'arm64-v8a' // 仅构建 ARM64 版本 universalApk false // 不生成通用 APK } } }依赖清单与构建文档一致(Kotlin 侧依赖 androidx 基础组件 + 协程):
dependencies { implementation project(':mnn_tts') // MNN TTS 库 implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.10.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' implementation 'androidx.core:core-ktx:1.16.0' implementation 'androidx.recyclerview:recyclerview:1.3.2' implementation 'androidx.cardview:cardview:1.0.0' }4.2 库模块配置(android/build.gradle)
库模块 build.gradle 是原生代码构建的核心,实际配置比构建文档摘录的更完整:
android { namespace 'com.alibaba.mnn.tts' compileSdk 34 ndkVersion "27.2.12479018" // NDK 版本 sourceSets { main.java.srcDirs += ['java'] } defaultConfig { minSdk 21 targetSdk 35 externalNativeBuild { cmake { cppFlags "-std=c++17" arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" } } ndk { abiFilters 'arm64-v8a' } } externalNativeBuild { cmake { path file('../CMakeLists.txt') // 指向 mnn_tts/CMakeLists.txt version '3.22.1' } } buildFeatures { buildConfig true prefab true } prefab { mnn_tts { headers "include/mnn_tts" } } }几个配置项的含义:
cppFlags "-std=c++17":与 CMake 中CMAKE_CXX_STANDARD 17保持一致;-DANDROID_STL=c++_shared:使用动态 C++ 标准库,即最终 APK 中携带的libc++_shared.so;-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON:与 CMake 侧的 16KB 页对齐选项配合,支持新的内存页大小;abiFilters 'arm64-v8a':原生代码同样只编译 ARM64;prefab配置将include/mnn_tts下的头文件(如 common.h)暴露给消费方模块。
4.3 CMake 配置选项(CMakeLists.txt)
mnn_tts/CMakeLists.txt 定义了四个关键选项:
| 选项 | 默认值 | 说明 |
|---|---|---|
BUILD_BERTVITS2 | ON | 构建 BertVits2 TTS 引擎(中文/英文 G2P、Bert 音素预测、声学模型生成) |
BUILD_PIPER | OFF | 构建 PIPER TTS 引擎(依赖 espeak-ng 子模块,默认不启用) |
BUILD_SUPERTONIC | ON | 构建 Supertonic TTS 引擎 |
BUILD_ANDROID | OFF(自动检测) | Android 平台标志,检测到ANDROID变量后强制置 ON |
各选项直接决定编译哪些源文件并追加哪些头文件目录。例如BUILD_BERTVITS2开启时纳入src/bertvits2/下共 11 个源文件(text_preprocessor、chinese_g2p、english_bert、tts_generator 等);BUILD_ANDROID开启时额外纳入src/android/tts_service.cpp与src/android/tts_service_jni.cpp两个 JNI 服务源文件——这正是 Android 平台上 TTS 引擎服务的原生实现入口。
最终产物为动态库libmnn_tts.so(add_library(${PROJECT_NAME} SHARED ...)),链接log、MNN(Android 平台另链接系统 log 库),形成如下原生库组合:
- libMNN.so:MNN 核心推理引擎(来自
project/android/build_64预构建产物); - libmnn_tts.so:MNN TTS SDK 实现(由本 CMake 工程构建);
- libc++_shared.so:C++ 标准库(
c++_sharedSTL 模式)。
五、安装、运行与验证
5.1 安装到设备
# 方式一:Gradle 命令 ./gradlew installDebug # 方式二:adb 命令 adb install build/outputs/apk/debug/MNNTTSDemo-arm64-v8a-debug.apk # 方式三:Android Studio 工具栏 "Run" 按钮,选择目标设备后自动安装并启动5.2 启动应用
# 启动 Demo 主界面 adb shell am start -n com.alibaba.mnn.tts.demo/.MainActivity # 停止 / 卸载 / 清数据(来自 QUICKREF.md 的常用命令) adb shell am force-stop com.alibaba.mnn.tts.demo adb uninstall com.alibaba.mnn.tts.demo adb shell pm clear com.alibaba.mnn.tts.demo从 AndroidManifest.xml 可以看到,这个 Demo 除了普通 Launcher 应用之外还有一个值得注意的身份:它声明了一个com.mnn.tts.demo.MnnTtsService服务并匹配android.intent.action.TTS_SERVICE意图,附带@xml/tts_engine元数据——也就是说它同时注册为系统 TTS 引擎,用户可以在系统"设置 → 语言和输入法 → 文字转语音"中选择 "MNN TTS Engine",配套的设置界面由MnnTtsSettingsActivity(匹配TTS_SERVICE_SETTINGS意图)提供。应用还申请了RECORD_AUDIO、MODIFY_AUDIO_SETTINGS等权限,并通过<queries>声明了对 TTS 服务意图的可见性。
5.3 日志与性能分析
# 查看应用日志 adb logcat -s MNN_TTS:* AndroidRuntime:E # 查看原生日志 adb logcat -s DEBUG:* native:*性能侧可使用 Android Studio 的 Profiler(View → Tool Windows → Profiler)监控 CPU/内存,或使用 Systrace 抓取系统级调度轨迹(python systrace.py -t 10 -o trace.html sched freq idle)。
六、常见问题与解决方案
以下五项 FAQ 均继承自构建文档,并补充了仓库内可核对的路径:
1. NDK 未找到(NDK not configured)
在local.properties中配置 NDK 与 SDK 路径(以本机实际路径替换):
echo "ndk.dir=/path/to/sdk/ndk/27.2.12479018" >> local.properties echo "sdk.dir=/path/to/sdk" >> local.properties2. MNN 库未找到(libMNN.so not found)
先构建 MNN 核心库(对应 CMakeLists.txt 中MNN_INSTALL_ROOT指向的位置):
cd project/android ./build_64.sh ls project/android/build_64/lib/libMNN.so # 验证产物存在3. Gradle 同步失败
清理缓存并强制刷新依赖:
./gradlew clean rm -rf .gradle build ./gradlew build --refresh-dependencies4. CMake 构建失败
按顺序检查:NDK 版本是否为 27.2.12479018、CMake 版本是否 ≥ 3.22.1、project/android/build_64/lib/libMNN.so是否存在。可用./gradlew assembleDebug --info查看详细构建日志。
5. ABI 不匹配(INSTALL_FAILED_NO_MATCHING_ABIS)
应用仅支持 ARM64(arm64-v8a)设备,需确保测试设备为 ARM64 架构,或修改build.gradle的splits.abi与ndk.abiFilters添加其他 ABI 支持。
七、性能优化建议
Release 构建优化
构建文档建议的 Release 优化开关(当前 demo build.gradle 中minifyEnabled默认为false,以下为发布时的可选增强):
buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') shrinkResources true } }Release 构建同时会自动使用优化后的原生库编译选项。
运行时优化
- 模型加载:首次加载 TTS 模型耗时较长,建议走异步加载路径(Demo 中使用 Kotlin 协程封装);
- 内存管理:及时释放不再使用的模型资源;
- 线程池:使用合理的线程数量进行推理。
八、运行时架构
MainActivity.kt ├── ModelAdapter.kt # 模型列表适配器 ├── AudioChunksPlayer.kt # 分块音频播放器(实时播放合成音频) └── MNN TTS SDK (libmnn_tts.so) ├── BertVits2 TTS # BertVits2 语音合成(src/bertvits2/) ├── Supertonic TTS # Supertonic 语音合成(src/supertonic/) └── MNN Engine # MNN 推理引擎(libMNN.so)对应的源码目录与 include/ 下的公开头文件一一对应:BertVits2 引擎的对外实现头为 mnn_bertvits2_tts_impl.hpp,Supertonic 引擎为 mnn_supertonic_tts_impl.hpp,SDK 统一入口为 mnn_tts_sdk.hpp。
关键功能:
- 文本转语音:输入文本,经 G2P/文本前端处理后由声学模型生成语音;
- 模型管理:支持多种 TTS 模型切换(Demo 中由
ModelConfig/ModelAdapter管理); - 音频播放:
AudioChunksPlayer分块播放生成的语音,实现低延迟实时收听; - 性能监控:显示推理时间和资源使用;
- 系统 TTS 引擎注册:通过
MnnTtsService接入 Android 系统 TTS 框架(见第五节清单分析)。
九、版本信息与适用前提
- 应用版本:1.0(versionCode 1)
- 最低 Android 版本:5.0(API 21)
- 目标 Android 版本:14.0(API 35)
- 支持的架构:ARM64(arm64-v8a)
- 许可证:遵循 MNN 项目许可证条款
适用前提说明:本文所有构建步骤均以当前仓库状态为准,MNN 核心库必须由仓库内的 build_64.sh 先行产出;构建文档中出现的作者本机绝对路径(如/Users/...)在仓库内均应理解为相对仓库根目录的路径。配套的快速开始与常用命令速查可参考同目录的 README.md 和 QUICKREF.md。
【免费下载链接】MNNMNN: A blazing-fast, lightweight inference engine battle-tested by Alibaba, powering high-performance on-device LLMs and Edge AI.项目地址: https://gitcode.com/GitHub_Trending/mn/MNN
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考