共计 2124 个字符,预计需要花费 6 分钟才能阅读完成。
在移动端开发中,离线语音识别既能保护用户隐私,又能在网络信号不佳的场景下提供稳定的服务。Vosk 作为轻量级开源工具,完美适配这些需求场景。

技术选型:Vosk vs Google Speech-to-Text
- 离线能力 :Vosk 完全离线运行,Google 服务依赖网络连接
- 模型大小 :Vosk 基础英文模型仅 50MB,Google 云端模型通常需 200MB+
- 多语言支持 :Vosk 支持 20+ 种语言,Google 服务覆盖更广但需付费
环境搭建与依赖配置
在 app 模块的 build.gradle 中添加以下依赖(注意注释说明的配置要点):
dependencies {
// 核心库版本需与模型版本匹配
implementation 'com.alphacephei:vosk-android:0.3.39'
// 音频处理必备库
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
}
模型文件处理优化
推荐将模型存放在应用专属外部存储,避免重复下载:
// 获取模型存储路径(无需权限)val modelDir = getExternalFilesDir("vosk")?.apply {if (!exists()) mkdirs()}
// 下载解压示例(实际项目应增加进度回调)fun downloadModel(url: String) {
runCatching {File("$modelDir/model.zip").outputStream().use { fos ->
OkHttpClient().newCall(Request.Builder().url(url).build())
.execute().body?.byteStream()?.copyTo(fos)
}
// 使用 ZipInputStream 解压到目标目录
}.onFailure {Log.e("Model", "Download failed", it) }
}
实时语音处理实现
配置 AudioRecord 并建立识别管道:
// 音频参数(与模型采样率匹配)private const val SAMPLE_RATE = 16000
private const val BUFFER_SIZE = 4096
fun startRecording() {
val audioRecord = AudioRecord(
MediaRecorder.AudioSource.MIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
BUFFER_SIZE
).apply {startRecording() }
// 启动识别协程
CoroutineScope(Dispatchers.IO).launch {val recognizer = Model(modelDir.path).let {Recognizer(it, SAMPLE_RATE.toFloat())
}
val buffer = ShortArray(BUFFER_SIZE)
while (isActive) {val read = audioRecord.read(buffer, 0, BUFFER_SIZE)
if (recognizer.acceptWaveForm(buffer, read)) {
val result = recognizer.result
withContext(Dispatchers.Main) {updateUI(result)
}
}
}
}
}
性能优化关键点
- 模型预加载 :在 SplashScreen 或后台服务提前加载模型
- 线程管理 :使用固定大小线程池(建议 4 - 6 线程)
- 内存泄漏防护 :
- Recognizer 对象需在 onDestroy 释放
- 检查 AudioRecord 是否及时 stop/release
- 使用 WeakReference 持有 Activity 引用
低延迟模式适配
针对需要快速响应的场景(如语音指令):
val wifiManager = getSystemService(WIFI_SERVICE) as WifiManager
wifiManager.isWifiEnabled = true // 确保 WIFI 开启
// 尝试启用低延迟模式(需要 API 29+)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {wifiManager.setWifiMode(WifiManager.WIFI_MODE_FULL_LOW_LATENCY)
}
完整示例项目
参考实现已上传 GitHub:VoskAndroidDemo(包含错误处理与性能监控模块)
进阶思考
如何结合 Android 的 TextClassifier 实现语义理解?可尝试:
1. 对识别文本进行意图分类
2. 提取关键实体(时间 / 地点等)
3. 构建领域特定语言模型(DSL)
在实际项目中,建议先明确语音交互边界(如仅处理 10 秒内的指令),再逐步扩展复杂场景。遇到模型加载慢的问题时,可尝试量化模型或使用按需加载策略。
正文完
