8、车载语音助手开发:CarVoiceInteractionSession、自定义唤醒词、多轮对话管理、场景引擎集成
车载语音助手,说白了就是车的「耳朵」和「嘴巴」。但跟手机上的语音助手不一样,车载场景下,用户的手和眼都被占用着,语音就成了最自然的交互方式。我最早做车载语音时,踩过一个坑——用户说「打开空调」,结果系统把「打开车窗」也识别出来了,差点把乘客吹感冒。嗯,从那以后,我对语音交互的精准度和场景理解,就格外上心。
这一章,我们聚焦 Android Automotive 平台上的语音助手开发。核心围绕四个关键词:CarVoiceInteractionSession、自定义唤醒词、多轮对话管理、场景引擎集成。我会结合项目中的实际经验,把每个环节的要点和坑都讲清楚。
8.1 CarVoiceInteractionSession:语音交互的「会话容器」
CarVoiceInteractionSession 是 Android Automotive 提供的一个抽象类。它管理着一次语音交互的完整生命周期——从用户开始说话,到系统给出反馈,再到会话结束。
我个人习惯把 Session 理解成一个「对话盒子」。每次用户唤醒语音助手,系统就创建一个新的 Session 实例。这个 Session 负责接收语音输入、解析意图、执行动作、返回结果。
onShow():Session 被激活时调用,通常在这里初始化 UI 或播放提示音。onHide():Session 被隐藏时调用,清理资源。onHandleIntent(Intent intent):处理语音识别后的意图,这是核心逻辑所在。onCancel():用户取消或超时,释放资源。
我曾经在一个项目中,把所有的业务逻辑都塞进了 onHandleIntent 里,结果方法体超过 500 行,维护起来简直噩梦。后来我重构了,把每个意图的处理拆成独立的方法,代码清晰多了。
public class MyVoiceSession extends CarVoiceInteractionSession {
public MyVoiceSession(Context context) {
super(context);
}
@Override
public void onHandleIntent(Intent intent, VoiceInteractionSessionCallback callback) {
String action = intent.getAction();
switch (action) {
case "NAVIGATE":
handleNavigate(intent, callback);
break;
case "CONTROL_CLIMATE":
handleClimate(intent, callback);
break;
default:
callback.onResult("抱歉,我暂时无法处理这个指令");
break;
}
}
private void handleNavigate(Intent intent, VoiceInteractionSessionCallback callback) {
String destination = intent.getStringExtra("destination");
// 调用导航模块
callback.onResult("正在导航到 " + destination);
}
}
onHide()。记得在 onHide() 中停止语音合成和动画,避免资源泄漏。
8.2 自定义唤醒词:让车「认得」你的声音
唤醒词,就是那句「嗨,小蓝」或者「你好,车机」。Android Automotive 支持自定义唤醒词,但实现起来有几个关键点。
首先,唤醒词检测通常由底层 DSP(数字信号处理器)完成,不占用主 CPU。这样即使车机在休眠状态,也能被唤醒。我建议你使用 KeyphraseEnrollmentManager 来管理唤醒词的注册和训练。
KeyphraseEnrollmentManager manager =
(KeyphraseEnrollmentManager) context.getSystemService(Context.KEYPHRASE_ENROLLMENT_SERVICE);
// 注册自定义唤醒词
manager.enrollKeyphrase("你好小蓝", Locale.CHINESE, new EnrollmentCallback() {
@Override
public void onEnrollmentProgress(int progress) {
// 训练进度 0-100
}
@Override
public void onEnrollmentError(int errorCode, CharSequence errorMessage) {
// 处理错误
}
});
另外,唤醒词模型需要适配车内噪声环境。我建议在实车采集至少 200 条语音样本,包含不同车速、不同风噪的场景。否则,高速上喊破嗓子车都没反应。
8.3 多轮对话管理:别让用户重复说
多轮对话,是车载语音助手的「高阶技能」。比如用户说「导航到天安门」,系统问「走高速还是普通路?」,用户说「高速」,系统再问「要避开拥堵吗?」。这就是典型的多轮对话。
Android Automotive 没有内置的多轮对话框架,但我们可以基于 VoiceInteractionSession 自己实现一个简单的状态机。
我习惯用一个 DialogState 枚举来管理当前对话的阶段:
public enum DialogState {
IDLE,
WAITING_DESTINATION,
WAITING_ROUTE_TYPE,
WAITING_TRAFFIC_PREFERENCE,
COMPLETED
}
public class MultiTurnDialogManager {
private DialogState currentState = DialogState.IDLE;
private Map<String, String> slotData = new HashMap<>();
public String processInput(String userInput) {
switch (currentState) {
case IDLE:
if (userInput.contains("导航")) {
currentState = DialogState.WAITING_DESTINATION;
return "请问您要去哪里?";
}
break;
case WAITING_DESTINATION:
slotData.put("destination", userInput);
currentState = DialogState.WAITING_ROUTE_TYPE;
return "走高速还是普通路?";
case WAITING_ROUTE_TYPE:
slotData.put("routeType", userInput);
currentState = DialogState.WAITING_TRAFFIC_PREFERENCE;
return "要避开拥堵吗?";
case WAITING_TRAFFIC_PREFERENCE:
slotData.put("trafficPreference", userInput);
currentState = DialogState.COMPLETED;
return buildNavigationCommand();
}
return "我没听清,请再说一遍";
}
}
CANCEL 状态,系统会一直卡在 WAITING_DESTINATION。所以,一定要监听类似「取消」「返回」「算了」这样的关键词,及时重置状态。
8.4 场景引擎集成:让语音「懂」当前场景
场景引擎,是车载语音助手的「大脑」。它根据当前车辆状态、时间、位置、用户习惯等信息,决定语音助手的响应策略。
举个例子:
- 车辆在高速上,用户说「我冷了」,场景引擎应该调高空调温度,而不是打开车窗。
- 车辆在充电,用户说「我要休息」,场景引擎应该推荐附近的酒店,而不是加油站。
场景引擎的架构,我一般分为三层:
- 数据层:收集车辆信号(车速、电量、车门状态)、时间、GPS 位置、用户画像。
- 规则层:定义场景规则。比如「车速 > 80 km/h 且 室外温度 < 10°C」→ 场景 = 「高速低温」。
- 决策层:根据场景,调整语音助手的意图解析权重和回复策略。
下面是我画的一张场景引擎架构图,方便你理解整体流程:
集成场景引擎后,语音助手的「智商」会明显提升。我曾在一次 demo 中演示:车辆进入隧道,用户说「我有点闷」,系统自动打开外循环并降低空调风速。客户当场就拍板了。
- CarVoiceInteractionSession 是语音交互的容器,管理生命周期和意图分发。
- 自定义唤醒词要兼顾识别率和误唤醒率,建议在实车采集噪声样本。
- 多轮对话用状态机管理,别忘了处理「取消」和「反悔」场景。
- 场景引擎让语音助手「懂场景」,三层架构(数据层、规则层、决策层)是主流方案。
车载语音助手开发,说到底就是让机器学会「听」和「说」,并且「听懂」车内的环境。嗯,这一章的内容就到这里。如果你在实际开发中遇到什么奇怪的问题,欢迎来交流。