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

Wesley13
• 阅读 742

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

视频编码问题常常是最难解决的问题之一,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年的实时通信处理经验。他在媒体协议栈领域有非常丰富的经验,特别是在视频编解码以及其他类型的信号处理、网络协议和错误恢复能力等方面。

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

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

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

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

视频编码问题常常是最难解决的问题之一。最初,我自己写了一个测试方法,每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没有协商和使用,音频和视频将使用单独的通道。

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

下一步,我们将查看协商的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。

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

如果你正在寻找发送流而不是接收的信息,你应该看看其他参与者通过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。

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

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中。

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

建立WebRTC 和 video_replay

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

1mkdir webrtc-checkout2cd webrtc-checkout/3fetch --nohooks webrtc4gclient sync5cd src6gn gen out/Default7ninja -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: -110-ssrc (Incoming SSRC) type: uint64 default: 1264842911-ssrc_rtx (Incoming RTX SSRC) type: uint64 default: 19593906912-transmission_offset_id (RTP extension ID for transmission-offset) type: int32 default: -1

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

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

快捷方法

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

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

WebRTCon 2018 8折报名

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

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

本文分享自微信公众号 - LiveVideoStack(livevideostack)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这