
前言
此前,笔者梳理了语音相关的两篇文章:
- 如何打造车载语音交互:Google Voice Interaction 给你答案:介绍的是 3rd Party App 如何通过
Voice InteractionAPI 快速调用系统的语音交互服务快速完成确认、选择的基础语音对话 - 直面原理:5 张图彻底了解 Android TextToSpeech 机制:侧重于阐述 TTS Engine App 如何提供
Text-to-Speech文字转语音服务,以及 3rd Party App 又如何便捷地调用这些服务。
还缺最后一块即如何向系统提供语音识别的 SpeechRecognizer 服务、3rd Party App 如何使用他们,以及系统和联系这两者?
本篇文章将为你补齐这块知识点。
如何实现识别服务?
首先我们得提供识别服务的实现,简单来说继承 RecognitionService 实现最重要的几个抽象方法即可:
- 首先可以定义抽象的识别 Engine 的接口
IRecognitionEngine - 在 RecognitionService 启动的时候获取识别 engine 提供商的实现实例
- 在
onStartListening()里解析识别请求 Intent 中的参数,比如语言、最大结果数等信息封装成 json 字符串传递给 engine 的开始识别。那么 Engine 也需要依据参数进行识别实现方面的调整,并将识别过程中相应的状态、结果返回,比如开始说话 beginningOfSpeech() 、结束说话 endOfSpeech() 、中间结果 partialResults() 等 onStopListening()里调用 engine 的停止识别,一样的需要 engine 回传结果,比如最终识别结果 results()onCancel()里执行 engine 提供的 release() 进行识别 engine 的解绑、资源释放
interface IRecognitionEngine {
fun init()
fun startASR(parameter: String, callback: Callback?)
fun stopASR(callback: Callback?)
fun release(callback: Callback?)
}
class CommonRecognitionService : RecognitionService() {
private val recognitionEngine: IRecognitionEngine by lazy {
RecognitionProvider.provideRecognition()
}
override fun onCreate() {
super.onCreate()
recognitionEngine.init()
}
override fun onStartListening(intent: Intent?, callback: Callback?) {
val params: String = "" // Todo parse parameter from intent
recognitionEngine.startASR(params, callback)
}
override fun onStopListening(callback: Callback?) {
recognitionEngine.stopASR(callback)
}
override fun onCancel(callback: Callback?) {
recognitionEngine.release(callback)
}
}
当然不要忘记在 Manifest 中声明:
<service
android:name=".recognition.service.CommonRecognitionService"
android:exported="true">
<intent-filter>
<action android:name="android.speech.RecognitionService"/>
</intent-filter>
</service>
如何请求识别?
首先得声明 capture audio 的 Runtime 权限,还需补充运行时权限的代码逻辑。
<manifest ... >
<uses-configuration android:name="android.permission.RECORD_AUDIO"/>
</manifest>
另外,Android 11 以上的话,需要额外添加对识别服务的包名 query 声明。
<manifest ... >
...
<queries>
<intent>
<action
android:name="android.speech.RecognitionService" />
</intent>
</queries>
</manifest>
权限满足之后,最好先检查整个系统里是否有 Recognition 服务可用,NO 的话,直接结束即可。
class RecognitionHelper(val context: Context) {
fun prepareRecognition(): Boolean {
if (!SpeechRecognizer.isRecognitionAvailable(context)) {
Log.e("RecognitionHelper", "System has no recognition service yet.")
return false
}
...
}
}
有可用服务的话,通过 SpeechRecognizer 提供的静态方法创建调用识别的入口实例,该方法必须在主线程调用。
class RecognitionHelper(val context: Context) : RecognitionListener{
private lateinit var recognizer: SpeechRecognizer
fun prepareRecognition(): Boolean {
...
recognizer = SpeechRecognizer.createSpeechRecognizer(context)
...
}
}
当然如果系统搭载的服务不止一个,并且已知了其包名,可指定识别的实现方:
public static SpeechRecognizer createSpeechRecognizer (Context context,
ComponentName serviceComponent)
接下来就是设置 Recognition 的监听器,对应着识别过程中各种状态,比如:
- onPartialResults() 返回的中间识别结果,通过 SpeechRecognizer#RESULTS_RECOGNITION key 去 Bundle 中获取识别字符串 getStringArrayList(String)
- onResults() 将返回最终识别的结果,解析办法同上
- onBeginningOfSpeech():检测到说话开始
- onEndOfSpeech():检测到说话结束
- onError() 将返回各种错误,和 SpeechRecognizer#ERROR_XXX 中各数值相对应,例如没有麦克风权限的话,会返回
ERROR_INSUFFICIENT_PERMISSIONS - 等等
class RecognitionHelper(val context: Context) : RecognitionListener{
...
fun prepareRecognition(): Boolean {
...
recognizer.setRecognitionListener(this)
return true
}
override fun onReadyForSpeech(p0: Bundle?) {
TODO("Not yet implemented")
}
override fun onBeginningOfSpeech() {
TODO("Not yet implemented")
}
override fun onRmsChanged(p0: Float) {
TODO("Not yet implemented")
}
override fun onBufferReceived(p0: ByteArray?) {
TODO("Not yet implemented")
}
override fun onEndOfSpeech() {
TODO("Not yet implemented")
}
override fun onError(p0: Int) {
TODO("Not yet implemented")
}
override fun onResults(p0: Bundle?) {
TODO("Not yet implemented")
}
override fun onPartialResults(p0: Bundle?) {
TODO("Not yet implemented")
}
override fun onEvent(p0: Int, p1: Bundle?) {
TODO("Not yet implemented")
}
}
之后创建识别的必要 Intent 信息并启动,信息包括:
EXTRA_LANGUAGE_MODEL:必选,期望识别的偏好模型,比如代码里设置的自由形式的 LANGUAGE_MODEL_FREE_FORM 模型,还有依赖网络搜索的 LANGUAGE_MODEL_WEB_SEARCH 模型等EXTRA_PARTIAL_RESULTS:可选,是否要求识别服务回传识别途中的结果,默认 falseEXTRA_MAX_RESULTS:可选,设置允许服务返回的最多结果数值,int 类型EXTRA_LANGUAGE:可选,设置识别语言,默认情况下是 Locale.getDefault() 的地区语言(笔者使用的是 Google Assistant 提供的识别服务,暂不支持中文,所以此处配置的 Locale 为 ENGLISH)- 等
另外,需要留意两点:1. 此方法必须在上述监听器设置之后进行,2. 该方法得在主线程发起:
class RecognitionHelper(val context: Context) : RecognitionListener{
...
fun startRecognition() {

本文聚焦Android语音识别,介绍如何实现识别服务,包括定义接口、解析请求参数等;阐述请求识别的步骤,如声明权限、创建入口实例等;还探究系统调度原理,涵盖检测、初始化、开始及停止识别等环节,最后结合图示展示机制链路。
最低0.47元/天 解锁文章
644

被折叠的 条评论
为什么被折叠?



