开发者社区> livevideostack> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

video_replay如何捕获和回放WebRTC视频流

简介: 视频编码问题常常是最难解决的问题之一,video_replay工具可以帮助分析定位故障。
+关注继续查看

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

视频编码问题常常是最难解决的问题之一,video_replay工具可以帮助分析定位故障。视频协作平台pixip的工程师Stian Selnes撰文,详解了如何通过video_replay来捕获、分析视频的。LiveVideoStack对本文进行了摘译。


文 / Stian Selnes

译 / 刘庆超


在数据包有丢失的环境下进行视频解码不是一件容易的事。Chrome 58中引入了一种新的视频抖动缓冲区,这导致最新版的Chrome在视频显示时一直有问题。由于该问题只在某些数据包丢失时才会出现,因此调试难度很大。为此,webrtc.org提供了一个名为video_replay的工具来复现和分析这些棘手问题。


当看到Stian Selnes提交的一个版本中视频显示仍然有问题时,我将这个工具告诉了他。将视频流轻松重现后,谷歌的WebRTC视频团队很快就解决了这个bug。不过,这一过程的记录做得不是很好,所以我们请Stian重现了抓取必要数据和使用该工具进行操作的过程。Stian目前在pexip工作,他有超过10年的实时通信处理经验。他在媒体协议栈领域有非常丰富的经验,特别是在视频编解码以及其他类型的信号处理、网络协议和错误恢复能力等方面。


640?wx_fmt=png


WebRTC包含了一个非常好用但鲜为人知的工具——video_replay。事实证明,在调试视频解码问题时,这个工具非常好用。它的目的是什么呢?为了在发现异常行为之后能容易地重复捕获WebRTC呼叫,video_replay将捕获的RTP流视频作为输入文件,然后离线使用WebRTC框架来解码数据,最后在屏幕上显示输出的结果。


例如,最近我正在研究一个问题,有一个版本的Chrome显示输入的视频时突然出了上面这样的问题。最终,使用video_replay调试后,WebRTC的团队发现,Chrome中实现抖动缓冲区的部分出现了一个错误,这导致视频流在某些情况下显示会有异常。这种看似随机数据导致的错误其实是VP8解码器的内部状态引起的。

 

640?wx_fmt=png


视频编码问题常常是最难解决的问题之一。最初,我自己写了一个测试方法,每20次调用中大约复现1次这样的问题。使用这种方法重现问题是非常耗时的,效果通常也不好,最终也没有给WebRTC团队解决该问题起到什么作用。


为了可以多次重现这个问题,我设法使用wireshark捕获到一个失败的呼叫,然后使用video_replay工具来分析。这样我就有了一个每次都能重现这个罕见的问题测试用例。当一个问题具有重复性的时候,解决问题和打补丁就非常轻松啦!这是典型的双赢局面。


在这篇文章中,我将通过一个例子来演示如何使用video_replay,包括如何来捕捉一个WebRTC呼叫的RTP通信数据,识别和提取接收到的视频流,最后如何导入到video_replay中来实现在屏幕上显示捕获的视频。


捕获未加密的RTP数据


video_replay将输入的文件导入到RTP协议栈、协议包解析设备和解码器中,不过目前还没有能力解密加密呼叫使用的SRTP包。Chrome和Firefox都支持加密呼叫,但是解密WebRTC呼叫却不是一个简单的过程。尤其是SRTP进行秘钥分发时使用DTLS来保密共享,因此该秘钥难以获得。为此,最好用Chromium或Chrome Canary,因为它们有一个可以禁用SRTP加密的选项。启动浏览器时添加命令行标志–disable-webrtc-encryption即可,如果在窗口的顶部看到警告信息,说明你使用的浏览器不支持命令行标志。注意,这要求双方在通话都不能加密,否则会话将无法连接。


首先,使用Wireshark捕获数据包。在会话开始发送媒体数据之前就要打开捕获功能,这一点很重要,因为这可以将整个流都能记录下来。如果捕获的数据中丢失了流的开头,视频解码器将无法解码。


第二,打开一个选项卡,进入chrome://webrtc-internals (或者Fippo最新的webrtc-externals).。呼叫之前首先做这个,以获取所有需要的信息,特别是SDP协商信息(如果想深入分析该问题,请见webrtchacks SDP分析指导)。


最后,就是呼叫了。我们以appr.tc为例,但适用于任何使用WebRTC的呼叫。打开第二标签进入https://appr.tc/?IPv6 = false。由于目前video_replay尚没有IPv6相关的解决方案,因此在这个例子中,我将其禁用,希望该问题能很快解决。


