云控平台的双向音频解决方案

导读

随着移动互联网的发展,行业内衍生了基于移动平台的各类解决方案。其中,设备规模化管理的云控能力是各互联网公司在设备集群控制背景下的诉求。因此涌现了大批提供类似解决方案的平台。如:阿里系的阿里云MQC、阿里无线和菜鸟Nimitz等,阿里之外的有Testin、百度MTC、腾讯WeTest、华为、三星等等。

目前以上平台在云真机的使用上,都存在一个已知的短板 —— 声音。用户看的到画面,能够响应操作,但是涉及到声音播报、语音交互的场景时则无能为力。尤其对于音乐、视听、短视频、直播客户端等这类多媒体属性强的App,在云真机的使用场景上是受限最大的。

现在回到我们自己的产品。高德地图车机/镜版(后面统称Auto)。其中最常见的导航播报、与系统的多媒体混音交互、以及语音助手多轮对话的交互场景中,这些与声音相关的场景占比高达25%以上。所以解决远程场景下的声音双向交互问题,是云真机要成为一个日常化的生产工具之前必须迈过的坎。

 

挑战

在远程音频的双向通讯解决方案的背景下,满足基本用户体验的方面也存在以下挑战:

  • 能力:满足所有车载设备的声音场景的双向交互能力(因为车载设备在声音部分比手机具有更高的定制性,在覆盖车载场景后,手机基本可以无缝适配);
  • 延迟:传输延迟低于500ms(基于一定的网络条件);
  • 体验:无明显卡顿、杂音问题。

设想

首先通过下面的一张图来了解一下我们的需求是什么:

 

  • 将声音通过电脑传输到远端的车机设备(车机系统能正常解析处理);
  • 将车机通过喇叭播报出的声音传输到用户端。

而实现这两条链路,关键核心的两个因素是:

  • 如何获取和写入音频数据;
  • 如何实现实时的音频数据在车机和用户设备间的传输链路。

音频获取和写入

Android系统音频概要

在思考如何进行设备的音频获取前,我们先来了解下Android的音频系统架构:

 

上图描述了音频通信从应用层、Libraries、HAL、到Driver,最后到硬件模块各层主要实现。而我们也需要从这条链路中去挖掘获取和写入音频数据的思路。

首先,我们考虑的是Android对应的音频链路中是否有成熟的支持双向音频的能力。即音频数据在OS内部获取到对外传输。

REMOTE_SUBMIX

API 19新加的MediaRecorder. AudioSource. REMOTE_ SUBMIX,用于传输系统混音的音频流到远端(在API 18也存在,只是属于隐藏属性)。

由于要生效REMOTE_SUBMIX,需要Manifest. permission. CAPTURE_ AUDIO_ OUTPUT权限,而该权限只有系统组件才具备。也就是如果第三方App需要的话,需要进行系统签名或者在烧写OS版本时就修改对应的权限。作为系统方是可以这么操作的,但显然对于要适配所有系统方的我们来说不适用。

软件hook

考虑到我们拿到的车载设备中,root比例高达80%以上。因此我们想从在音频数据传输到底层硬件驱动前进行“截胡”。也就是hook HAL定义的往驱动写入和读取对应音频数据的方法,来达到音频数据的双向获取。

  • hook HAL hardware

hw hook的是struct audio_hw_device的
音频输出:open_output_stream、close_output_stream 
音频输入:open_input_stream、close_input_stream

system/lib/hw/audio.primary.*.so (不同的设备有后缀部分差异)

  • hook tinyalsa

在实际的调研测试中,我们发现并不是每台设备都能通过hook hw 来获取到对应的声音数据,尤其是车载设备。于是我们又调研了ALSA(Advanced Linux Sound Architecture)高级Linux声音架构。根据官方的推荐,我们选择了具备GPL-licensed 的external/tinyalsa

hook tinyalsa.so

音频输出:pcm_open、pcm_close、pcm_write、pcm_mmap_write

音频输入:pcm_open、pcm_close、pcm_read、pcm_mmap_read

system/lib/libtinyalsa.so

  • 问题

