亚马逊Alexa WebRTC对接天坑之路

引言

本文由zlmediakit核心开发者 monktan(老衲不出家)编写,夏楚审阅修订;文章主要记录了作者在对接亚马逊Alexa设备时遇到的一些经验教训,希望前人趟过的坑后人无需再趟。

1、背景

因业务发展,需要在亚马逊Alexa设备上实现与访客视频对讲;调研发现亚马逊Lambad Alexa Skill平台(以下简称亚马逊平台)支持WebRTCRTSP两种方式接入,由于需要实现双向对讲,只能采用WebRTC方式与Alexa设备对接;至于门铃设备端,硬件资源有限且不带屏幕,我们采用的私有协议方式接入。为了便于读者理解,我们省去了发现、认证等流程,整体架构流程图如下:

2、开始趟坑

研究Alexa WebRTC接入相关文档,发现其视频支持H264编码格式,音频则支持Opus/PCMU/PCMA/AAC

由于WebRTC协议通常不支持AAC,为了节省时间,我们直接采用更简单的PCMU(而不是Opus)来测试,然而测试发现Alexa设备竟然无法播放,于是我们对比了之前对接过的web demo,发现竟然是通的,其架构方式也基本一致:

3、趟坑之路

由于Alexa设备死活无法播放门铃的音视频流而web demo却一切正常,我做了大量的努力和尝试,包括sdp的分析对比,rtp的分析对比、变换音频编码格式(因为单视频模式有播放成功的案例,原因是单视频模式请求链路时间不一样,时间更短)、音频编码切片长度、音视频时间戳同步、分析设备日志等工作。

3.1 趟坑之路一,分析对比SDP

  • Alexa设备Offer

  • 平台回复Answer

这里咋一看好像没啥问题;仔细发现,Alexa PCMU和PCMA在SDP中没有出现a=rtpmap,可能导致协商不成功,于是我修改了SDP,添加了:a=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\n,然而发现并没什么用,还是对接Alexa设备无输出。

3.2 趟坑之路二,抓包分析

web demo推流,Alexa设备可以正常播放,但是拉取门铃设备流无法播放,分别对起流进行抓包分析对比:

对比发现两个流同样都是PCMU数据,但是数据长度不一样,上面的能播放,下面的无法播放语音,导致我初步怀疑是因为上面启用了RTP扩展导致可以播放,分析SRTP包发现,web端推流确实多了RTP扩展,所以长度多了8个字节

此时的我虽然不太相信是由于RTP扩展引起Alexa设备无法播放语音,但是对于Alexa黑盒来说,只有尽力一试了,通过修改服务端代码,终于做成与web推断流数据包一模一样了;然而,结果并没有什么不一样,web端推流和设备推流到底问题在哪里,分析了数据长度,数据发送频率,音频时间间隔,时间戳增量,甚至尝试过NTP时间发送,都是没有任何效果,依然是播放不出来的。

把数据分析数据发给其他WebRTC领域专家们分析,他们也看不出什么问题,建议我使用opus编码尝试一下,毕竟它在Alexa官网是preferred codec,鉴于此决定先用opus尝试。

【学习地址】:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发

【文章福利】:免费领取更多音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击1079654574加群领取哦~

3.3 趟坑之路三,换Opus编码

opus编码在FFmpeg中直接采用AV_CODEC_ID_OPUS方式查找的解码器,找到的是内置opus编码器,实测发现编码延时很大,达到了普遍350ms~450ms的延迟(编码机器linux cvm 8c16g主机),下面是FFmpeg内部源码:

最后定位内置的opusenc.c(注意, 不是libopusenc.c)设置的frame_size120帧, opus采样率48000也就是2.5ms一帧,理论采样延时大概300ms;从我测试的情况来看, 编码延时很高(400+ms):

由于内置opusenc.c编码器延迟实在太大,显然不适合WebRTC低延时场景,开始有点不知所以,后来在朋友的指导下,发现FFmpeg还有个libopus编码器,于是决定使用libopus来编码,FFmpeg中libopus信息如下:

替换libopus编码后,编码延时在40~50ms内,效果符合预期的;然而在做了音视频同步后,Alexa依然播放不出opus语音,此时已经快到了黔驴技穷的边缘了。

3.4 趟坑之路四,分析Alexa日志

对于Alexa这个黑盒,我们极度缺乏调试手段,只能通过给Amazon提交工单,很遗憾,工单并未得到相应回复,通过内部关系找到Alexa中国区负责对接人,对方需要提供公司对接商务信息,才能予以支持,且需要走商务流程;没办法,只能抓取Android端Alexa智能这个APP日志看能否找到相应线索。

于是搭建Android adb环境,抓取com.amazon.dee.app:alexa包日志:

# 查看进程号
adb shell ps
# 抓取日志, xxx为进程号
adb logcat xxx

不出意外,你将会得到一堆无用的日志信息:

3.5 趟坑之路五,柳暗花明

经过长时间的尝试,始终无法攻克这个问题,后续差点绝望到想放弃,实在没办法,于是只能在逐字逐句的查看文档,看看能不能得到点线索,看到这里:

终于顿悟!看描述本意是,Alexa设备发起offer请求后,需要在6s内回复相应的Answer SDP,然而最后实测发现这个6s是需要包含音视频数据的,如果6s内没有音视频数据发送,Alexa建立连接失败,但是 不会有任何提示,不会有任何提示,不会有任何提示!

  • 经过一番调整,终于完美播放:

4、总结

经过这番折腾,最后复盘下事情的来龙去脉,开始死活不通的原因如下:

  • 亚马逊的服务器部署在海外,整个信令交互延时很高,大大降低了在6秒钟内完成交互的成功率,这也是一直失败的最大原因。

  • 门铃设备的唤醒、控制延时较高,加大了整个链路的的延时。

  • 门铃设备音频采集、编码、输出时间比视频晚几百毫秒,导致单视频成功率较高,但是复合流时成功率很低,从而产生音频数据是否有问题的误导,浪费很多时间花在排查音频切片(确保20ms一个包)、编码、时间戳等问题上。

  • Alexa设备是个封闭的黑盒设备,无法获取准确的失败原因;另外,其文档描述也不准确;这些坑必须一个一个趟出来,没有前人指导,很难注意到这些问题,而国内在这方面的实践较少,相关技术文章不多。

最后,感谢整个过程一直支持我的小伙伴们,感谢他们的悉心指导,遇事不要气馁,自己短期解决不了的问题,不要死磕牛角尖,尽量集思广益,从不同角度去尝试,最终你会发现,这可能根本就不是一个技术问题!

原文链接:亚马逊Alexa WebRTC对接天坑之路

猜你喜欢

转载自blog.csdn.net/irainsa/article/details/130140591