共计 3360 个字符,预计需要花费 9 分钟才能阅读完成。
背景与痛点
语音识别作为 AI 技术的重要应用场景,在移动开发中需求广泛。百度语音识别 AIP(AI Platform)提供了高精度的识别能力,但对新手开发者来说,集成过程常遇到以下问题:

- 官方文档涉及多个产品线,配置路径分散
- 鉴权机制复杂,容易遗漏关键步骤
- 实时流式传输与文件识别的接口差异大
- 性能优化和安全防护缺乏明确指导
技术选型对比
目前主流的语音识别方案包括:
- 百度 AIP:识别准确率高(中文场景 >95%),免费额度充足(每日 5 万次),支持离线唤醒
- 讯飞开放平台:多语种支持更好,但商用授权费用较高
- 阿里云智能语音:适合阿里云生态用户,文档整合度高
- Google ML Kit:国际应用首选,但中文识别效果稍逊
建议选择标准:
- 国内应用首选百度 AIP(成本与技术成熟度平衡)
- 需要离在线混合方案可考虑讯飞
- 出海项目建议使用 ML Kit
环境准备
前置条件
- 百度开发者账号(需企业实名认证)
- Android Studio 2021+(支持 JDK 11)
- 最低 API Level 21(Android 5.0)
基础配置
在 build.gradle(Module) 中添加依赖:
dependencies {
// 官方 SDK(2023 新版)implementation 'com.baidu.aip:java-sdk:4.16.10'
// 网络请求优化
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
}
在 AndroidManifest.xml 中声明权限:
<!-- 基础网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 录音权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
核心实现步骤
1. 初始化 AIP 客户端
创建 BaiduASRManager 管理类:
class BaiduASRManager(context: Context) {
private val aipClient: AipSpeech
init {
// 从百度控制台获取的 API Key/Secret Key
val APP_ID = "your_app_id"
val API_KEY = "your_api_key"
val SECRET_KEY = "your_secret_key"
aipClient = AipSpeech(APP_ID, API_KEY, SECRET_KEY).apply {
// 设置网络超时
connectionTimeoutInMillis = 5000
socketTimeoutInMillis = 60000
// 启用 gzip 压缩
isGzipEnabled = true
}
}
}
2. 实现语音识别
文件识别模式
fun recognizeFile(filePath: String, callback: (Result<String>) -> Unit) {
try {val options = HashMap<String, Any>().apply {put("dev_pid", 1537) // 普通话输入法模型
put("cuid", DeviceIdUtil.getDeviceId(context))
}
val result = aipClient.asr(filePath, "pcm", 16000, options)
when {result.has("result") -> callback(Result.success(result.getString("result")))
else -> callback(Result.failure(Exception(result.getString("err_msg"))))
}
} catch (e: Exception) {callback(Result.failure(e))
}
}
实时流式识别
需要配合 AudioRecord 实现:
private fun startRecording() {
val bufferSize = AudioRecord.getMinBufferSize(
16000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT
)
audioRecord = AudioRecord(
MediaRecorder.AudioSource.MIC,
16000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize
)
CoroutineScope(Dispatchers.IO).launch {val buffer = ByteArray(bufferSize)
audioRecord.startRecording()
while (isRecording) {val read = audioRecord.read(buffer, 0, bufferSize)
if (read > 0) {sendAudioChunk(buffer.copyOf(read))
}
}
}
}
private fun sendAudioChunk(chunk: ByteArray) {val options = HashMap<String, Any>().apply {put("dev_pid", 1537)
put("cuid", DeviceIdUtil.getDeviceId(context))
put("format", "pcm")
put("rate", 16000)
}
val result = aipClient.asr(chunk, "pcm", 16000, options)
// 处理识别结果...
}
性能优化要点
- 音频参数选择:
- 采样率 16kHz 足够满足中文识别
-
单声道 (CHANNEL_IN_MONO) 比立体声节省 50% 流量
-
网络请求优化:
- 使用 OkHttp 替换默认 HttpClient
- 开启 gzip 压缩(百度 SDK 默认支持)
-
设置合理的超时时间:连接 5s,读取 60s
-
缓存策略:
- 对相同音频 MD5 做本地缓存
- 使用
Stetho调试网络请求
安全防护方案
- 鉴权信息保护:
- 将 API Key 存储在 Native 层(通过 JNI 获取)
-
使用 Android Keystore 加密敏感配置
-
数据传输安全:
- 确保所有请求走 HTTPS
-
关键参数做 Base64 编码
-
权限动态申请:
private fun checkPermission() { when { ContextCompat.checkSelfPermission( this, Manifest.permission.RECORD_AUDIO ) == PackageManager.PERMISSION_GRANTED -> {startRecording() } ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.RECORD_AUDIO ) -> {showPermissionExplanationDialog() } else -> { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.RECORD_AUDIO), REQUEST_RECORD_AUDIO ) } } }
常见问题解决
- 错误码 31001:
- 检查 API Key/Secret Key 是否正确
-
确认网络请求能访问百度服务器(测试 curl https://aip.baidubce.com)
-
无录音权限:
- Android 6.0+ 需要动态申请权限
-
部分厂商 ROM 需要单独开启应用录音白名单
-
识别结果为空:
- 确认音频格式为 16kHz/16bit PCM
- 检查
dev_pid参数是否匹配语言类型
扩展实践
尝试实现以下增强功能:
– 结合 WakeWord 检测实现离线唤醒
– 使用 FFmpeg 进行音频格式实时转换
– 添加 VAD(Voice Activity Detection)减少无效请求
欢迎在评论区分享你的实现方案!
正文完