在实际摸底验证中,我们发现车机比手机还复杂的原因在于多了功放的概念,而部分车厂选择在设备的DSP模块去处理混音。带来的问题就是部分设备如果单纯的通过hook播报,对应听到的声音与设备真实通过喇叭播报的效果不同,这也导致我们对于该场景的还原并不真实。

因此,在于root设备覆盖不完全且部分设备存在硬件功放处理混音问题的情况下,软件hook的方案只能适用于部分设备。

  • 成本

hook自身也会带来一个问题,即针对不同的车机需要每台都进行hook处理,使得hook带来的成本过高。需要批量一键hook来解决这个问题。

分析到这里,我们回顾下音频传输的链路:

 

基于以上我们对音频获取的这条传输链路上的分析,现在理论上可行的获取途径,就只有硬件的对接或者具体的接收端(喇叭、蓝牙)。

usb音频

硬件对接部分,在云控场景下,我们的设备通常是通过USB线束与我们的节点PC连接的。因此音频通过USB进行传输的链路,也是一个值得探索的方向。

我们知道,Android设备在连接usb时有三种模式:Host、Development、Accessory Mode:

  • 主机模式:可以传输音频,但是Android设备作为主机,无法使用adb的能力;
  • 开发者模式:具备adb的能力,但是没有现成的USB音频能力;
  • 配件模式:既保留了adb的能力,在Android4.1后的配件模式下,Android 也能自动将其音频输出导向到USB。

思路:通过实现AOA协议,作为主机角色的设备,必须具有能够将Android设备从开发模式切换到配件模式的主机控制能力,然后主机从适当的端点传输音频数据

该方案的局限性在于:1、单向传输;2、配件模式取决于设备硬件,但并非所有设备都支持。实测过程中,车机支持配件模式的比例很低,绝大多数都被“阉割”了。

综上,我们无法靠单纯的某种USB模式来实现音频的双向交互。但如果是手机集群的场景中,这个方案倒是可以作为单向音频传输的一个优选方案。

蓝牙接收

声音除了可以通过usb传输以外,常见的方式还有蓝牙耳机、有线耳机。(这里由于车载设备不存在3.5mm孔,所以我们先不讨论有线方式,具体可参考后面「硬件转发」的方案)。

关于蓝牙接收的基本思路就是PC端通过安装蓝牙接收器与车机通信。其中蓝牙接收器起到类似于蓝牙耳机的作用。然后对蓝牙接收器的收发数据在PC端进行编码处理。

蓝牙耳机:具备了可以听说的能力,也就是双向的音频通信。

摸底验证:部分车机对蓝牙驱动进行了定制,使得蓝牙设备只能作为从设备,无法接入蓝牙耳机功能。我们测试了35台,其中5台可以用,成功率14%,收益太低,成本过高。这个方案如果是面向手机集群,倒是一个不错的选择,理论上成功率应该会大大高于车载设备。

硬件转发

上面提到的有线耳机的思路。在车载设备上,不存在3.5mm孔或者type C口,而是通过主机与功放、音箱外放装置进行连接。在车辆量产上市前的研发阶段,只是一个主机通过线束连接着喇叭的一个过渡状态。所以我们实际是通过将原本接到喇叭上的音频数据通过一种转换装置转接到PC上,在PC端进行音频编码处理。

大致的参考示意效果如下:

 

上述方案的优势在于:

  • 跨平台,不管是Android、Linux、QNX或者iOS的设备都适用;
  • 解决了混音问题,由于对接的是最终播报出的声音效果,就不存在软件hook可能还原不真实的问题;
  • 支持双向音频通信。

缺点:

  • 部分智能车镜设备,由于集成封装性太强,没有暴露出可对接的线束。这类设备不容易通过该方案覆盖;
  • 需要针对车机进行线束定制来实现整体的动态封装性;
  • 需要配套的硬件成本。

硬件转发方案中存在几个方面的问题需要注意,比如失真问题、声卡识别问题、usb兼容上限、声卡与ehci、xhci的兼容性问题以及整体封装设计等等。

小结

综合以上音频传输的整条链路的所有方案,我们列举对比下这些方案的优劣(特指在车载场景下):

 

基于上述情况,考虑到车载的应用场景。最终我们的选型是 「软件hook」 +「硬件转发」的组合方案。

音频编码传输

