18、SDL语音与导航集成:SDL语音命令注册、SDL导航TTS、SDL WayPoints管理、SDL AppLink集成

各位同学,今天我们来聊聊车载开发中一个非常“有温度”的话题——语音与导航集成。说实话,在座舱里,用户最常用的两个交互方式就是“说”和“看路”。SDL作为连接手机和车机的桥梁,把这俩功能做好,用户体验直接上一个台阶。

我个人习惯把这一章分成四个核心模块:语音命令怎么注册、导航TTS怎么播报、途经点怎么管理、以及AppLink怎么把这一切串起来。咱们一个一个来拆。

18.1 SDL语音命令注册

先说说语音。SDL的语音命令,说白了就是让车机听懂用户说了什么,然后触发对应的App功能。你想想看,开车的时候,用户说“导航到公司”,车机就能自动打开导航App并设置目的地——这多爽。

在SDL里,语音命令是通过AddCommand这个RPC来实现的。你需要指定一个vrCommands数组,里面放上用户可能说的语音短语。比如:

// 伪代码示例
AddCommand addCmd = new AddCommand();
addCmd.setCmdID(1);
addCmd.setMenuParams("导航到公司");
addCmd.setVrCommands(Arrays.asList("导航到公司", "去公司", "公司怎么走"));
sdlProxy.addCommand(addCmd);

这里有个坑,我踩过。语音短语不要写太长,3-5个字最佳。太长的话,车机语音识别引擎容易出错。另外,同一个功能最好配2-3个同义短语,用户的口语习惯千差万别,你只写一个“导航到公司”,用户说“去公司”就识别不了。

核心要点:语音命令的注册,本质上是把用户的自然语言映射到App的某个功能入口。映射关系越丰富,用户体验越好。

18.2 SDL导航TTS

导航TTS,就是让车机把导航提示“读”出来。比如“前方300米右转”、“您已到达目的地”。在SDL里,这个功能是通过Speak这个RPC来实现的。

我记得在项目中,有一次客户反馈说导航播报和音乐播放冲突了。音乐声音突然变小,导航播报完又恢复——这个效果其实是对的,但客户觉得“太突兀”。后来我们调整了TTS的优先级和混音策略,才让体验变得平滑。

代码层面,TTS的调用很简单:

// 伪代码示例
TTSChunk chunk = new TTSChunk();
chunk.setText("前方300米,请右转");
chunk.setType(SpeechCapabilities.TEXT);

Speak speak = new Speak();
speak.setTtsChunks(Collections.singletonList(chunk));
sdlProxy.sendRPCRequest(speak);

但要注意,TTS的文本不要写得太长。我建议单次播报不超过15个字。太长的话,用户记不住,也容易烦躁。另外,播报的时机也很关键——不要在用户正在操作中控屏的时候突然插话,那会让人很恼火。

小技巧:导航TTS的文本,可以加入一些“人性化”的表达。比如“前方300米右转,请提前变道”,比单纯的“前方300米右转”听起来更自然。

18.3 SDL WayPoints管理

WayPoints,就是途经点。比如你从北京开车去上海,中间想在济南停一下吃个饭,济南就是一个途经点。SDL支持在导航过程中动态添加、删除、修改途经点。

这个功能在SDL里是通过WayPoint这个数据结构来管理的。每个途经点包含经纬度、名称、地址等信息。你可以通过SendLocationSubmitNavigation来设置途经点。

// 伪代码示例
LocationDetails waypoint = new LocationDetails();
waypoint.setLatitude(36.65);
waypoint.setLongitude(116.98);
waypoint.setLocationName("济南服务区");
waypoint.setAddress("济南市历下区");

SubmitNavigation nav = new SubmitNavigation();
nav.setDestination(waypoint);
nav.setWayPoints(Arrays.asList(waypoint));
sdlProxy.sendRPCRequest(nav);

这里要特别提醒一下:途经点的数量不要太多。SDL规范里建议不超过10个,但我个人建议控制在5个以内。你想想看,用户开车已经很累了,你让他一路设10个途经点,导航路线会变得非常复杂,反而容易走错路。

避坑指南:我曾经在项目中遇到过一个问题——途经点设置后,导航路线没有重新计算。后来发现是因为没有设置navigationType参数。记得在请求里明确指定是“导航”还是“路线规划”,否则车机可能只记录位置,不触发导航。

18.4 SDL AppLink集成

AppLink,是SDL里一个比较“高级”的玩法。它允许手机App和车机之间建立一种“深度链接”的关系。说白了,就是手机App可以主动把一些数据推送到车机上,而不需要用户手动操作。

举个例子:你在手机上用地图App规划了一条路线,点击“发送到车机”,这条路线就能自动出现在车机导航上。这就是AppLink的典型应用场景。

AppLink的集成,需要手机App和车机App两端配合。手机端通过SDL的AppLink接口发送数据,车机端通过OnAppLink回调来接收数据。

// 手机端发送数据
AppLinkData data = new AppLinkData();
data.setUrl("https://maps.example.com/route?from=...&to=...");
data.setTitle("我的导航路线");
sdlProxy.sendAppLinkData(data);

// 车机端接收数据
@Override
public void onAppLink(AppLinkData data) {
    String url = data.getUrl();
    // 解析URL,启动导航
    startNavigation(url);
}

嗯,这里要注意安全。AppLink传输的数据,一定要做合法性校验。我曾经见过一个案例,手机端发送了一个恶意URL,导致车机导航崩溃。所以,接收端一定要对URL做白名单过滤,只允许可信的域名。

总结一下:AppLink的本质,是让手机App和车机App之间建立一条“数据通道”。这条通道可以用来传输导航路线、音乐播放列表、甚至车辆控制指令。用好它,你的车载应用会变得非常“智能”。

知识体系总览

下面这张图,是我自己整理的SDL语音与导航集成的整体架构。你可以看到,语音命令、TTS、WayPoints、AppLink这四个模块,最终都汇聚到SDL核心层,再通过车机端的HMI呈现给用户。

SDL语音与导航集成架构 语音命令注册 AddCommand / VR 导航TTS Speak / 语音播报 WayPoints管理 途经点增删改 AppLink集成 深度链接 SDL核心层(RPC调度 / 协议解析) AddCommand / Speak / SubmitNavigation / AppLink 车机HMI层(用户交互界面) 语音识别 / 导航地图 / 路线显示 / 播报 用户

从这张图你可以看到,语音命令和TTS属于“输入-输出”的闭环,用户说一句话,车机播报一个结果。WayPoints和AppLink则更偏向“数据管理”和“跨设备协同”。这四个模块组合起来,基本覆盖了车载导航场景下的大部分交互需求。

好了,这一章的内容就到这里。语音和导航的集成,说难不难,说简单也不简单。关键是要理解SDL的RPC机制,以及每个接口背后的设计意图。你把这些搞懂了,后面做复杂场景的集成就会顺手很多。


公众号:蓝海资料掘金营,微信deep3321