Android 语音识别入门实战:从零构建高准确率语音转文本应用

1次阅读
没有评论

共计 2876 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

移动端语音识别技术让智能助手、实时字幕等场景成为可能,大幅提升了人机交互效率。作为开发者,快速实现稳定可靠的语音转文本功能是增强应用竞争力的关键。

Android 语音识别入门实战:从零构建高准确率语音转文本应用

一、API 选型:SpeechRecognizer vs ML Kit

在 Android 平台上,我们主要面对两种语音识别方案选择:

  • SpeechRecognizer(系统内置 API)
  • 必须联网使用,依赖 Google 语音服务
  • 延迟较高(通常 1 - 3 秒)但准确率优秀
  • 免费且兼容 Android 4.1+ 设备

  • ML Kit 语音识别 API

  • 支持离线模式(需下载约 200MB 模型文件)
  • 延迟可控制在 800ms 内
  • 需要 Firebase 依赖,部分高级功能收费

对于新手项目,建议优先使用 SpeechRecognizer 快速验证功能,后期再根据需求考虑迁移到 ML Kit。

二、基础实现全流程

1. 权限声明

AndroidManifest.xml 中添加:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />

2. 动态权限申请

private fun checkAudioPermission() {
    when {
        ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.RECORD_AUDIO
        ) == PackageManager.PERMISSION_GRANTED -> {startVoiceRecognition()
        }
        ActivityCompat.shouldShowRequestPermissionRationale(
            this,
            Manifest.permission.RECORD_AUDIO
        ) -> {showPermissionExplanationDialog()
        }
        else -> {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.RECORD_AUDIO),
                AUDIO_PERMISSION_CODE
            )
        }
    }
}

3. 音频配置核心参数

val audioFormat = AudioFormat.ENCODING_PCM_16BIT // 16 位采样
val sampleRate = 16000 // 16kHz 采样率
val channelConfig = AudioFormat.CHANNEL_IN_MONO // 单声道
val bufferSize = AudioRecord.getMinBufferSize(
    sampleRate,
    channelConfig,
    audioFormat
) * 2 // 双倍缓冲

4. 完整语音识别示例

class SpeechActivity : AppCompatActivity() {
    private lateinit var speechRecognizer: SpeechRecognizer
    private val audioManager by lazy {getSystemService(AUDIO_SERVICE) as AudioManager }

    override fun onCreate(savedInstanceState: Bundle?) {
        //... 初始化视图
        setupSpeechRecognizer()}

    private fun setupSpeechRecognizer() {speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this).apply {
            setRecognitionListener(object : RecognitionListener {override fun onResults(results: Bundle) {
                    val matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
                    matches?.firstOrNull()?.let { text ->
                        updateUI(text)
                    }
                }

                // 必须实现所有回调方法
                override fun onError(error: Int) {when(error) {SpeechRecognizer.ERROR_NO_MATCH -> showToast("未识别到语音")
                        else -> showToast("识别错误代码: $error")
                    }
                }
                //... 其他回调省略
            })
        }
    }

    fun startListening() {
        audioManager.requestAudioFocus(
            focusChangeListener,
            AudioManager.STREAM_MUSIC,
            AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
        )

        val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
            putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true)
        }
        speechRecognizer.startListening(intent)
    }
}

三、性能优化实战

1. 内存管理策略

  • 采用环形缓冲区处理音频流
  • 每 2 秒强制 flush 一次识别请求
  • 使用 WeakReference 持有 Activity 引用

2. 超时重试机制

private var retryCount = 0

override fun onError(error: Int) {if(error == ERROR_SPEECH_TIMEOUT && retryCount < 3) {
        retryCount++
        Handler(Looper.getMainLooper()).postDelayed({ startListening() },
            1000L
        )
    }
}

3. 内存泄漏检测

  1. 在 Android Studio 中打开 Profiler
  2. 选择 Memory 视图开始记录
  3. 反复进入 / 退出语音识别界面
  4. 观察 Activity 实例是否被正确回收

四、避坑指南

  • 国产手机兼容性
  • 小米 / 华为等设备需要单独申请自启动权限
  • OPPO 系统会限制后台麦克风访问

  • 电量优化

  • 使用 WorkManager 调度后台识别任务
  • 设置最长持续识别时间为 60 秒

  • 数据安全

  • 敏感语音采用 AES-256 加密后存储
  • 避免在日志中输出原始语音文本

五、进阶思考

当前基于云端 ASR 的通用模型对医疗、法律等专业术语识别较差。是否可以通过以下方式优化:
1. 在客户端预过滤行业关键词
2. 上传上下文语义辅助云端分析
3. 定制化微调 Transformer 模型

完整的语音识别系统就像训练一个耐心的倾听者——既要快速响应,又要准确理解。希望这篇指南能帮你避开我踩过的那些坑!

正文完
 0
评论(没有评论)