关于音频编码传输这部分的内容,行业中已经有较成熟的解决方案,因此,这部分不展开篇幅讨论,我们仅针对一些方案做选型评估:

 

综上,从我们的应用场景以及高实时性要求考虑,最终选取了webRtc的方案。

最终选型

结合音频的获取和写入以及整体编码传输的方案,最终的技术方案选型图如下:

 

对应流程图中,也顺带涵盖了远程画面传输的视频流优化的参考链路。

总结

通过软硬件组合的方案来实现音频数据读写的能力,是一种基于特定背景条件下解决方案。但其基本推演的思路和策略,也是适用于手机平台的。而其中硬件的解决方案,理论上是适用于Android、iOS、Linux、QNX等平台设备的。

相较来说,手机的硬件转发成本更低。而对于软件的方案,实际的播报效果上仍会有很多细节问题,比如播报声音太小,需要对应设备去调节播报音量比例;出现延迟的场景,可能需要修改采样率;或是需要hook的自动化来降低成本等等。最终落地到项目中时,还需要考虑各方面的适配成本,确保整体的投入产出比。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518054.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蚂蚁金服高要求的领域建模能力,对研发来说到底指什么?

来源 | 独自慎思责编 | Carol封图由 CSDN 付费下载于视觉中国最近,由于工作需要,作者接触了网商银行的一个项目。项目里对应的业务模型设计,是我工作这三年来见过的所有模型里最复杂的。于是,利用五一这个短暂的假期,我…

如何造一个“钉钉”?谈谈消息系统架构的实现

阿里妹导读:消息类场景是表格存储(Tablestore)主推的方向之一,因其数据存储结构在消息类数据存储上具有天然优势。为了方便用户基于Tablestore为消息类场景建模,Tablestore封装Timeline模型,旨在让用户更快…

SprinBoot 集成 Flowable 工作流引擎镜像制作

文章目录一、实现原理1. 镜像制作个数2. 调用流程3. 调用流程分析二、前期准备2.1. 克隆项目到本地2.2. 修改数据库连接和容器别名2.3. 修改请求地址为容器别名(后端)三、 修改请求地址为容器别名(前端)3.1. 环境配置3.2. 安装依赖…

Android 控件 - Notification通知、Toolbar、AlertDiallog、PopupWindow

1、Notification通知 创建一个NotificationManager NotificationManager类是一个通知管理器类,这个对象是由系统维护的服务,是以单例模式的方式获得,所以一般并不直接实例化这个对象。在Activity中,可以使用Activity.getSystemSe…

阿里云 ESSD 采用自研新一代存储网络协议,打造“超级高速”

8月26日,阿里云透露,正投入自研数据存储“超级高速”,核心存储产品ESSD已率先采用这一最新的自研存储网络协议,并实现大规模商用,数据传输效率提高50%。 据了解,未来该协议还将继续演进,有望取…

1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contai

文章目录1. 现象2. docker内部mysql容器 解决方案3. windows和linux 解决方案1. 现象 在使用sql语句创建表时,报错: 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column ‘information_schema.PRO…

10 人,2 个月 | 虾米音乐的监控体系升级之路

背景 监控一直是服务端掌握应用运行状态的重要手段,经过近几年的发展,阿里虾米服务端目前已经有 100 多个 Java 应用,承担核心业务的应用也有将近 50 个,对于应用的监控配置也是因人而异。有的人配置的监控比较细,有的…

Python 本身真的没什么用!

越来越多的人学习编程不再只是为了当程序员,而是为了提升效率,多一份职业技能,正面应对瞬息万变的全球大环境。据麦肯锡全球研究院发布的一份就业报告中显示,到 2030 年,中国预计将有 1200 万~ 1.02 亿人面…

Timestream开发最佳实践

背景 Timestream模型是针对时序场景设计的特有模型,可以让用户快速完成业务代码的开发,实现相关业务需求。但是,如果业务系统不仅想实现基础的相关业务功能,还要达到最佳的性能,并且兼顾到未来的扩展性的话&#xff0…

linux-ubuntu-16.04 安装系统、安装 SSH 服务、设置root用户密码

