语音交互深度集成:Google Assistant集成、Siri集成、自定义唤醒词
语音交互,说白了就是车载系统的“第二双手”。
我做了这么多年车载开发,最深的体会就是:屏幕再大,也不如一句话来得快。尤其在驾驶场景下,眼睛离开路面一秒都危险。所以,Google Assistant和Siri的深度集成,几乎是现代车载信息娱乐系统的标配。
这一章,我们就来聊聊怎么把这两个“大管家”请进你的车机,顺便再搞一个自定义唤醒词,让用户喊“你好小蓝”就能唤醒系统。
18.1 Google Assistant 集成:从唤醒到对话
Google Assistant的集成,其实分两层:浅层集成和深层集成。
浅层集成,就是简单的“语音转文字”+“文字转语音”。深层集成,则是把Assistant的对话能力嵌入到你的应用里,让它能控制导航、音乐、空调等车载功能。
18.1.1 核心API与权限
你需要引入Google Mobile Services(GMS)的语音服务包。嗯,这里要注意,国内有些车机没有GMS,那就得走其他方案了。
// 在build.gradle中添加依赖
implementation 'com.google.android.gms:play-services-assistant:2.0.0'
implementation 'com.google.android.gms:play-services-voice:1.0.0'
// AndroidManifest.xml中声明权限
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
18.1.2 启动Assistant会话
我个人习惯用Intent的方式启动Assistant。这样最简单,也最稳定。
// 启动Google Assistant
private void launchGoogleAssistant() {
Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
// 降级方案:打开语音搜索
Intent searchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
startActivity(searchIntent);
}
}
我在项目中遇到过一个问题:有些车机厂商把Google Assistant给阉割了。这时候,你就得准备一个降级方案,比如直接用系统自带的语音识别。
18.1.3 深度集成:自定义Action
如果你想让Assistant能控制你的App,比如“导航到公司”,那就得注册Deep Link。
<!-- AndroidManifest.xml -->
<activity android:name=".NavigationActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:scheme="mycar"
android:host="navigate" />
</intent-filter>
</activity>
然后在Assistant的Actions Console里配置好对应的意图。这样,用户说“导航到公司”,Assistant就会把参数传给你的App。
18.2 Siri集成:CarPlay的语音入口
Siri的集成,主要是在CarPlay场景下。你想想看,用户连上CarPlay,第一件事就是喊“嘿Siri”。
SiriKit是苹果给开发者留的接口。通过它,你可以让Siri控制你的App里的功能。
18.2.1 配置Siri权限
// Info.plist中配置
<key>NSSiriUsageDescription</key>
<string>我们需要使用Siri来控制导航和音乐</string>
// Capabilities中开启Siri
// 注意:需要开发者账号
18.2.2 实现Siri意图
假设你要让Siri能控制你的导航App,需要实现一个Intents Extension。
// 创建Intents Extension Target
// 在IntentHandler中处理请求
class IntentHandler: INExtension, INStartAudioCallIntentHandling {
func handle(intent: INStartAudioCallIntent, completion: @escaping (INStartAudioCallIntentResponse) -> Void) {
// 处理语音通话请求
let response = INStartAudioCallIntentResponse(code: .success, userActivity: nil)
completion(response)
}
func resolveContacts(for intent: INStartAudioCallIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) {
// 解析联系人
guard let contacts = intent.contacts else {
completion([INPersonResolutionResult.needsValue()])
return
}
completion(contacts.map { INPersonResolutionResult.success(with: $0) })
}
}
我记得有一次,用户反馈说Siri识别不了“导航到加油站”。查了半天,发现是Intents的词汇表没配好。后来我在App的Info.plist里加了一组自定义词汇,问题就解决了。
18.3 自定义唤醒词:打造专属语音入口
Google Assistant和Siri虽然好用,但毕竟是别人的东西。很多车厂希望有自己的唤醒词,比如“你好,小鹏”、“嗨,蔚来”。
自定义唤醒词,说白了就是做一个本地语音唤醒引擎。它不需要联网,实时监听麦克风,检测到特定关键词就触发动作。
18.3.1 技术选型
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Snowboy | 轻量、离线、跨平台 | 准确率一般、已停止维护 | 原型验证 |
| Porcupine | 准确率高、支持自定义词 | 商业使用需付费 | 量产项目 |
| Kaldi + 自训练 | 完全可控、准确率最高 | 开发成本高、资源消耗大 | 高端车型 |
| 厂商SDK(如科大讯飞) | 本地化好、中文识别强 | 依赖第三方 | 国内车机 |
我个人比较推荐Porcupine。它轻量、准确,而且支持自定义唤醒词。你只需要录制几遍你的唤醒词,它就能生成一个模型文件。
18.3.2 Porcupine集成示例
// 1. 添加依赖
implementation 'ai.picovoice:porcupine-android:2.1.0'
// 2. 初始化唤醒词引擎
private Porcupine porcupine;
private PorcupineManager porcupineManager;
private void initWakeWord() {
try {
// 使用预置的唤醒词
porcupine = new Porcupine.Builder()
.setAccessKey("你的AccessKey")
.setKeyword(Porcupine.BUILT_IN_KEYWORDS.PICOVOICE)
.build();
// 或者使用自定义唤醒词
porcupine = new Porcupine.Builder()
.setAccessKey("你的AccessKey")
.setKeywordPath("path/to/custom_keyword.ppn")
.build();
// 启动监听
porcupineManager = new PorcupineManager(porcupine, wakeWordCallback);
porcupineManager.start();
} catch (PorcupineException e) {
e.printStackTrace();
}
}
// 3. 唤醒回调
private PorcupineManagerCallback wakeWordCallback = new PorcupineManagerCallback() {
@Override
public void onWakeWordDetection(int keywordIndex) {
// 检测到唤醒词,触发语音交互
runOnUiThread(() -> {
// 播放提示音
// 启动语音识别
// 或者直接打开Assistant
launchGoogleAssistant();
});
}
};
18.3.3 避坑指南:唤醒词的那些坑
我曾经在一个项目里,把唤醒词设成了“你好小蓝”。结果测试的时候,发现它经常被“你好小兰”误唤醒。后来分析了一下,发现是“蓝”和“兰”的发音太接近了。
所以,选唤醒词有几个原则:
- 音节要清晰:避免“吃”、“是”这种轻音字
- 长度要适中:2-4个音节最好。太短容易误唤醒,太长用户嫌麻烦
- 避免常见词:比如“你好”、“导航”这种高频词,很容易误触发
- 测试环境要真实:在车内、开空调、放音乐的情况下测试,看看误唤醒率
18.4 语音交互的完整流程
说了这么多,我们来画一张图,看看语音交互的完整链路是什么样的。
你看,从唤醒到反馈,整个链路其实挺长的。任何一个环节慢了,用户都会觉得“这车机好蠢”。
18.5 实战经验:多语音源共存
一个现实的问题:车机上同时有Google Assistant、Siri、自定义唤醒词,它们会不会打架?
会的。我遇到过最典型的情况是:用户喊“嘿Siri”,结果Google Assistant也跳出来了。
解决方案其实不复杂:
- 优先级管理:自定义唤醒词 > Siri > Google Assistant。先响应自家的,再响应外部的
- 互斥机制:当一个语音引擎被激活时,其他引擎暂时休眠
- 场景判断:如果检测到CarPlay连接,优先使用Siri;如果是Android Auto,优先使用Google Assistant
18.6 性能与功耗的平衡
语音唤醒引擎是要一直跑在后台的。它要实时监听麦克风,这就意味着CPU不能休眠。
功耗问题,在车载场景下其实还好,因为车机有车载电源。但性能问题要注意:
- 唤醒引擎最好跑在独立的DSP或者NPU上,不要占用主CPU
- 如果硬件不支持,那就得优化算法,比如降低采样率、减少特征维度
- 设置合理的超时机制:如果10秒内没有语音输入,自动进入低功耗模式
嗯,说到低功耗模式,我记得有一次测试,发现车机在熄火后还在监听麦克风,导致电瓶亏电。后来加了一个“电源状态监听”,熄火后自动关闭唤醒引擎,问题才解决。
语音交互的深度集成,说白了就是让车机“听得懂人话”。Google Assistant和Siri是两条大腿,抱好了能省不少事。自定义唤醒词则是你的特色,让用户记住你的品牌。
下一章,我们会聊聊更高级的话题:多模态交互——语音+手势+触控,怎么让它们协同工作。不过那是后话了,先把今天的代码跑通再说。
公众号:蓝海资料掘金营,微信deep3321