共计 2187 个字符,预计需要花费 6 分钟才能阅读完成。
1. 背景痛点:为什么语音识别这么难?
在移动端实现语音识别文字功能时,开发者常遇到这些拦路虎:

- 环境噪音干扰:地铁、咖啡馆等场景的背景噪音会导致识别准确率暴跌
- 设备碎片化:不同厂商的麦克风硬件和系统定制层(如 EMUI)对音频采集的处理差异巨大
- 实时性要求:用户期望边说边出文字,但网络延迟可能造成卡顿
- 资源消耗:持续录音和云端识别会快速消耗电量和流量
2. 技术选型:用轮子还是造轮子?
2.1 Android 原生 SpeechRecognizer
- 优点:
- 系统内置,无需额外集成
- 支持离线基础识别(Android 4.1+)
- 免费使用
- 缺点:
- 识别精度一般
- 不支持自定义模型
- 国内厂商可能阉割该服务
2.2 Google ML Kit 语音识别
- 优点:
- 准确率高(基于 Google 语音技术)
- 支持 60+ 语言
- 提供离线模型
- 缺点:
- 需要 Google Play 服务
- 免费版有调用次数限制
2.3 讯飞等第三方 SDK
- 优点:
- 针对中文优化
- 支持方言识别
- 提供成熟的降噪方案
- 缺点:
- 商用需授权费
- SDK 体积较大
选型建议:快速验证用原生 API,商业项目推荐 ML Kit 或讯飞
3. 核心实现四步走
3.1 权限申请(Android 6.0+)
// 在 AndroidManifest.xml 声明
<uses-permission android:name="android.permission.RECORD_AUDIO" />
// 运行时请求
val permissions = arrayOf(Manifest.permission.RECORD_AUDIO)
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE)
3.2 初始化语音识别器
val speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this).apply {
setRecognitionListener(object : RecognitionListener {override fun onResults(results: Bundle) {val matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
textView.text = matches?.get(0) ?: "识别失败"
}
// 其他回调方法省略...
})
}
3.3 启动识别会话
val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true) // 实时返回结果
}
speechRecognizer.startListening(intent)
3.4 结果后处理
建议添加标点预测算法(简易版):
fun addPunctuation(text: String): String {val lastChar = text.lastOrNull()
return when {text.endsWith("吗") -> "$text?"
lastChar in setOf('吧','呢','啊') -> "$text!"
else -> text
}
}
4. 性能优化三板斧
4.1 音频预处理
- 使用
AudioRecord替代MediaRecorder获取原始 PCM 数据 - 实现简单降噪(示例代码):
fun denoise(audioData: ShortArray): ShortArray {
val threshold = 500 // 根据环境调整
return audioData.map { sample ->
if (abs(sample.toInt()) < threshold) 0 else sample
}.toShortArray()}
4.2 缓存机制
- 本地缓存最近 5 条识别结果
- 当网络抖动时展示缓存内容
4.3 电量优化
- 识别完成后立即释放麦克风
- 使用 WorkManager 处理后台识别任务
5. 避坑指南
- EMUI 系统兼容性问题:
- 添加
try-catch包裹startListening -
备用方案:检测到华为设备时启用第三方 SDK
-
内存泄漏预防:
- 在
onDestroy中调用speechRecognizer.destroy() -
使用 WeakReference 持有 Activity 引用
-
长时间识别卡顿:
- 每 60 秒主动重启识别会话
- 使用
EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS设置静音检测
6. 延伸思考
想挑战更高阶功能?可以尝试:
- 离线识别:集成 TensorFlow Lite 语音模型
- 方言支持:讯飞 SDK 支持粤语、四川话等
- 语音指令:结合 NLU 实现 ” 下一首 ” 等命令识别
写在最后
实际开发中发现,单纯的代码正确性只是基础。真正影响用户体验的是对边界 case 的处理——比如用户突然锁屏时如何优雅释放资源,地铁进站时的网络切换如何处理。这些经验需要在实际项目中不断积累,希望本文能帮你少走弯路。
正文完