1、ubuntu-16.04安装 使用UltraISO 软碟通 将 ubuntu-16.04-desktop-amd64.iso 制作为U盘镜像插入U盘,开机按F12选择U盘启动安装过程参考 https://blog.csdn.net/weixin_59605625/article/details/125807363 2、ubuntu-16.04 安装 SSH 服务 $ 在linux中代表普通用…

Error starting userland proxy: listen tcp 0.0.0.0:8080: bind: address already in use.

文章目录一、现象二、解决方案一、现象 [rootlocalhost app]# docker run -p 8080:8080 -p 9326:9326 --name eblog --link es_643:ees --link myrabbit:erabbit --link mymysql:emysql --link myredis:eredis -d eblog:1.0a74c2caaca88203c1ca575cd2f8a0e0426d892d5800c487…

助力企业应用与基础架构现代化 VMware这波组合拳够强!

顺应时代的发展,“数字化转型”已经成为企业发展的必由之路。应用作为数字化转型的核心,能够帮助企业向客户提供定制化的数字化体验,创造新的收入来源。在数字化转型道路上,中国企业走的并不慢甚至非常之快,在此过程中…

应用架构的核心使命是什么?阿里高级技术专家这样说

阿里妹导读:什么是架构?关于架构这个概念很难给出一个明确的定义,也没有一个标准的定义。如果,硬是要给一个概述,阿里巴巴高级技术专家张建飞认为架构就是对系统中的实体以及实体之间的关系所进行的抽象描述。今天&…

2分钟学会Docker部署SpringBoot项目

文章目录一、安装docker1. 在线安装docker2. 换镜像源二、安装redis三、安装mysql四、安装RabbitMq五、安装ElasticSearch5.1. 修改服务器配置5.2. 创建容器并启动 ES5.3. 查看启动日志5.4. 进入镜像5.5. 修改cluster-name5.6. 安装中文分词插件5.7. 退出并重启镜像5.8. 查看启…

linux-ubuntu-16.04 安装 java8、 firewalld、 mysql5.7、Redis 5.0.3、FastDFS、nginx1.18

1、安装java 新建jdk目录 cd /usr/local mkdir java下载JDK8上传到java目录下,解压文件 cd java tar -zxvf jdk-8u201-linux-x64.tar.gz链接:https://pan.baidu.com/s/155P1Y5YetBD0E4PhcPgNfg 提取码:z27j 配置环境变量 vi /etc/profi…

K8s 学习者绝对不能错过的最全知识图谱(内含 56个知识点链接)

导读:Kubernetes 作为云原生时代的“操作系统”,熟悉和使用它是每名用户的必备技能。本篇文章概述了容器服务 Kubernetes 的知识图谱,部分内容参考了网上的知识图谱,旨在帮助用户更好的了解 K8s 的相关知识。 1. 概述 容器服务 …

利用 Docker 在不同宿主机做 CentOS 系统容器 | 原力计划

作者 | 于先森2017责编 | 伍杏玲出品 | CSDN博客最近公司新接到一个项目,惯例是通过技术架构、业务需求、用户量还有以往的经验大概评估出一份资源配置表格提供给客户,让客户参考采购的服务器资源。但这次客户根本没有根据我们提供的参考表格来&#xff…

编程界的“二向箔”——Dart元编程

阅读过《三体》的同学肯定知道“降维打击”,从更高维度看问题,直接将对手KO。今天我们闲聊一下编程界的“二向箔”——元编程。 1. 什么是元编程 我们听过了太多太多的名词,耳朵似乎都有点名词麻痹症了。比如,有些名词为了装x&a…

在线安装docker

文章目录一、安装docker1. 在线安装docker2. 换镜像源一、安装docker 1. 在线安装docker #安装 yum install docker#检验安装是否成功 [rootlocalhost opt]# docker --version Docker version 1.13.1, build 7f2769b/1.13.12. 换镜像源 sudo vim /etc/docker/daemon.json 内…

linux-ubuntu-22.04 安装 java8、 firewalld、 mysql5.7、Redis 6.0、FastDFS、nginx1.18

1、安装java 可参考ubuntu-16.04,没区别 https://blog.csdn.net/qq_38959934/article/details/126101028 2、安装 firewalld 可参考ubuntu-16.04,没区别 https://blog.csdn.net/qq_38959934/article/details/126101028 3、安装 mysql5.7 apt-get in…