WebRTC 实现实时音视频技术研究

293 阅读6分钟

由于疫情原因很多公司都选择线上办公,让我对实时音视频倍感兴趣,所以决定了解下。

首先来画个饼,说下我的熟悉了解的过程。

  1. 了解下 webRTC 是个什么,能做什么。

  2. 选一家可以做实时音视频的三方集成实验下,同时也想具体了解小他们是如何实现的。

调研是了几家:腾讯,声网和融云,这三家,最后选中了融云。 首先说下为什么选择了融云:首先作为个人开发者,而且是对这块想了解的用户,融云在我注册后给我了很快的回访,我说明我的需要还有人很细致的介绍了下,体验不错。就那你先试试吧,不过有点不给力的是,集成中遇到些问题,不过提工单还是解决了。虽然过程略微有点磕磕绊绊~~~~

首先按照画饼的步骤说下 WebRTC

WebRTC 简介 WebRTC 是一个由 Google 发起的实时通讯解决方案,其中包含视频音频采集,编解码,数据传输,音视频展示等功能,我们可以通过技术快速地构建出一个音视频通讯应用。 虽然其名为 WebRTC,但是实际上它不光支持 Web 之间的音视频通讯,还支持 Android 以及 IOS 端,此外由于该项目是开源的,我们也可以通过编译 C++代码,从而达到全平台的互通。

WebRTC 架构介绍

咳咳~~ 介绍说的有点生硬,这个查 WebRTC 相关资料室看到的。不过个人看架构图还是研究了下,有点收获的大家也可以细看看,有不明白的可以深入了解下,很有意思的

再说下集成融云音视频的一些问题:

  1. 下载了 Demo,跑步起来,报了个 RongRTC-3.2.3.js:8335 Uncaught (in promise) DOMException: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': Failed to parse SessionDescription. m=video 9 UDP/TLS/RTP/SAVPF 98 99 96 97 100 101 127 Invalid value:

  2. 获取本地资源失败

说说我是如何解决的吧:

先说第二个问题吧。获取失败是因为我开了两个浏览器,有一个浏览器已经占用了资源,在第二个浏览器访问时就报了资源获取失败。好吧~只能这样了,那就不用两个浏览器呗~~~

再说问题一,由于本来就是抱着学习的态度去了解 RTC 一看报了 RTCPeerConnection 很感兴趣,正好可以好好梳理下。说以了解了下 RTCPeerConnection 和 SDP

RTCPeerConnection: 一个 RTCPeerConnection 对象允许用户在两个浏览器之间直接通讯。

SDP 中都有哪些属性,分别是什么含义:

//版本​v=0​//<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>​o=- 3089712662142082488 2 IN IP4 127.0.0.1​//会话名​s=-​//会话的起始时间和结束时间,0代表没有限制​t=0 0​//表示音频传输和data channel传输共用一个传输通道传输的媒体,通过id进行区分不同的流​a=group:BUNDLE audio data​//WebRTC Media Stream​a=msid-semantic: WMS​//m=audio说明本会话包含音频,9代表音频使用端口9来传输,但是在webrtc中现在一般不使用,如果设置为0,代表不传输音频​//使用UDP来传输RTP包,并使用TLS加密, SAVPF代表使用srtcp的反馈机制来控制通信过程​//111 103 104 9 0 8 106 105 13 110 112 113 126表示支持的编码,和后面的a=rtpmap对应​m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126​//表示你要用来接收或者发送音频使用的IP地址, webrtc使用ice传输,不使用这个地址, 关于ICE是什么后面会讲到​c=IN IP4 0.0.0.0​//用来传输rtcp的地址和端口,webrtc中不使用​a=rtcp:9 IN IP4 0.0.0.0​//ice协商过程中的安全验证信息​a=ice-ufrag:ubhd​a=ice-pwd:l82NnsGm5i7pucQRchNdjA6B​//支持trickle,即sdp里面只描述媒体信息, ice候选项的信息另行通知​a=ice-options:trickle​//dtls协商过程中需要的认证信息​a=fingerprint:sha-256 CA:83:D0:0F:3B:27:4C:8F:F4:DB:34:58:AC:A6:5D:36:01:07:9F:2B:1D:95:29:AD:0C:F8:08:68:34:D8:62:A7​a=setup:active​//前面BUNDLE行中用到的媒体标识​a=mid:audio​//指出要在rtp头部中加入音量信息​a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level​//当前客户端只接受数据,不发送数据,recvonly,sendonly,inactive,sendrecv​a=recvonly​//rtp,rtcp包使用同一个端口来传输​a=rtcp-mux​//下面都是对m=audio这一行的媒体编码补充说明,指出了编码采用的编号,采样率,声道等​a=rtpmap:111 opus/48000/2​a=rtcp-fb:111 transport-cc​//对opus编码可选的补充说明,minptime代表最小打包时长是10ms,useinbandfec=1代表使用opus编码内置fec特性​a=fmtp:111 minptime=10;useinbandfec=1​//下面就是对Data Channel的描述,基本和上面的audio描述类似,使用DTLS加密,使用SCTP传输​m=application 9 DTLS/SCTP 5000​c=IN IP4 0.0.0.0​//可以是CT或AS,CT方式是设置整个会议的带宽,AS是设置单个会话的带宽。缺省带宽是千比特每秒​b=AS:30​a=ice-ufrag:ubhd​a=ice-pwd:l82NnsGm5i7pucQRchNdjA6B​a=ice-options:trickle​a=fingerprint:sha-256 CA:83:D0:0F:3B:27:4C:8F:F4:DB:34:58:AC:A6:5D:36:01:07:9F:2B:1D:95:29:AD:0C:F8:08:68:34:D8:62:A7​a=setup:active​//前面BUNDLE行中用到的媒体标识​a=mid:data​//使用端口5000,一个消息的大小是1024比特​a=sctpmap:5000 webrtc-datachannel 1024

好吧了解完这些还是没解决,于是我提了工单,额

~让我升级 SDK 说 chrome 升级优化了协议,SDK 有配套优化更新。fine

~

问题解决。很开心这次体验,虽然 Demo 写的很简单还借鉴了融云的 Demo ,不过本身就是为了学习 WebRTC 东西。整个历程还是收获匪浅的。

梳理了下融云整体的 SDK 结构大体分了两大概念。

  1. 房间的概念

  2. 资源流的概念

房间是一个抽象概念,目的是加入房间,然后再使用 PeerConnection 建立连接进行通话。所以房间模型中提供了加入,离开获取房间内信息等接口

资源流主要是指媒体流,用到的是 WebRTC 的 navigator.mediaDevices.getUserMedia 来获取视频流,在通过建立的 PeerConnection 连接,对自己和他人的流进行发布和订阅等操作。具体可以看参考文旦中的 PeerConnection 介绍的连接,本人也是通过此处了解的,不过还不是很透彻还只是了解皮毛。

融云提供的接口还是蛮简洁的,用起来很方便。上几块代码大家可以看下如果感兴趣也可以多了解了解。

截图借鉴的融云官方文档的,没有贴自己的代码,因为我的代码里会有些自己的业务逻辑。

本文纯属个人学习总结,为了了解 WebRTC,也集成了下融云的 SDK !不喜勿喷哦 ~~~ ❤

参考文案:

developer.mozilla.org/en-US/docs/…

baike.baidu.com/item/WebRTC…

融云官网:https://www.rongcloud.cn/

集成文档:https://docs.rongcloud.cn/v2/views/rtc/meeting/intro/ability.html