现在,加入一个直播室。当第二个参与者加入同一个房间时,RTP将开始流动。不管谁先加入,除非chrome://webrtc-internals看起来有异常。下面的截图是在拨号进入现有房间时拍摄的。


收集信息


为了从接收到的流中成功获得RTP包,并能顺利使用video_replay播放,我们需要收集一些关于RTP流的细节信息。有几种方法可以做到这一点,我坚信最重要的是下面这几个:


  • Video codec 视频编码

  • RTP SSRC  RTP SSRC

  • RTP payload types RTP 载荷类型

  • IP address and port  IP地址和端口


使用webrtc-internals来收集统计信息 


首先,扩大接收到的视频流的统计表,给一个类似于ssrc_4075734755_recv这样的命名。统计表可能不止一个,一般第二个是音频流,还可能有一对以_send为后缀的表,里面是发送流的等效统计信息。视频流接收的统计表可以根据_recv后缀和mediaType=video来识别出来。分别记下ssrc、googCodecName 和transportId属性,例如4075734755、VP9和channel-audio-1。


你可能会问为什么的视频流和音频通道有相同的transportid?这表示使用了BUNDLE来使音频和视频共享通道。如果BUNDLE没有协商和使用,音频和视频将使用单独的通道。

 

640?wx_fmt=png


下一步,我们将查看协商的SDP以获得RTP有效载荷类型(PT)。除了PT使用的视频编解码器,我们还必须找到RED的PT标记,这个PT是WebRTC用来封装的视频包的。SDP描述了视频客户端的接收能力,因此为了找到接收到的有效负载类型,我们必须查看浏览器向另一个参与者提供的SDP类型。


这可以通过扩展的setlocaldescription API调用找到,找到M =video的部分和后面每个支持的编解码器的PT的rtpmap定义。由于我们的视频编解码器的VP9,我们会关注的属性是a=rtpmap:98 / 90000和a= rtpmap:102 red/9000,这告诉我们,VP9和RED的有效载荷类型分别为98和102。

 

640?wx_fmt=png


如果你正在寻找发送流而不是接收的信息,你应该看看其他参与者通过setRemoteDescription的扩展字段标记了什么。事实上,载荷字段的类型应该是对称的,所以无论你看setlocaldescription或setremotedescription无关紧要,但在实时视频通信的世界,没人什么都知道,所以最好是都看一下。


为了在Wireshark中快速确定正确的RTP流,需要知道IP地址和使用端口。远程或本地地址并不重要,只要使用适当的wireshark过滤就行。对于这个示例,我们将使用本地地址,因为我们希望提取所接收的流,所以它是数据包的目的地。在chrome://webrtc-internals 的Conn-audio  和 Conn-video部分包含了连接的统计信息。处于活跃状态的用粗体突出显示,根据上一步提到的transportid我们就可以知道要看视频还是音频通道。


为了在我们的例子中找到本地地址,我们需要扩大conn-audio-1-0,并且注意googlocaladdress,其值为10.47.4.245:52740。


640?wx_fmt=png


Wireshark中的RTP标记


现在,为了在我们的呼叫中方便地识别和提取所接收的视频流,我们已经收集了所有必要的信息。Wireshark可能会将捕获的RTP数据包简单地以UDP数据包来显示。我们想告诉Wireshark这些是RTP包,所以我们可以将其导出为rtpdump格式。


首先,使用地址和端口显示过滤器,例如ip.dst = = 10.47.4.245和udp.dstport = = 52740。然后,右击一个数据包,选择解码为,然后选择RTP。


其次,选择菜单电话→RTP →RTP流,列出列表中的所有RTP流。我们接收到的视频流中的SSRC连同其他流的一起列出来,选择并导出为rtpdump格式。(video_replay还支持PCAP格式,但由于其对各种链路层的支持非常有限,我一般推荐使用rtpdump。)最后我们有一个文件只包含接收的视频数据包,可以将其导入到video_replay中。


640?wx_fmt=png640?wx_fmt=png


建立WebRTC 和 video_replay


使用之前,需要从WebRTC源码生成video_replay。如何设置环境、获取代码和编译等一般性的说明可以从https://webrtc.org/native-code/development中查到。注意,为了能生成video_replay工具,在编译时需要将其明确指定为一个目标。总之,在确定必要的软件已经安装了之后,下面的命令可以获得代码和生成video_replay:



1mkdir webrtc-checkout
2cd webrtc-checkout/
3fetch --nohooks webrtc
4gclient sync
5cd src
6gn gen out/Default
7ninja -C out/Default video_replay


使用video_replay重放捕捉信息


最后重播捕获的流,并希望之前它是如何在appr.tc中的状态可以准确地显示出来。我们的示例做到这一点的最小命令行是:


1out/Default/video_replay -input_file received-video.rtpdump -codec VP9 -media_payload_type 98 -red_payload_type 102 -ssrc 4075734755

(注意:媒体payload_type参数之前命名为payload)


根据之前的说明, 命令行的参数也非常容易理解。


video_replay参数


如果你的目标是重现WebRTC出现问题后的bug,对于某些问题,将rtpdump连同命令行参数一起进行重放将有巨大的帮助。如果你想多做一些自己的video_replay调试,有几个命令行选项可能会很有用。


让我们看看当前的帮助文本并解释不同选项的作用。编写这一文件时,../../webrtc/video/replay.cc的标记有如下:



1-abs_send_time_id (RTP extension ID for abs-send-time) type: int32 default: -1
2-codec (Video codec) type: string default: "VP8"
3-decoder_bitstream_filename (Decoder bitstream output file) type: string default: ""
4-fec_payload_type (ULPFEC payload type) type: int32 default: -1
5-input_file (input file) type: string default: ""
6-out_base (Basename (excluding .yuv) for raw output) type: string default: ""
7-payload_type (Payload type) type: int32 default: 123
8-payload_type_rtx (RTX payload type) type: int32 default: 98
9-red_payload_type (RED payload type) type: int32 default: -1
10-ssrc (Incoming SSRC) type: uint64 default: 12648429
11-ssrc_rtx (Incoming RTX SSRC) type: uint64 default: 195939069
12-transmission_offset_id (RTP extension ID for transmission-offset) type: int32 default: -1


下面是关于它们的更多解释:


640?wx_fmt=png


快捷方法


当你熟悉上面的过程时,你可以使用一些快捷方式来提高效率。首先,你可以使用Wireshark中查看RTP视频包而不必使用chrome://webrtc-internals。大多数视频包通常超过1000字节,而音频数据包一般也就几百字节。将解码的视频数据包使用RTP协议在Wireshark中处理,可以同时显示SSRC和有效载荷类型。Wireshark不能自动确定是RED有没有用,但是可以从经验中猜到,因为有效载荷类型一般不会在通话之间改变。


其次,如果你的video_replay支持pcap,你可以将原有pcap直接导入video_replay中。由于忽略了所有未知的数据包,命令行输出可能会有很多错误,但它可以解码并显示指定的流。


WebRTCon 2018 8折报名


WebRTCon希望与行业专家一同分享、探讨当下技术热点、行业最佳应用实践。如果你拥有音视频领域独当一面的能力,欢迎申请成为讲师,分享你的实践和洞察,请联系 speaker@livevideostack.com。更多详情扫描下图二维码

640?wx_fmt=jpeg

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
SAP CRM Fiori应用Simulation pipeline的刷新问题
在Simulation pipeline里修改opportunity的status之后,有两种方式trigger OData update request到后来来保存这个change:
59 0
replace(char oldChar, char newChar)源码分析
一String中的replace(char oldChar, char newChar)源码 以下是JRE中源码,分析在第二部分,将全面分析这个方法。
950 0
分布式RPC框架性能大比拼 dubbo、motan、rpcx、gRPC、thrift的性能比较
Dubbo 是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。不过,略有遗憾的是,据说在淘宝内部,dubbo由于跟淘宝另一个类似的框架HSF(非开源)有竞争关系,导致dubbo团队已经解散(参见http://www.oschina.net/news/55059/druid-1-0-9 中的评论),反到是当当网的扩展版本仍在持续发展,墙内开花墙外香。
5477 0
Chapter 1 Securing Your Server and Network(3):使用托管服务帐号
原文: Chapter 1 Securing Your Server and Network(3):使用托管服务帐号 原文出处:http://blog.csdn.net/dba_huangzj/article/details/38017703,专题目录:http://blog.csdn.net/dba_huangzj/article/details/37906349 未经作者同意,任何人不得以“原创”形式发布,也不得已用于商业用途,本人不负责任何法律责任。
1081 0
ShmooCon IX: Moloch: A New And Free Way To Index Your Packet Capture Repository
http://securitykb.org/2013/04/10/shmoocon-ix-moloch-a-new-and-free-way-to-index-your-packet-cap...
793 0
UC编程04-io读写write/read系统函数的使用
////myuc.h #include #include #include #include #include #include #include #include #include #include #include ...
763 0
+关注
livevideostack
LiveVideoStack是专注在音视频领域的技术社区媒体,成立于2017年初,通过LiveVideoStackCon等技术大会、技术培训、高质量技术内容及咨询服务,推动相关开源项目与最佳实践普及和传播,帮助技术人成长,解决企业发展中的技术难点。
文章
问答
文章排行榜
最热
最新
相关电子书
更多
全景视频的播放及优化
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载