WebRTC

WebRTC

对抗疫情,让我们来一场酷酷的在线考试

WebRTC徐凤年 发表了文章 • 0 个评论 • 94 次浏览 • 2021-04-15 15:15 • 来自相关话题

随着移动互联网的迅速发展,手机已经成为了中青年人身体的一部分,他们从起床到睡觉前的最后一分钟都不会离开手。最近几个月,受疫情影响,在线学习和在线考试再次成为互联网上的热门话题。那问题来了,在线学习和考试如何保证学生的学习和考试的质量呢?慢慢的各大网络机构出了各... ...查看全部

随着移动互联网的迅速发展,手机已经成为了中青年人身体的一部分,他们从起床到睡觉前的最后一分钟都不会离开手。最近几个月,受疫情影响,在线学习和在线考试再次成为互联网上的热门话题。

那问题来了,在线学习和考试如何保证学生的学习和考试的质量呢?慢慢的各大网络机构出了各种线上教学线上考试的功能,国家也推出来听课不停学的政策。作为一个 web 端的开发还是很好奇音视频这块功能的。选择了融云做音视频的三方,开启了我的探测路程。

功能构想

(1)学生端做直播 ,1 个学生三个视图( 摄像头采集,屏幕共享,手机端采集)通过融云后台转码合图后推到 CDN ; (2)老师同时订阅并播放多个学生的直播画面,也可查看学生端采集视频的截图或前几分钟录像 ; (3)当老师发现某个学生需要警告或答疑时,老师可以进入单个学生所在房间 ,与学生连麦进行实时通讯。

学生端实现

(1)学生的角色我使用的是“主播”;在多机位拍摄时,需要两个设备,一般是一个 pc,一个移动端;两个端登录应用用一个账号,但是加入融云音视频房间时用两个 uid(此处有些小坑调试了很久才弄明白,pc 端创建并加入直播间,进行音视频推流;之后移动端加入相应的房间,也发送音视频流;(可以关闭麦克风 ,看业务场景需求);调试完毕后 可以正常进行考试。

此处参考的是主播流程文档:https://docs.rongcloud.cn/v3/views/rtc/livevideo/guide/quick/anchor/web.html

(2)学生端在 pc 上通过浏览器登录考试系统;

(3)登录后电脑摄像头采集学生正面实时图像,学生还可以发出屏幕共享 ,手机端登录应用加入相同的考场,摆放在学生身后来捕捉考生整体视图;

(4)学生端应用可以调用融云提供的截图接口随时截图,以便给图像识别模块进行是否作弊的检测;

(5)学生端上传的面部头像,全身图像,屏幕共享图像;会在融云服务器上合成一个流。

教师端实现

(1) 老师的角色是“观众”;订阅多个学生输出的图像整体;观众观看参考的接口文档 :https://docs.rongcloud.cn/v3/views/rtc/livevideo/guide/quick/audience/web.html

(2)当老师发现问题时可以查看指定学生直播流的前几分钟回放,需要开通实时录制,录制在 cdn 处。

(3)当需要警告或答疑时,老师可以进入单个学生所在房间,与学生做实时通讯。加入时可以只发音频。老师警告答疑参考文档:https://docs.rongcloud.cn/v3/views/rtc/livevideo/guide/joinManage/join/web.html

录制留存

(1)可以用融云云端录制;每个学生上传的所有视频流可以合图录制,以满足审查人员在考试后检查学生考试全过程有无作弊等情况。融云云端录制 ,可以上传多家对象存储,可以按需求选择音视频格式参考文档 https://docs.rongcloud.cn/v3/views/rtc/record/intro/guide.html

上图

24954647-204042d8c97b3599.png24954647-1f71b7908bfc0131.png

H5 如何实现直播

WebRTC徐凤年 发表了文章 • 0 个评论 • 93 次浏览 • 2021-04-15 15:15 • 来自相关话题

目前直播大火,在看直播后突然想自己做个直播软件。想了想想自己做下,开始在网上各种找资源。直播嘛,那必然有主播端和观众端。经过一系列的考察后后来找到了融云,使用了他们的 SDK,一共用了无 UI IM 和低延时直播两个 SDK。IM 用了连接和发送消息,选择的是... ...查看全部

微信截图_20210415150543.png

目前直播大火,在看直播后突然想自己做个直播软件。想了想想自己做下,开始在网上各种找资源。直播嘛,那必然有主播端和观众端。经过一系列的考察后后来找到了融云,使用了他们的 SDK,一共用了无 UI IM 和低延时直播两个 SDK。

IM 用了连接和发送消息,选择的是融云的聊天室场景。

低延时直播分了主播端和观众端。使用 H5 作为观众端进行观看,使用 web 端作为主播端进行了直播。

功能点介绍

主播端

按照文档的思路,主播端用的 web 界面,使用的 chrome 浏览器。 涉及到的功能点:

  1. 主播分享视频

  2. 查看观众发的消息

  3. 回复消息

观众端

观众端用的 H5 实现,涉及到的功能点:

  1. 观看主播分享的视频

  2. 发消息

  3. 点赞

额,就是为了体验功能做的简单了些,没有弄那些礼物什么的有些麻烦。

实现思路

主播端

  1. 需要先初始化连接 IM,RTC 两个融云的 SDK,此处参考的快速集成 https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/quick/premise/web.html

  2. 加入到房间中 https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/anchorManage/room/web.html#newroom

  3. 发布视频资源供观众查看 https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/anchorManage/resource/web.html#publish

  4. 配置直播 CDN 推流地址 https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/manager/pushcdn/web.html

  5. 完成

此处仅给了我认为关键的几个接口,如果大家感兴趣可以自己细看下文档。有些高级的接口这边没有测试,不过看介绍可以设置直播视频的样式。感兴趣的小伙伴按照文档自行研究下吧。

观众端

观众端就很简单了,H5 的观众端仅需要订阅 CDN 推流的地址就可以看到主播的视频流,很方便。

总结

整体做下来大概零零散散用了两三天,UI 也没怎么最求在网上找了个大致的样式做了下。不过整体还好最起码基本的功能实现了。也算是自己做的第一个直播的小 Demo,还是很欣喜的。喜欢的大家可以体验下。


成为主播的必备神器

WebRTC徐凤年 发表了文章 • 0 个评论 • 82 次浏览 • 2021-04-15 15:15 • 来自相关话题

前言本人是一个游戏爱好者,经常会在斗鱼或者虎牙看游戏主播的精彩操作,特别是近几年直播的火速崛起,各个平台都打着人人都可以成为主播的口号来获取直播流量,所以我就在想直播门槛这么低的吗!这个疑问直到我看到 融云的低延迟直播 SDK 才打消了。那... ...查看全部

前言

本人是一个游戏爱好者,经常会在斗鱼或者虎牙看游戏主播的精彩操作,特别是近几年直播的火速崛起,各个平台都打着人人都可以成为主播的口号来获取直播流量,所以我就在想直播门槛这么低的吗!这个疑问直到我看到 融云的低延迟直播 SDK 才打消了。

微信截图_20210415150703.png

那么这个低延迟直播 SDK 是什么呢?

工欲善其事,必先利其器!那么这个低延迟直播就是成为主播之路的神器。下面是介绍:

低延迟直播 SDK 可以满足 1 个或多个主播与百万观众实时互动,避免延迟带来的距离感,增加用户活跃,支持主播推流,观众拉流,连麦互动等功能,为方便开发者集成降低集成难度,直播场景和会议场景都用 RongRTCLib SDK ,可在 SDK 调用时用参数加以区分集成场景

也就是说通过集成 低延迟直播 SDK 我们可以自己实现一个主播平台,集成的方式也非常简单,快速集成分三个步骤:

1、首先您需要了解集成的前置条件https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/quick/premise/web.html

2、完成前置条件后,开始实现主播端发布音视频流的操作:https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/quick/anchor/web.html

3、有了主播后,咋们也不能忘记观众端,观众端就比较简单了,只需要订阅主播端发布成功的音视频资源就可以了:https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/quick/audience/web.html

完成上面三个步骤后,您就已经初步集成完 低延迟直播 SDK 了,主播和观众就可以互通了,是不是很简单!如果您觉得集成比较麻烦,OK !还有一个 Web 在线集成体验的示例,体验完后还可以直接拿到 demo ,跳转地址:https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/demo/web.html

如果您还想进阶更高级一点的,需要好好研究一下文档当中的其他功能,比如:

发布文件资源:Web 可以通过拿到本地音频、视频文件资源,进行发布。代码示例:

// 通过 video 标签播放本地音视频资源。
let videoNode = document.querySelector('#target');
let mediaStream = videoNode.captureStream();
let user = {
  id: '请填写用户 ID',
  stream: {    
    tag: 'custom',
    type: StreamType.AUDIO_AND_VIDEO,
    mediaStream: mediaStream
  }
};
stream.publish(user).then(() => {
  console.log('发布成功');
}, error => {
  console.log(error);
});

发布屏幕共享资源:Web 可以通过 stream.get 方法获取屏幕媒体流。 仅支持 Chrome 获取屏幕共享资源。代码示例:

var config = {
  height:480,
  width:640,
  frameRate:15,
  screen: true,
  desktopStreamId: 'desktopStreamId',
}

stream.get(config).then(function ({ mediaStream }) {
  let user = {
    id: '请填写用户 ID',
    stream: {    
      tag: 'screen',
      type: StreamType.AUDIO_AND_VIDEO,
      mediaStream: mediaStream
    }
  }
  stream.publish(user).then(() => {
    console.log('发布成功');
  }, error => {
    console.log(error);
  });
}, error => {
  console.error(error);
});

等等······还有好多扩展功能等您来发现!授人以鱼,不如授人以渔,哈哈哈,我们不仅能自己成为主播,还能创造主播,还等什么呢,赶紧试一下吧


实现类似微信视频聊天的功能

WebRTC赵炳东 发表了文章 • 0 个评论 • 123 次浏览 • 2021-04-15 15:15 • 来自相关话题

前言今年因为疫情的影响,很多线下的项目或者活动都放在了线上,所以集成音视频等相关的话题一直比较火热。 作为一个小码农对微信音视频通话的功能还是比较好奇的,所以空闲的时候就想着自己能不能也实现一个,给朋友一个链接地址然后就可以愉快的视频通话了(小小的满足一下虚荣... ...查看全部

前言

今年因为疫情的影响,很多线下的项目或者活动都放在了线上,所以集成音视频等相关的话题一直比较火热。 作为一个小码农对微信音视频通话的功能还是比较好奇的,所以空闲的时候就想着自己能不能也实现一个,给朋友一个链接地址然后就可以愉快的视频通话了(小小的满足一下虚荣心)

微信截图_20210415151315.png

对于集成音视频纯小白来说,前期准备工作的确不好整,因为对这块没什么概念,对后面需要做什么列不出一个清晰的步骤出来(蓝廋香菇~~~),幸运的是,在网上找相关知识时意外发现了一家做音视频 SDK 的(融云https://www.rongcloud.cn/

为什么推荐他们家呢,主要是他们的开发文档比较适用于像我这样的小白,跟着他们的快速文档无脑实现音视频通话。点这个地址,开启你的音视频之旅吧:https://docs.rongcloud.cn/v4/views/rtc/call/noui/quick/web.html

特别意外的是融云还提供了 Web 端在线集成体验示例,体验完后还能拿到 demo ,附上跳转连接:https://docs.rongcloud.cn/v4/views/rtc/call/noui/demo/web.html

音视频通话介绍 音视频通话 SDK 含呼叫流程,可以实现一对一呼叫、多人呼叫等音视频通话场景,音视频通话 SDK 区别于音视频会议 SDK,音视频通话(呼叫)SDK 不需要双方约定房间号,呼叫流程自动处理房间号,适用于类似微信音视频通话等必须含有呼叫流程的应用场景,由两部分组成 信令通知 和 音视频传输

信令通知:基于 IMLib SDK,例如 A 给 B 发起通话,A 优先会通过 IM 给 B 发送一个通话请求,B 同意后再进入音视频房间进行音视频通信 音视频传输:基于 RongRTCLib SDK,例如 A 给 B 发起通话,信令传输完成后,会适用融云提供的音视频能力进行通信

但是在集成的时候,有几点是需要吐槽的:

1、我给其他人发起通话的时候,直接就触发挂断了返回 "SummaryMessage" 类型消息,咋又看不懂在文档找了半天都没发现 SummaryMessage 的详细描述,只知道是挂断电话返回的消息,最后提交了工单才了解挂断的原因。

Web 端挂断原因 HungupMessage 消息中 reason 字段及 SummaryMessage 消息中 status 字段都为挂断原因

状态码说明状态码说明
1己方取消已发出的通话请求11对方取消已发出的通话请求
2己方拒绝收到的通话请求12对方拒绝收到的通话请求
3己方挂断13对方挂断
4己方忙碌14对方忙碌
5己方未接听15对方未接听
6己方不支持当前引擎16对方不支持当前引擎
7己方网络错误17对方网络错误
8其他设备已处理18CallLib 不可用

原来是对方忙碌导致的接听失败!!!

2、前段时间还能正常通话,升级完 chrome 后就报错了(一脸懵逼 ),报错信息如下: 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:

提供单询问融云的技术人员,才知道是由于 chrome 86 升级了 webRTC 的规范,SDK 在 3.2.6 版本做了相关适配。如果 SDK 使用的不是 3.2.6 版本。需要升级至 3.2.6 版本


超大规模会议技术优化策略 轻松实现 500 人线上流畅沟通

WebRTC梅川酷子 发表了文章 • 0 个评论 • 145 次浏览 • 2021-03-01 16:44 • 来自相关话题

受疫情影响,许多公司已经形成线上办公习惯,尤其是在线音视频会议,已经成为一种常态。对于一些大型企业和组织机构来说,分支机构遍布全国各地,员工异地参会人数众多,大规模音视频会议成为刚需。而当前音视频会议主流产品中,单个会议最多支持 500 人入会进行互动。但是 ... ...查看全部
受疫情影响,许多公司已经形成线上办公习惯,尤其是在线音视频会议,已经成为一种常态。对于一些大型企业和组织机构来说,分支机构遍布全国各地,员工异地参会人数众多,大规模音视频会议成为刚需。而当前音视频会议主流产品中,单个会议最多支持 500 人入会进行互动。


但是 500 人同时线上开会,对于资源消耗比较高。而传统的 WebRTC 架构并不擅长超过 200 人以上的会议场景。在面对超大规模会议室、聊天室、直播等各种复杂场景时,对流进行按需合流,可以降低带宽占用和设备压力;对流进行有选择的订阅分发,有助于扩展各种组合场景。针对 App 具体的应用场景,可以配合订阅分发模式,组合使用 SFU 和 MCU 架构。下来我们将详细分析一下大规模会议的资源优化策略。

1.超大规模会议架构对比


WebRTC 多对多网络架构有 P2P、MCU、SFU 三种。各种网络拓扑的优缺点如下:

1.png

SFU 方式灵活,只要降低带宽就可以实现大规模会议的要求。


2.超大规模会议中存在的挑战


在超过 20 人会议场景下,SFU 及 WebRTC 兼容场景仍然无法很好的解决。如果直接选择参会人之间进行音视频互动,音视频数据完全转发对服务器资源的要求是巨大的,如果会议中有大量人员同时接入,服务端上行流量和下行流量陡增,会对服务器造成巨大压力。


这里我们来对比一下 20 人与 200 人同时参加音视频会议时,对服务端造成压力的差距:
20人
各端流量:
20*(1Mbps+32Kbps)=20.64Mbps
服务端上行流量:
20*(1Mbps+32Kbps)=20.64Mbps
服务端下行流量:
20*(20-1)*(1Mbps+32Kbps)=392.16Mbps
200人
各端流量:
200*(1Mbps+32Kbps)=206.4Mbps
服务端上行流量:
200*(1Mbps+32Kbps)=206.4Mbps
服务端下行流量:
200*(200-1)*(1Mbps+32Kbps)=41.07Gbps

从对比结果中可以看出,服务端下行流量直接上升了一个量级。如果采用视频按需订阅,音频选择出音量最大的几路可以大大降低下行流量。比如每个客户端订阅 4 路视频,服务器只需下发 4 路音量最大的音频,服务端下行流量只需要 200*4*(1Mbps+32Kbps)=800+25.6=825.6Mbps,可以极大缓解服务器压力。
 
若要解决上面的问题,建议通过按需订阅与转发、音频流量两个方面来制定策略,在保证效果的前提下,降低服务端的压力。

3.按需订阅与转发以及音频流量优化策略


3.1 按需订阅与转发


按需订阅与转发的方式有:
支持单独订阅某个人的某路视频或某路音频。
接收端仅订阅正在说话的人的视频,音频全部订阅。
融云 SDK 支持发送端视频编码支持大小流。接收端按需订阅大流或小流。大流的清晰度高,码率高;小流的清晰度低,码率低。这样当接收端想观看清晰视频的时候订阅大流;对清晰度要求不高的时候订阅小流。另外,弱网下自动切换大小流,可以保证视频的流畅性。

3.2 音频流量优化策略

针对音频全部订阅有以下几种优化音频流量的方法。

3.2.1 发送端静音时不发送数据
WebRTC 的音频 codec 如果采用 Opus,可以开启 Opus 的 DTX(Discontinuous Transmission)。SDP 对应的设置为 usedtx=1。但测试中发现流量下降不如预期,因为用户的使用环境多少有点背景音。背景音量很容易超出静音阈值。像 Android/iOS 这种定制开发端可以手动调整静音阈值,而 PC 的 Web 端因为是浏览器,则无法调整静音阈值。

3.2.2 调整音频码率
通过设置客户端上音频码率,降低客户端上行的音频码率。当音频路数跟多的时候,限定每一路的音频码率后,总的音频码率会减少很多。SDP 设置方式 b=AS:码率。下面是摘自 RFC3556 的原文:

The Session Description Protocol includes an optional bandwidth
   attribute with the following syntax:

      b=<modifier>:<bandwidth-value>

   where <modifier> is a single alphanumeric word giving the meaning of
   the bandwidth figure, and where the default units for <bandwidth-
   value> are kilobits per second.  This attribute specifies the
   proposed bandwidth to be used by the session or media.

   A typical use is with the modifier "AS" (for Application Specific
   Maximum) which may be used to specify the total bandwidth for a
   single media stream from one site (source).
3.2.3 服务器下发音量 Top N 路

客户端收到音频流,在音频解码后,默认一般仅混流播放音量最大的 3(WebRTC 中的 kMaximumAmountOfMixedAudioSources 值)路声音。所以避免不必要的音频包的转发可以减少服务流量的。步骤如下:
发送端通过 Audio Level 标识音频能量。
音频包进入 SFU 转发队列,先进入计算队列,定期弹出 Top N 的音频包。
只有有效音频包,会进入到下行分发队列。
 
下面介绍音频如何转发音量最大几路的方法实践。

4. 音频 Top N 选择


4.1 客户端处理

客户端会计算出音量大小,并把值记录在 RTP 包中。所以客户端需要开启 audio-level 的 RTP 扩展, 如下: a=extmap:1urn:ietf:params:rtp-hdrext:ssrc-audio-level 开启这个 RTP 扩展后,WebRTC 客户端机会计算 audio 包的音量大小。这个音量大小计算方法 RFC6464 有明确定义。WebRTC 中的计算方法为 modules/audio_processing/rms_level.cc 的 ComputeRms 方法:

// Calculates the normalized RMS value from a mean square value. The input
// should be the sum of squared samples divided by the number of samples. The
// value will be normalized to full range before computing the RMS, wich is
// returned as a negated dBfs. That is, 0 is full amplitude while 127 is very
// faint.
int ComputeRms(float mean_square) {
  if (mean_square <= kMinLevel * kMaxSquaredLevel) {
    // Very faint; simply return the minimum value.
    return RmsLevel::kMinLevelDb;
  }
  // Normalize by the max level.
  const float mean_square_norm = mean_square / kMaxSquaredLevel;
  RTC_DCHECK_GT(mean_square_norm, kMinLevel);
  // 20log_10(x^0.5) = 10log_10(x)
  const float rms = 10.f * log10(mean_square_norm);
  RTC_DCHECK_LE(rms, 0.f);
  RTC_DCHECK_GT(rms, -RmsLevel::kMinLevelDb);
  // Return the negated value.
  return static_cast<int>(-rms + 0.5f);
}
客户端告诉服务器音频包的音量大小。服务器收到音频包后不用做解码,就能知道从客户端上来的音频包的音量值,为后面的服务器音频包下发策略奠定了基础。


4.2 服务器处理

下面用 Publisher 表示发布者的音频流,Subscriber 表示订阅者的音频流。RtpAudioPacket 表示一个音频包。RtpAudioPacket 里有个 mute 属性,标记这个音频包时是否静音。

在没有音频根据音量大小转发的逻辑前,Publisher 和 Subscriber 的处理关系如下。


2.png

Subscriber1、Subscriber2、Subscriber3 订阅 Publisher1、Publisher2、Publisher3。Publisher 发上来的音频包都会转发给各自的订阅者。


音频根据音量大小转发的逻辑如下:
AudioLevelHandler 表示每个 Publisher 的音频处理单元。AudioLevelHandler 里有两个音频包缓冲队列,计算队列 calculate_queue 和发送队列 send_queue。Publisher 的音频包先进入计算队列 calculate_queue 中。有个定时计算任务 AudioLevelCalculator。AudioLevelCalculator 会每隔一个音频打包时间 ptime 进行一次对所有 Publisher 的计算队列里音频包的 audio_level 均值(因为均值表示这个 Publisher 收到的若干个音频包的音量)做排序计算,选出音量值最大的几路。这几路的音频包 RtpAudioPacket 的 mute 被标记为 false,而其他音频包标记为 true。
排序后,这些音频包会从计算队列里移入到发送队列 send_queue 中。
之后音频包从 send_queue 出队,转发给 Subscriber。Subscriber 中的 MuteHandler 有以下两个作用:
a. 根据 RtpAudioPacket 的 mute 属性,mute 为 true 时,这个音频包直接被吞掉,false 表示转发给订阅者。
b. 因为下发给订阅者的音频包 RTP 序号 SeqNum 不是连续的,需要做连续化处理。

下面图中 Subscriber1、Subscriber2、Subscriber3 订阅 Publisher1、Publisher2、Publisher3。假设 Publisher1 收到的当前音量最大,最终只有它的音频包会转发给 Subscriber1、Subscriber2、Subscriber3。

3.png

4.3 级联的考虑


比如下面的图中,Subscriber4 通过级联服务器连接到当前 MediaServer 上。Publisher1、Publisher2、Publisher3 的音频包都会直接转发级联服务器。由级联服务器负责计算 Top N 音频包的计算下发给 Subscriber4。

5.png

下面是这部逻辑的伪代码:
void Publisher::Process(RtpAudioPacket packet, AudioLevelHandler handler) {
    handler.calculate_queue.enqueue(packet)

    RtpAudioPacket packetSend = handler.send_queue.dequeue();
    for (对当前Publisher的所有Subscriber subscriber) {
        if (subscriber是级联服务器) {
            转发packet
        } else {
            转发packetSend
        }
    }
}
4.4 音频下发策略优化


现实中人的说话是有停顿的。比如停顿前后人声比较大,如果简单的排序下发音频包,客户端会收到连续的非静音包。经测试,这样的体验并不理想,因此需要加入平滑处理。这里 history 为过去若干次的音频是否进入 Top N。音频包是最大的几路中的,加入 history 队列尾部加入 true,转发表示此次声音大而发。否则,加入 history 队列尾部加入 false。因为本次静音,还需判断过去的静音情况,若 history 中有 true 值,转发可表示过去一小段说过话,所以需要转发。若 history 中全为 false, 不转发则表示本次声音不大,过去一小段声音也不大,所以不转。

4.5 其他相关策略

当会议中的人数相对比较的少的时候,音频包为上面所述的正常转发。而当多个 Publisher 的订阅人数超过某个阈值(比如 50),此时 MediaServer 发的音频码率很大,对应客户端也要收相应的音频流量。这时可以走超大会议音频最大几路转发逻辑。而当会议中多个 Publisher 的订阅人数下降到阈值之下,再回归正常的转发逻辑。
经过选取最大几路流的下发方式,音频流量已经大大降低了。而在此基础上实际设置的选取路数做少许冗余,可以多发一些有音量的音频包,提高接收方体验。
当参会者增加时,相应的 MediaServer 也需要动态调度。通过把参会者音视频流打到多个 MediaServer 上,通过级联的方式解决问题,保证每台 MediaServer 服务器上的 CPU、内存、带宽的正常。

5. 总结


以上是基于超大规模会议技术优化进行的策略方面的探索。其主要思想是视频按需订阅,音频降低不必要的流量。其中涉及客户端音量值的上传、服务器端音量选择、级联、优化体验、减少音频流量等多个方面。研发过程中,超大会议需要多测试,才能暴露其中的问题,从而提高最终的会议体验。


RTC vs RTMP,适合的才是最好的!

WebRTC赵炳东 发表了文章 • 0 个评论 • 262 次浏览 • 2021-01-29 16:17 • 来自相关话题

随着在线教育、电商直播、泛娱乐社交等 App 的普及,实时音视频技术的应用需求也越来越多元化。目前,市场中能够支持音视频通信的主流技术有“RTMP+CDN”和“RTC”两大阵营。选型时,开发者如何根据场景选择更适合自己的通信技术?这就要从两者的技术特点、价格、... ...查看全部

随着在线教育、电商直播、泛娱乐社交等 App 的普及,实时音视频技术的应用需求也越来越多元化。目前,市场中能够支持音视频通信的主流技术有“RTMP+CDN”和“RTC”两大阵营。选型时,开发者如何根据场景选择更适合自己的通信技术?这就要从两者的技术特点、价格、厂商服务综合考虑。1.png

RTMP+CDN 技术特点与适用场景

RTMP (Real Time Messaging Protocol)基于 TCP 的流媒体传输协议,最大的特点是与 CDN 的强绑定,需要借助 CDN 的负载均衡系统将内容推送到接近用户的边缘节点,使用户就近取得所需内容,提高用户访问的响应速度和成功率,解决因分布、带宽、服务器性能带来的访问延迟问题。更多适用于站点加速、点播、短视频等场景。

对于初次通过 CDN 服务来实现音视频通信的开发者来说,技术指标应主要关注延时、卡顿率、下载速度、打开速度、回源率、宽带冗余提升率等几个维度。

有研究表明,在 0.1s 以下的延迟,用户几乎是无感知的;1s 左右的延迟,用户会明显注意到延时的发生,但在该时间内思维依然是连贯的;超过 10s 的延时,用户会失去等待的耐心。在所有关键技术指标中,控制延时是 CDN 最需要提升的。

以直播场景为例,延时主要看 2 个核心指标:首播时间和再缓存时间。首播时间即从打开到看到视频画面的时间,会受域名解析、连接、第一包时间的影响,首播时间控制在 1 秒内算是不错的效果。其次是再缓冲时间,是用户观看视频时的卡顿时间。由于实际服务中视频长度不一,一般会做播放的体验统计,主要监测的是卡顿率。行业内而言,直播首播时间 300ms,卡顿率在 15% 以下算是优质的通信服务。

目前的 CDN,通常有 3-5 秒的延迟,在浏览图片、短视频等内容时用户感知不明显,对于不需要实时强互动的直播,比如体育赛事网络直播、演唱会网络直播、新闻现场直播,延迟是可以接受的,并不会影响用户体验。

2.png

而在线视频会议、在线教育、电商直播、远程医疗会诊这些对互动有非常高要求的场景,RTMP+CDN 的模式与这些场景对于低延时、无卡顿的要求有一定差距。这时,选择 RTC 技术才能更好地满足开发者的需求。

RTC 技术特点与适用场景

说到 RTC(Real Time Communication)实时音视频通信,它最大的特点就是低延时和无卡顿。从功能流程上说,它包含了采集、编码、前后处理、传输、解码、缓冲、渲染等诸多环节,RTC 不是靠“优化”各环节去实现的实时互动,而是依靠推流端实时的传输机制。

3.png

很多实时音视频服务专业厂商使用的就是 WebRTC 标准,这是一种基于浏览器的实时通信的开源解决方案,使用 UDP 私有协议来进行媒体推流,而不需要创建离散的媒体段;并且它是面向无连接的,没有 TCP 连接断开时的挥手确认连接关闭的机制,基于这两点,WebRTC 能够做到毫秒级的低延迟,远远低于基于 RTMP 协议的 CDN 分发的延迟。而且,它直接通过浏览器就可以完成推流和播放,对于开发者接入来说实在太方便。

因此,WebRTC 标准针对有高互动性要求的直播场景尤为适宜。以直播连麦为例,主播端把通信直播流发到观众端,同时也可以把观众端拉上麦,实现主播和观众的互动。使用 WebRTC,内容实时传输,主播和观众可以进行音视频连麦互动,实时沟通,延时一般低至 400ms 以内。

4.png

基于 WebRTC 标准的融云实时音视频服务,拥有超低延迟的优势,同时也支持将 RTC 音视频流合流(MCU)转码为 RTMP,并推流到第三方 CDN 上,保留了标准协议普遍被 CDN 网络支持的好处。目前,融云音视频通话,可做到全球端到端延时小于 400ms,最低延时 66ms;低延时互动直播的直播推流可以做到主播观众间延迟在 300ms 左右,保障端到端之间延迟无感知的实时互动。

CDN vs RTC 选型还需看价格服务综合比

一套实时音视频通信能力的搭建,除了要根据场景选择适合的技术外,还要看价格、服务的综合性价比。通常来说,使用 RTC 技术的成本比 RTMP+CDN 高。因为,从实践来看,UDP 传输比 TCP 传输对资源消耗要多,而且重传、封包、FEC 冗余计算等都会额外增加计算量,在多进程模式下可能还会遇到内存资源的过多消耗,这些都导致开发及使用成本的增加。

开发者选型中,性价比需综合技术特点、适用场景、价格和服务四个方面的全面考量。服务在产品上线前后的开发阶段和运营阶段,都要发挥重要作用。目前,开发者服务做得比较好的厂商比如融云,会与开发者共建开发文档,技术手册短视频化,提供场景化的 Demo,以及在官网搭建开发者专区,帮助开发者更便捷、更快速的理解 SDK。

融云全新升级的实时音视频服务,提出“以一套 SDK 解决所有通信场景”,使用融云 RTC 的开发者,同时可以用融云 IM 作为信令通道,而不用自己重新搭建或选择第三方信令通道,这样可以大大提升开发效率,减少 SDK 文档学习时间。

总体而言,RTC 低延迟直播是未来发展的趋势,而 RTMP 在当前依然拥有价格上的优势,而两者作为音视频领域的实用技术,无论是适用场景、还是贴近开发的服务都越来越多样化,开发者未来选型之路也将更顺畅。



【融云分析】WebRTC如何通过STUN、ICE协议实现P2P连接

WebRTC赵炳东 发表了文章 • 0 个评论 • 302 次浏览 • 2021-01-21 11:04 • 来自相关话题

WebRTC中两个或多个主机进行P2P连接是通过STUN、TURN、ICE等技术实现的。主机往往都是在NAT之后,且不同的NAT导致外部主机向内网主机发送数据的可见性不同。 内网主机通过STUN协议可以获得NAT分配的外部地址。ICE是主机之间发现P2P传输路... ...查看全部

WebRTC中两个或多个主机进行P2P连接是通过STUN、TURN、ICE等技术实现的。主机往往都是在NAT之后,且不同的NAT导致外部主机向内网主机发送数据的可见性不同。 内网主机通过STUN协议可以获得NAT分配的外部地址。ICE是主机之间发现P2P传输路径机制,ICE中使用了STUN协议进行连通检测、传输路径的指定和保活。 本文将对STUN和ICE协议进行分析和解读,希望能为开发者们带来一些启发和帮助

1. NAT类型

网络地址转换, 简称NAT,节省了IPv4地址空间的使用并且隔离了内网和外网。NAT对待UDP的实现方式有4种,分别如下:

1.1完全圆锥型

一个内网地址(iAddr:iPort)被映射到一个外网地址 (eAddr:ePort)。这个内网(iAddr:iPort)地址发送的数据包都会通过这个外网地址(eAddr:ePort)。外部主机可以通过这个外网地址(eAddr:ePort)向这个内网地址(iAddr:iPort)发送数据包

1.png

1.2地址受限锥型

一个内网地址(iAddr:iPort)被映射到一个外网地址 (eAddr:ePort)。这个内网(iAddr:iPort)地址发送的数据包都会通过这个外网地址(eAddr:ePort)。外部主机 (hAddr:any) 只有接收过从内网(iAddr:iPort)发送来的数据包后,才能通过外部地址 (eAddr:ePort)发送数据包给内网地址(iAddr:iPort)。其中外部主机的端口可以是任意的。

2.png

1.3端口受限锥型

一个内网地址(iAddr:iPort)被映射到一个外网地址 (eAddr:ePort)。这个内网(iAddr:iPort)地址发送的数据包都会通过这个外网地址(eAddr:ePort)。外部主机 (hAddr:hPort) 只有接收过从内网(iAddr:iPort)发送来的数据包后,才能通过外部地址 (eAddr:ePort)发送数据包给内网地址(iAddr:iPort)。其中外部主机的端口hPort是受限的。

3.png

1.4对称型

一个内网地址(iAddr:iPort)向外网地址 (sAddr1:sPort1)发送的多次请求时,NAT会分配同一个外网地址(eAddr1:ePort1)。若向不同的外网地址如(sAddr2:sPort2)发送数据包时,NAT分配另外一个外网地址(eAddr2:ePort2)。外网地址 (sAddr1:sPort1)只有接收过从内网(iAddr:iPort)发送来的数据后,才能通过已经在NAT上开辟的(eAddr1:ePort1)发送数据包给内网.

4.png

2. STUN简介

STUN是Session Traversal Utilities for NAT简写,RFC5389规定了具体内容。STUN协议是用来获取内网地址对应在NAT上的外网地址,NAT穿越。 STUN是C/S模式的协议,由客户端发送STUN请求;STUN服务响应,告知由NAT分配给主机的IP地址和端口号。

2.1 STUN消息结构

STUN消息头为20字节,后面紧跟0或多个属性。STUN头部包含一STUN消息类型、magic cookie、事务ID和消息长度。 

5.png

(图)STUN消息结构

每个STUN消息的最高位前2位必须为0。当多个协议复用同一个端口的时候,这个可以用于与其他协议区分STUN数据包。 消息类型确定消息的类别(如请求、成功回应、失败回应、指示indication)。虽然这里有四种消息类型,但可以分为2类事务:请求/响应事务、指示事务。

magic cookie为固定值0x2112A442。

Transaction ID标识同一个事务的请求和响应。当客户端发送多个STUN请求,通过Transaction ID识别对应的STUN响应。

2.2 STUN消息类型

6.png

(图)STUN消息类型

C0和C1位置的bit指明了消息的分类。其余的12位置标示不同的请求类型,比如绑定请求。

2.3 STUN属性

STUN头之后是0或多个属性。每个属性都采用TLV编码,type为16位的类型、lenght为16位的长度、value为属性值。每个STUN属性必须是4字节对齐。

7.png

(图)STUN属性

STUN属性格式

STUN服务器请求和响应都包含消息属性。一些属性不是强制性的,其中一些只能出现在绑定请求中,而其他一些只能出现在绑定响应中。  属性空间被划分为2个范围。强制理解属性STUN代理必须处理,否则STUN代理将无法正常处理该属性的消息;STUN代理不能理解可选理解属性的话,这些属性可以被忽略。

强制理解属性 (0x0000-0x7FFF):

8.png

 可选理解属性 (0x8000-0xFFFF)

9.png

具体说明如下: MAPPED-ADDRESS属性标识了NAT映射后的地址。

XOR-MAPPED-ADDRESS属性与MAPPED-ADDRESS属性一致,映射后的地址要做异或处理。

USERNAME属性用于消息完整性。用户名和密码包含在消息完整性中。

MESSAGE-INTEGRITY属性是STUN消息的HMAC-SHA1值,长度20字节。MESSAGE-INTEGRITY属性可以出现在任何类型的STUN消息中。用作HMAC输入的文本是STUN消息,包括头部,直到且包括MESSAGE-INTEGRITY属性前面的属性。FINGERPRINT属性出现MESSAGE-INTEGRITY后。所以FINGERPRINT属性外,STUN代理忽略其他出现在MESSAGE-INTEGRITY属性后的任何属性。

FINGERPRINT属性可以出现在所有的STUN消息中,该属性用于区分STUN数据包与其他协议的包。属性的值为采用CRC32方式计算STUN消息直到但不包括FINGERPRINT属性的的结果,并与32位的值0x5354554e异或。

ERROR-CODE属性被用于错误响应消息中。它包含一个在300至699范围内的错误响应号。

REALM属性出现在请求中,表示认证时要用长期资格。出现在响应中,表示服务器希望客户端使用长期资格进行认证。

NONCE属性是出现在请求和响应消息中的一段字符串。

UNKNOWN-ATTRIBUTES属性出现在错误代码为420的的错误响应,表示服务器端无法理解的属性。

SOFTWARE属性用于代理发送消息时所使用的软件的描述。

ALTERNATE-SERVER属性表示STUN客户可以尝试的不同的STUN服务器地址。属性格式与MAPPED-ADDRESS相同。

2.4 STUN示例

下面是Wireshark抓取的一对STUN绑定请求和响应。STUN绑定请求,源地址192.168.2.36:47798,目标地址180.76.137.157:30001。

10.png

STUN绑定响应,源地址180.76.137.157:30001,目标地址192.168.2.36:47798

11.png

其中ICE-CONTROLLING、PRIORITY属性是下面提到的ICE中扩充的属性。

3. ICE简介

ICE两端并不知道所处的网络的位置和NAT类型,通过ICE能够动态的发现最优的传输路径。如下图L和R是ICE代理,下面简称L和R。L和R有各自的传输地址,包括主机的网卡地址、NAT上的外网地址、 TURN服务地址。ICE就是要从这些地址中,找到L和R的候选地址对,实现两端高效连通。

12.png

(图)ICE部署图举例

ICE两端可以通过信令服务器交换SDP信息。ICE使用STUN,TURN等协议来建立会话。

3.1收集候选地址

ICE端收集本地地址。通过STUN服务收集NAT外网地址;通过TURN收集中继地址。

所以有四种候选地址:

13.png

如下图: 主机候选X:x 服务器反射候选X1':x1' 中继候选Y:y 这里称主机候选地址是服务器候选地址的BASE。

14.png

(图)ICE端口

3.2连通检测

L收集了所有的候选地址后,按优先级从高到低排序,通过信令服务器发送SDP offer给R。R收到offer后,收集获选地址,并将自己候选地址放入SDP answer发送给L。此时两端都有了对端的和本端的候选地址。然后配对,生成candidate pair。为了确保candidate pair的有效性,两端都要做连通检测。根据candidate pair,从本地candidate发送STUN请求到远端candidate;接收端返回STUN响应给发送端。如下图。

15.png

(图)ICE基本连通检测

两端都按照各自checklist分别进行检查。

当R收到L的检测时,R发送向L的检测被称为Triggered检测。

3.3 Candidates pair排序

将连通性检查成功的candidate pair按优先级排序加入check list。两端定期遍历这个check list, 发送STUN请求给对端称为Ordinary检测。优先级的计算根据以下原则: 每端给自己的candidate一个优先级数值。本端优先级和远端优先级结合,得到candidate pair的优先级优先级。

公式 priority = (2^24)*(type preference) + (2^8)*(local preference) + (2^0)*(256 - component ID)

16.png

再根据candidate的优先级计算candidate pair的优先级。

priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0)

G:controlling candidate 优先级 D:controlled candidate 优先级

3.4提名Candidates

ICE中有两种角色, controlling角色可以选取最终的candidate pair;controlled角色会等待controlling角色选取的candidate pair。 ICE指定一个ICE代理为controlling角色,其他ICE代理为controlled角色。ICE优先检测优先级高的candidate pair。

Controlling角色有两中提名方案:REGULAR提名:当得到至少一对有效的pair的时候,Controlling角色就会选择其中的一个pair作为候选,此次连通检测发送一个带flag的请求,告诉对端这个就是被选中的pair。

17.png

(图)REGULAR提名

AGGRESSIVE提名:Controlling角色会在每个STUN请求之中添加flag标志,最先成功的那个被选为媒体传输通道。

18.png

(图)AGGRESSIVE提名

3.5 ICE示例

下面是例子中,L和R都是full模式ICE代理,采用aggressive提名,传输媒体为RTP。full模式为双方都要进行连通性检查,都要的走一遍流程;lite模式为,full模式ICE一方进行连通性检查,lite一方只需回应response消息。

19.png

(图)ICE举例

便于理解,采用"主机类型-网络类型-序号"的格式表示传输的地址。地址有两个分量,分别是IP和PORT。L,R,STUN,NAT代表不同的主机类型;PUB代表外网,PRV代表内网; L处在内网中,内网地址是10.0.1.1,R处在外网,外网地址是192.0.2.1。L和R都配置了STUN服务,地址是192.0.2.2,端口是3478。L在NAT后面,NAT外网地址是192.0.2.3。序号表示不同的媒体类型,这里只有RTP所以序号为1。 "S="表示STUN消息的发送地址、"D=" 表示STUN消息的接收地址。 "MA=" 表示STUN绑定响应的中mapped address。"USE-CAND" 表示带有"USE-CANDIDATE" STUN消息。

L收集本地候选地址,并发起STUN绑定请求给STUN服务器,L得到 NAT-PUB-1作为服务器反射候选地址。 L计算候选的优先级,主机候选地址type preference为126;服务器反射候选地址type preference为100。local preference为65535。component ID为1 套用公式priority = (2^24)*(type preference) + (2^8)*(local preference) + (2^0)*(256 - component ID) 得主机候选地址的优先级为2130706431,服务器反射候选地址的优先级为1694498815。 L设置主机候选地址的foundation为1,服务器反射候选地址foundation为2。  L将服务器反射候选地址作为default候选地址。对应的offer sdp为

20.png

替换地址后

21.png

因为L和R都采用的是full-mode,这种情况下ICE协议规定发送offer为controlling端,L为controlling端。 L和R生成candidate pair,两端都有2个candidate pair。L会裁减掉包含服务映射候选地址,保留candidate pair为本端$L_PRIV_1、远端$R_PUB_1

22.png

消息9表示R做连通检测,因为R是controlled角色,所以无需设置USE-CANDIDATE。L处于NAT后面,且没有向R发送过请求,所以此次连通检测会失败。

当L收到answer sdp后,开始连通检测(消息10-13)。L采用的是aggressive提名,所以每个请求都会有USE-CANDIDATE。L使用candidate pair为$L_PRIV_1/$R_PUB_1发起的连通检测成功后,L创建一个新的candidate pair,本端为NAT-PUB-1(消息13中得到) 、远端为R-PUB-1(消息10中得到),加入valid list中。这个连通检测中设置了USE-CANDIDA属性,该candidate pair为选中的候选。L的RTP流在valid list中有选中的candidate pair,所以L进入完成状态。

R收到L的STUN绑定请求(消息11)后,R发起消息11对应的Triggered检测,其candidate pair的本端为R-PUB-1、远端为NAT-PUB-1。检测成功后,R创建本端为R-PUB-1、远端为NAT-PUB-1的candidate pair,加入valid list。因为消息11中包含了USE-CANDIDATE,所以这个candidate pair就被选中为这个RTP流的传输通道。R进入完成状态。

4. 总结

本文介绍了NAT、STUN、ICE等基本概念。STUN部分介绍了STUN的消息结构、消息类型和消息属性ICE协议中STUN消息要遵循STUN协议。 ICE部分介绍了ICE代理之间是如何根据各自的网络地址建立连接的步骤有收集候选地址、连通检测、Candidates pair生成与排序、提名Candidates。 详细内容还需查看ICE协议rfc5245以及webrtc的p2p部分的具体实现。


万人群聊的消息分发控速方案

IM即时通讯徐凤年 发表了文章 • 0 个评论 • 186 次浏览 • 2021-01-21 11:04 • 来自相关话题

当前阶段,群聊已经成为主流IM软件的基本功能,不管是亲属群,朋友群亦或是工作群,都是非常常见的场景。随着移动互联网的发展,即时通讯服务被广泛应用到各个行业,客户业务快速发展,传统百人甚至千人上限的群聊已经无法满足很多业务发展需求,所以超大群的业务应运而生。&n... ...查看全部

当前阶段,群聊已经成为主流IM软件的基本功能,不管是亲属群,朋友群亦或是工作群,都是非常常见的场景。随着移动互联网的发展,即时通讯服务被广泛应用到各个行业,客户业务快速发展,传统百人甚至千人上限的群聊已经无法满足很多业务发展需求,所以超大群的业务应运而生。

 

1超大群面临的挑战

我们以一个万人群的模型进行举例:

1、如果群中有人发了消息,那么这条消息需要按照1:9999的比例进行分发投递,如果我们按照常规消息的处理流程,那么消息处理服务压力巨大。

2、消息量大的情况下,服务端向客户端直推消息的处理速度将会成为系统瓶颈,而一旦用户的消息下发队列造成了挤压,会影响到正常的消息分发,也会导致服务缓存使用量激增。

3、在微服务架构中,服务以及存储(DB,缓存)之间的QPS和网络流量也会急剧增高。

4、以群为单位的消息缓存,内存和存储开销较大(消息体的存储被放大了万倍)。

基于这些挑战,我们的服务势必要做一定的优化来应对。

 

2群消息分发模型

整体的群聊服务架构如下图所示:

1.png

   用户在群里发了一条群消息后,消息先到群组服务,然后通过群组服务缓存的群关系,锁定这条消息最终需要分发的目标用户,然后根据一定的策略分发到消息服务上,消息服务再根据用户的在线状态和消息状态来判断这条消息是直推、通知拉取还是转Push,最终投递给目标用户。

 

3超大群消息分发解决方案

3.1分发控速:

第一,首先我们会根据服务器的核数来建立多个群消息分发队列,这些队列我们设置了不同的休眠时间以及不同的消费线程数,这里可以理解为快、中、慢等队列。如下图所示:

2.png

第二,我们根据群成员数量的大小来将所有群映射到相应的队列中,规则是小群映射到快队列中,大群映射到相应的慢队列中。

第三,小群由于人数少,对服务的影响很小,所以服务利用快队列快速的将群消息分发出去,而大群群消息则利用慢队列的相对高延时来起到控速的作用。

3.2 合并分发:

一条群消息发送到IM服务器后,需要从群组服务投递给消息服务,如果每一个群成员都投递一次,并且投递的群消息内容是一致的话,那肯定会造成相应的资源浪费和服务压力。

服务落点计算中我们使用的是一致性哈希,群成员落点相对固定,所以落点一致的群成员我们可以合并成一次请求进行投递,这样就大幅提高了投递效率同时减少了服务的压力。

3.3 超大规模群的处理方案

在实际群聊业务中,还有一种业务场景是超大规模群,这种群的群人数达到了数十万甚至上百万,这种群如果按照上述的分发方案,势必也会造成消息节点的巨大压力。比如我们有一个十万人的群,消息节点五台,消息服务处理消息的上限是一秒钟4000条,那每台消息节点大约会分到2万条群消息,这超出了消息节点的处理能力。

所以为了避免上述问题,我们的超大群(群成员上线超过3000,可以根据服务器数量和服务器配置相应做调整)会用特殊的队列来处理群消息的分发,这个特殊的队列一秒钟往后端消息服务投递的消息数是消息服务处理上限的一半(留相应的能力处理其他消息),如果单台消息服务处理的QPS上限是4000,那群组服务一秒往单台消息服务最多投递2000条。

 

结束语

我们后续也会针对群消息进行引用分发,对于大群里发的消息体比较大的消息,我们给群成员只分发和缓存消息的索引,比如MessageID,等群成员真正拉取群消息时再从将消息组装好给客户端分发下去。这样做会节省分发的流量以及存储的空间。

随着互联网的发展,群组业务的模型和压力也在不停地扩展,后续可能还会遇到更多的挑战,届时我们服务器也会通过更优的处理方式来应对。

 

感兴趣的开发者可以扫码下载融云的 IM 即时通讯 Demo 产品:SealTalk,体验融云的群聊、聊天室等通信能力。

3.png

集成融云 Web 音视频通话踩坑之旅

WebRTC苏道 发表了文章 • 0 个评论 • 578 次浏览 • 2020-12-29 16:44 • 来自相关话题

前言最近有个项目需要使用的融云的 CallLib SDK 实现类似微信的视频通话,所以在项目还未正式启动的时候,我已经偷偷的开始进行集成了,以免到时候不熟一顿加班那真的欲哭无泪了,好消息就是我已经使用过融云家的 IMLib SDK 做过即时通讯的功能,所以整个... ...查看全部

前言

最近有个项目需要使用的融云的 CallLib SDK 实现类似微信的视频通话,所以在项目还未正式启动的时候,我已经偷偷的开始进行集成了,以免到时候不熟一顿加班那真的欲哭无泪了,好消息就是我已经使用过融云家的 IMLib SDK 做过即时通讯的功能,所以整个注册流程和开发者后台的使用已经比较熟了,当然,即时不熟也没关系,跟着他们的文档一步一步来,也能很快的就上手了。
融云官网:https://www.rongcloud.cn/

下面是集成的时候碰到的一些需要注意的问题:

1、Web 站点必须为 localhost 或 https
2、必须成功连接 IM 后, 才可进行 CallLib 通话
3、新版谷歌浏览器(86版本)会报错,我集成的 RTC 版本是 3.2.3
4、音视频通话接通不了

综上问题,我会逐一解答,关于具体的集成可以直接参考:https://docs.rongcloud.cn/v4/views/rtc/call/noui/quick/web.html

还有具体的 demo 也可以参考一下 https://github.com/rongcloud-snippets/web-call-quickstart

Web 站点必须为 localhost 或 https:
这个是融云的使用音视频通话的前置条件,本来在本地调试的时候好好的,可是发布到线上的时候就不能用了,最后提交工单询问融云的技术人员上线是否还需要配置什么,最后排查一圈发现生产环境使用的站点是 http(欲哭无泪。。。),童鞋们引以为戒啊!!

必须成功连接 IM 后, 才可进行 CallLib 通话:
直接看代码:

// appKey 可在融云开发者后台获取
const im = RongIMLib.init({ appkey: '<your-appkey>' })
// 添加事件监听器
im.watch({
  // 连接状态监听
  status(evt) {
    console.log('连接状态码:', evt.status);
  },
  // 消息监听
  message(evt) {
    console.log('收到新消息:', evt.message);
  }
})
// CallLib 初始化
var config = {
    timeout: 20000,
    RongIMLib: RongIMLib,
    RongRTC: RongRTC
};
rongCallLib = RongCallLib.init(config);
//token 可从开发者后台获取 或 Server API
const token = ''
im.connect({ token }).then(user => {
  console.log('链接成功, 链接用户 id 为: ', user.id);
}).catch(error => {
  console.log('链接失败: ', error.code, error.msg);
});

新版谷歌浏览器会报错:
由于浏览器更新,导致 SDK 需要升级,升级到最新版本的 RTC SDK 下载地址:https://cdn.ronghub.com/RongRTC-3.2.6.min.js
需要注意,如果使用的 SDK 2.X 也需要升级到 2.5.10 以上

音视频通话接通不了:
这种情况我总结分析了一下几种情况,如下:

代码传参错误或者书写错误
这个好像没什么说的,只能怪自己不仔细吧!跟着文档来呗

结束通话没有调用挂断方法 hungup
用户主动发起挂断,在 rongCallLib.commandWatch 监听中收到 HungupMessage 消息,可以调用 rongCallLib.hungup 来挂断通话,不然下次呼叫时会出现报错,提示对方正忙

如何识别挂断原因
HungupMessage 消息中 reason 字段及 SummaryMessage 消息中 status 字段都为挂断原因,详情地址参考:https://docs.rongcloud.cn/rtc/calllib/web/code/

因为对音视频的集成也刚开始,还在学习当中。后续随着继续深入,也会同步音视频相关的集成问题,方便复习记录也希望能帮到需要的童鞋!!!


融云 CallLib 集成遇到的问题

IM即时通讯苏道 发表了文章 • 0 个评论 • 549 次浏览 • 2020-12-29 16:41 • 来自相关话题

近期选用融云音视频产品实现类似微信的通话功能, 经过几天的调试, 终于完成了基本功能, 以下总结集成中遇到的问题查看文档首先先查看融云的文档, 介绍不是很详细, 如果不参考 Demo, 集成起来还是比较困难但有一个亮点, 文档内就直接能体验融云 CallLib... ...查看全部

近期选用融云音视频产品实现类似微信的通话功能, 经过几天的调试, 终于完成了基本功能, 以下总结集成中遇到的问题

查看文档

首先先查看融云的文档, 介绍不是很详细, 如果不参考 Demo, 集成起来还是比较困难

但有一个亮点, 文档内就直接能体验融云 CallLib 的效果

融云 CallLib 文档: https://docs.rongcloud.cn/v4/views/rtc/call/noui/intro.html

Demo 参考

Demo 找到两个. 代码都很简单, 没有太多业务代码, 参考起来比较友好

文档中的 Demo: https://github.com/rongcloud-snippets/web-call-quickstart

教程中的 Demo: https://github.com/rongcloud/websdk-demo/tree/master/calllib-v3/

教程类 Demo 包含一个完整的启动教程, 可参考: https://tutorials.rongcloud.cn/tutorial/web-calllib-demo#0

遇到的问题

1、未找到错误码的完整解释

在文档中搜索多遍, 都没有找到错误码的列表. 提工单询问后, 得知只有旧文档中有解释. 新文档还正在添加中

旧文档: https://docs.rongcloud.cn/rtc/calllib/web/code/

2、单对单通话, 一方挂断, 另一方必须也调用挂断方法

设计有些不合理. 应该是考虑兼容多人音视频, 希望单人、多人调用方式保持一致

3、Web 多端登录时, 需要额外处理错误码 8

如果同一个用户在 Web1、Web2 同时登录, 如果用户收到音视频呼叫, Web1 接通后, Web2 会自动挂断, 并抛出一个挂断码 8. 此处逻辑需要额外处理, 给客户一个提示


LiveVideoStackCon 深圳站:融云解析 WebRTC 低延迟直播技术

WebRTC融云那些事 发表了文章 • 0 个评论 • 377 次浏览 • 2020-06-16 18:36 • 来自相关话题

“基于 WebRTC 的低延迟直播将会是未来直播行业的主流解决方案!”这是融云联合创始人兼CTO 杨攀在 8 月 LiveVideoStackCon 2019 音视频技术大会北京站上对于未来行业趋势的判断。仅仅 4 个月之后,当大会首次落户有“中国硅谷”之称的... ...查看全部

“基于 WebRTC 的低延迟直播将会是未来直播行业的主流解决方案!”这是融云联合创始人兼CTO 杨攀在 8 月 LiveVideoStackCon 2019 音视频技术大会北京站上对于未来行业趋势的判断。仅仅 4 个月之后,当大会首次落户有“中国硅谷”之称的深圳时,融云的另一位技术专家,首席架构师李淼就“基于 WebRTC 的低延迟直播方案”进行了深入的技术分享。

12 月 13-14 日,LiveVideoStackCon 音视频技术大会在深圳举办,大会聚焦音视频、图像、AI 等技术的最新探索与应用实践,覆盖社交、游戏、直播、智能设备等行业领域,面向开发者分享技术创新与最佳实践。本次大会,聚集了数十名海内外技术专家和上千名开发者围绕前沿技术发展进行探讨。


融云首席架构师李淼
随着我国 5G 正式走向商用,直播行业在获得更多发展机遇的同时,也对直播技术提出了新的挑战。传统直播解决方案如果无法解决技术层面导致的延时问题,那么这一弊病将在 5G 的高速网络环境下被无限放大,这也进一步促使了低延迟音视频直播技术方案的演化。对此,李淼结合 WebRTC 的低延迟特性,在现场展示了融云 WebRTC 直播场景的构建全过程及服务架构设计,并向开发者们分享了技术实践细节,希望通过新技术的应用来解决视频直播的延时问题。

为什么要选用 WebRTC 来做直播?李淼表示,相较于传统的直播解决方案,WebRTC 拥有着不可比拟的三大优势。首先是低延时,让直播用户可以享受低延时的观看体验。目前直播行业中绝大多数产品是基于 RTMP、HLS、HDL 方式构建的,即使在不考虑网络链路的情况下,也会产生秒级的延迟,而 WebRTC 则天生具备低延迟的优势,使用 WebRTC 直播可有效将延迟降低至 200ms 以下。

其次是流量消耗小。基于 UDP 传输的 WebRTC 相比基于 TCP 传输的 RTMP 等协议,由于 UDP 协议内容较 TCP 小,且数据包是基于 NACK 进行传输等特点,对于流量的使用也有明显的降低。对于开发者和直播企业而言,流量消耗大幅削减,成本也因此可以得到有效的控制。

而最重要的优势在于 WebRTC 技术方案可以使主播端与观众端保持一致。当主播端使用  WebRTC 进行推流时,主播端与观众端保持一致,可以减少开发的编码量,对于团队人员的占用和后期对于代码的维护,都能保证最低的资源消耗。

在 LiveVideoStackCon 现场,李淼向开发者讲解了如何通过 WebRTC 完成直播场景构建的全过程,并对于 WebRTC 直播的技术细节一一进行了详细解读。李淼表示,使用 WebRTC 直播方案,MCU 服务器的设计至关重要。一方面 MCU 可以按需进行编解码,另一方面需要以房间号进行聚合,记录每台MCU的状态并按最小资源分配新房间,通过这种设计来减少 WebRTC 直播方案的资源消耗。


WebRTC 直播发布订阅流程
当然,对于很多开发者而言,实际的生产环境中仍面临着如何做到秒开视频、降低 MCU 带宽压力以及避免流量风暴等难题,李淼从 GOP 缓存结构和 GOP 控制策略两个层面进行了分析。以解决首帧卡顿延迟为例,直播数据在客户端与 Media Sever 进行交互之后,通常会对 SPS 和 I 帧进行正常下发,但是在随后的 P 帧或 B 帧的下发阶段,融云会采用 1.2 倍速下发的方式进行,直至所有数据包与 MCU 端推包进程同步,这就将直播延迟降至了最低。

此外,李淼还指出,客户端的设计必须考虑就近接入,且支持多链路选择,数据中心间同源音视频只有一路级联;同时还可以利用 IaaS 层的能力,进行中心间级联链路的优化。遵循这些直播网络设计原则都可以有效地降低直播延迟。

在分享的最后,李淼表示在 5G 时代,直播、短视频等内容传播形态将迎来新一轮技术升级,用户体验将成为行业洗牌的关键,此次将 WebRTC 低延迟直播的设计理念和技术要点与开发者和行业人士们一同分享,希望能够给业界带来一些启发和思考。作为互联网通信云行业的技术领导者,融云也将持续优化实时音视频技术和场景化解决方案,助力音视频直播行业在 5G 时代的创新发展。

对抗疫情,让我们来一场酷酷的在线考试

WebRTC徐凤年 发表了文章 • 0 个评论 • 94 次浏览 • 2021-04-15 15:15 • 来自相关话题

随着移动互联网的迅速发展,手机已经成为了中青年人身体的一部分,他们从起床到睡觉前的最后一分钟都不会离开手。最近几个月,受疫情影响,在线学习和在线考试再次成为互联网上的热门话题。那问题来了,在线学习和考试如何保证学生的学习和考试的质量呢?慢慢的各大网络机构出了各... ...查看全部

随着移动互联网的迅速发展,手机已经成为了中青年人身体的一部分,他们从起床到睡觉前的最后一分钟都不会离开手。最近几个月,受疫情影响,在线学习和在线考试再次成为互联网上的热门话题。

那问题来了,在线学习和考试如何保证学生的学习和考试的质量呢?慢慢的各大网络机构出了各种线上教学线上考试的功能,国家也推出来听课不停学的政策。作为一个 web 端的开发还是很好奇音视频这块功能的。选择了融云做音视频的三方,开启了我的探测路程。

功能构想

(1)学生端做直播 ,1 个学生三个视图( 摄像头采集,屏幕共享,手机端采集)通过融云后台转码合图后推到 CDN ; (2)老师同时订阅并播放多个学生的直播画面,也可查看学生端采集视频的截图或前几分钟录像 ; (3)当老师发现某个学生需要警告或答疑时,老师可以进入单个学生所在房间 ,与学生连麦进行实时通讯。

学生端实现

(1)学生的角色我使用的是“主播”;在多机位拍摄时,需要两个设备,一般是一个 pc,一个移动端;两个端登录应用用一个账号,但是加入融云音视频房间时用两个 uid(此处有些小坑调试了很久才弄明白,pc 端创建并加入直播间,进行音视频推流;之后移动端加入相应的房间,也发送音视频流;(可以关闭麦克风 ,看业务场景需求);调试完毕后 可以正常进行考试。

此处参考的是主播流程文档:https://docs.rongcloud.cn/v3/views/rtc/livevideo/guide/quick/anchor/web.html

(2)学生端在 pc 上通过浏览器登录考试系统;

(3)登录后电脑摄像头采集学生正面实时图像,学生还可以发出屏幕共享 ,手机端登录应用加入相同的考场,摆放在学生身后来捕捉考生整体视图;

(4)学生端应用可以调用融云提供的截图接口随时截图,以便给图像识别模块进行是否作弊的检测;

(5)学生端上传的面部头像,全身图像,屏幕共享图像;会在融云服务器上合成一个流。

教师端实现

(1) 老师的角色是“观众”;订阅多个学生输出的图像整体;观众观看参考的接口文档 :https://docs.rongcloud.cn/v3/views/rtc/livevideo/guide/quick/audience/web.html

(2)当老师发现问题时可以查看指定学生直播流的前几分钟回放,需要开通实时录制,录制在 cdn 处。

(3)当需要警告或答疑时,老师可以进入单个学生所在房间,与学生做实时通讯。加入时可以只发音频。老师警告答疑参考文档:https://docs.rongcloud.cn/v3/views/rtc/livevideo/guide/joinManage/join/web.html

录制留存

(1)可以用融云云端录制;每个学生上传的所有视频流可以合图录制,以满足审查人员在考试后检查学生考试全过程有无作弊等情况。融云云端录制 ,可以上传多家对象存储,可以按需求选择音视频格式参考文档 https://docs.rongcloud.cn/v3/views/rtc/record/intro/guide.html

上图

24954647-204042d8c97b3599.png24954647-1f71b7908bfc0131.png

H5 如何实现直播

WebRTC徐凤年 发表了文章 • 0 个评论 • 93 次浏览 • 2021-04-15 15:15 • 来自相关话题

目前直播大火,在看直播后突然想自己做个直播软件。想了想想自己做下,开始在网上各种找资源。直播嘛,那必然有主播端和观众端。经过一系列的考察后后来找到了融云,使用了他们的 SDK,一共用了无 UI IM 和低延时直播两个 SDK。IM 用了连接和发送消息,选择的是... ...查看全部

微信截图_20210415150543.png

目前直播大火,在看直播后突然想自己做个直播软件。想了想想自己做下,开始在网上各种找资源。直播嘛,那必然有主播端和观众端。经过一系列的考察后后来找到了融云,使用了他们的 SDK,一共用了无 UI IM 和低延时直播两个 SDK。

IM 用了连接和发送消息,选择的是融云的聊天室场景。

低延时直播分了主播端和观众端。使用 H5 作为观众端进行观看,使用 web 端作为主播端进行了直播。

功能点介绍

主播端

按照文档的思路,主播端用的 web 界面,使用的 chrome 浏览器。 涉及到的功能点:

  1. 主播分享视频

  2. 查看观众发的消息

  3. 回复消息

观众端

观众端用的 H5 实现,涉及到的功能点:

  1. 观看主播分享的视频

  2. 发消息

  3. 点赞

额,就是为了体验功能做的简单了些,没有弄那些礼物什么的有些麻烦。

实现思路

主播端

  1. 需要先初始化连接 IM,RTC 两个融云的 SDK,此处参考的快速集成 https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/quick/premise/web.html

  2. 加入到房间中 https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/anchorManage/room/web.html#newroom

  3. 发布视频资源供观众查看 https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/anchorManage/resource/web.html#publish

  4. 配置直播 CDN 推流地址 https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/manager/pushcdn/web.html

  5. 完成

此处仅给了我认为关键的几个接口,如果大家感兴趣可以自己细看下文档。有些高级的接口这边没有测试,不过看介绍可以设置直播视频的样式。感兴趣的小伙伴按照文档自行研究下吧。

观众端

观众端就很简单了,H5 的观众端仅需要订阅 CDN 推流的地址就可以看到主播的视频流,很方便。

总结

整体做下来大概零零散散用了两三天,UI 也没怎么最求在网上找了个大致的样式做了下。不过整体还好最起码基本的功能实现了。也算是自己做的第一个直播的小 Demo,还是很欣喜的。喜欢的大家可以体验下。


成为主播的必备神器

WebRTC徐凤年 发表了文章 • 0 个评论 • 82 次浏览 • 2021-04-15 15:15 • 来自相关话题

前言本人是一个游戏爱好者,经常会在斗鱼或者虎牙看游戏主播的精彩操作,特别是近几年直播的火速崛起,各个平台都打着人人都可以成为主播的口号来获取直播流量,所以我就在想直播门槛这么低的吗!这个疑问直到我看到 融云的低延迟直播 SDK 才打消了。那... ...查看全部

前言

本人是一个游戏爱好者,经常会在斗鱼或者虎牙看游戏主播的精彩操作,特别是近几年直播的火速崛起,各个平台都打着人人都可以成为主播的口号来获取直播流量,所以我就在想直播门槛这么低的吗!这个疑问直到我看到 融云的低延迟直播 SDK 才打消了。

微信截图_20210415150703.png

那么这个低延迟直播 SDK 是什么呢?

工欲善其事,必先利其器!那么这个低延迟直播就是成为主播之路的神器。下面是介绍:

低延迟直播 SDK 可以满足 1 个或多个主播与百万观众实时互动,避免延迟带来的距离感,增加用户活跃,支持主播推流,观众拉流,连麦互动等功能,为方便开发者集成降低集成难度,直播场景和会议场景都用 RongRTCLib SDK ,可在 SDK 调用时用参数加以区分集成场景

也就是说通过集成 低延迟直播 SDK 我们可以自己实现一个主播平台,集成的方式也非常简单,快速集成分三个步骤:

1、首先您需要了解集成的前置条件https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/quick/premise/web.html

2、完成前置条件后,开始实现主播端发布音视频流的操作:https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/quick/anchor/web.html

3、有了主播后,咋们也不能忘记观众端,观众端就比较简单了,只需要订阅主播端发布成功的音视频资源就可以了:https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/quick/audience/web.html

完成上面三个步骤后,您就已经初步集成完 低延迟直播 SDK 了,主播和观众就可以互通了,是不是很简单!如果您觉得集成比较麻烦,OK !还有一个 Web 在线集成体验的示例,体验完后还可以直接拿到 demo ,跳转地址:https://docs.rongcloud.cn/v4/views/rtc/livevideo/guide/demo/web.html

如果您还想进阶更高级一点的,需要好好研究一下文档当中的其他功能,比如:

发布文件资源:Web 可以通过拿到本地音频、视频文件资源,进行发布。代码示例:

// 通过 video 标签播放本地音视频资源。
let videoNode = document.querySelector('#target');
let mediaStream = videoNode.captureStream();
let user = {
  id: '请填写用户 ID',
  stream: {    
    tag: 'custom',
    type: StreamType.AUDIO_AND_VIDEO,
    mediaStream: mediaStream
  }
};
stream.publish(user).then(() => {
  console.log('发布成功');
}, error => {
  console.log(error);
});

发布屏幕共享资源:Web 可以通过 stream.get 方法获取屏幕媒体流。 仅支持 Chrome 获取屏幕共享资源。代码示例:

var config = {
  height:480,
  width:640,
  frameRate:15,
  screen: true,
  desktopStreamId: 'desktopStreamId',
}

stream.get(config).then(function ({ mediaStream }) {
  let user = {
    id: '请填写用户 ID',
    stream: {    
      tag: 'screen',
      type: StreamType.AUDIO_AND_VIDEO,
      mediaStream: mediaStream
    }
  }
  stream.publish(user).then(() => {
    console.log('发布成功');
  }, error => {
    console.log(error);
  });
}, error => {
  console.error(error);
});

等等······还有好多扩展功能等您来发现!授人以鱼,不如授人以渔,哈哈哈,我们不仅能自己成为主播,还能创造主播,还等什么呢,赶紧试一下吧


实现类似微信视频聊天的功能

WebRTC赵炳东 发表了文章 • 0 个评论 • 123 次浏览 • 2021-04-15 15:15 • 来自相关话题

前言今年因为疫情的影响,很多线下的项目或者活动都放在了线上,所以集成音视频等相关的话题一直比较火热。 作为一个小码农对微信音视频通话的功能还是比较好奇的,所以空闲的时候就想着自己能不能也实现一个,给朋友一个链接地址然后就可以愉快的视频通话了(小小的满足一下虚荣... ...查看全部

前言

今年因为疫情的影响,很多线下的项目或者活动都放在了线上,所以集成音视频等相关的话题一直比较火热。 作为一个小码农对微信音视频通话的功能还是比较好奇的,所以空闲的时候就想着自己能不能也实现一个,给朋友一个链接地址然后就可以愉快的视频通话了(小小的满足一下虚荣心)

微信截图_20210415151315.png

对于集成音视频纯小白来说,前期准备工作的确不好整,因为对这块没什么概念,对后面需要做什么列不出一个清晰的步骤出来(蓝廋香菇~~~),幸运的是,在网上找相关知识时意外发现了一家做音视频 SDK 的(融云https://www.rongcloud.cn/

为什么推荐他们家呢,主要是他们的开发文档比较适用于像我这样的小白,跟着他们的快速文档无脑实现音视频通话。点这个地址,开启你的音视频之旅吧:https://docs.rongcloud.cn/v4/views/rtc/call/noui/quick/web.html

特别意外的是融云还提供了 Web 端在线集成体验示例,体验完后还能拿到 demo ,附上跳转连接:https://docs.rongcloud.cn/v4/views/rtc/call/noui/demo/web.html

音视频通话介绍 音视频通话 SDK 含呼叫流程,可以实现一对一呼叫、多人呼叫等音视频通话场景,音视频通话 SDK 区别于音视频会议 SDK,音视频通话(呼叫)SDK 不需要双方约定房间号,呼叫流程自动处理房间号,适用于类似微信音视频通话等必须含有呼叫流程的应用场景,由两部分组成 信令通知 和 音视频传输

信令通知:基于 IMLib SDK,例如 A 给 B 发起通话,A 优先会通过 IM 给 B 发送一个通话请求,B 同意后再进入音视频房间进行音视频通信 音视频传输:基于 RongRTCLib SDK,例如 A 给 B 发起通话,信令传输完成后,会适用融云提供的音视频能力进行通信

但是在集成的时候,有几点是需要吐槽的:

1、我给其他人发起通话的时候,直接就触发挂断了返回 "SummaryMessage" 类型消息,咋又看不懂在文档找了半天都没发现 SummaryMessage 的详细描述,只知道是挂断电话返回的消息,最后提交了工单才了解挂断的原因。

Web 端挂断原因 HungupMessage 消息中 reason 字段及 SummaryMessage 消息中 status 字段都为挂断原因

状态码说明状态码说明
1己方取消已发出的通话请求11对方取消已发出的通话请求
2己方拒绝收到的通话请求12对方拒绝收到的通话请求
3己方挂断13对方挂断
4己方忙碌14对方忙碌
5己方未接听15对方未接听
6己方不支持当前引擎16对方不支持当前引擎
7己方网络错误17对方网络错误
8其他设备已处理18CallLib 不可用

原来是对方忙碌导致的接听失败!!!

2、前段时间还能正常通话,升级完 chrome 后就报错了(一脸懵逼 ),报错信息如下: 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:

提供单询问融云的技术人员,才知道是由于 chrome 86 升级了 webRTC 的规范,SDK 在 3.2.6 版本做了相关适配。如果 SDK 使用的不是 3.2.6 版本。需要升级至 3.2.6 版本


超大规模会议技术优化策略 轻松实现 500 人线上流畅沟通

WebRTC梅川酷子 发表了文章 • 0 个评论 • 145 次浏览 • 2021-03-01 16:44 • 来自相关话题

受疫情影响,许多公司已经形成线上办公习惯,尤其是在线音视频会议,已经成为一种常态。对于一些大型企业和组织机构来说,分支机构遍布全国各地,员工异地参会人数众多,大规模音视频会议成为刚需。而当前音视频会议主流产品中,单个会议最多支持 500 人入会进行互动。但是 ... ...查看全部
受疫情影响,许多公司已经形成线上办公习惯,尤其是在线音视频会议,已经成为一种常态。对于一些大型企业和组织机构来说,分支机构遍布全国各地,员工异地参会人数众多,大规模音视频会议成为刚需。而当前音视频会议主流产品中,单个会议最多支持 500 人入会进行互动。


但是 500 人同时线上开会,对于资源消耗比较高。而传统的 WebRTC 架构并不擅长超过 200 人以上的会议场景。在面对超大规模会议室、聊天室、直播等各种复杂场景时,对流进行按需合流,可以降低带宽占用和设备压力;对流进行有选择的订阅分发,有助于扩展各种组合场景。针对 App 具体的应用场景,可以配合订阅分发模式,组合使用 SFU 和 MCU 架构。下来我们将详细分析一下大规模会议的资源优化策略。

1.超大规模会议架构对比


WebRTC 多对多网络架构有 P2P、MCU、SFU 三种。各种网络拓扑的优缺点如下:

1.png

SFU 方式灵活,只要降低带宽就可以实现大规模会议的要求。


2.超大规模会议中存在的挑战


在超过 20 人会议场景下,SFU 及 WebRTC 兼容场景仍然无法很好的解决。如果直接选择参会人之间进行音视频互动,音视频数据完全转发对服务器资源的要求是巨大的,如果会议中有大量人员同时接入,服务端上行流量和下行流量陡增,会对服务器造成巨大压力。


这里我们来对比一下 20 人与 200 人同时参加音视频会议时,对服务端造成压力的差距:
20人
各端流量:
20*(1Mbps+32Kbps)=20.64Mbps
服务端上行流量:
20*(1Mbps+32Kbps)=20.64Mbps
服务端下行流量:
20*(20-1)*(1Mbps+32Kbps)=392.16Mbps
200人
各端流量:
200*(1Mbps+32Kbps)=206.4Mbps
服务端上行流量:
200*(1Mbps+32Kbps)=206.4Mbps
服务端下行流量:
200*(200-1)*(1Mbps+32Kbps)=41.07Gbps

从对比结果中可以看出,服务端下行流量直接上升了一个量级。如果采用视频按需订阅,音频选择出音量最大的几路可以大大降低下行流量。比如每个客户端订阅 4 路视频,服务器只需下发 4 路音量最大的音频,服务端下行流量只需要 200*4*(1Mbps+32Kbps)=800+25.6=825.6Mbps,可以极大缓解服务器压力。
 
若要解决上面的问题,建议通过按需订阅与转发、音频流量两个方面来制定策略,在保证效果的前提下,降低服务端的压力。

3.按需订阅与转发以及音频流量优化策略


3.1 按需订阅与转发


按需订阅与转发的方式有:
支持单独订阅某个人的某路视频或某路音频。
接收端仅订阅正在说话的人的视频,音频全部订阅。
融云 SDK 支持发送端视频编码支持大小流。接收端按需订阅大流或小流。大流的清晰度高,码率高;小流的清晰度低,码率低。这样当接收端想观看清晰视频的时候订阅大流;对清晰度要求不高的时候订阅小流。另外,弱网下自动切换大小流,可以保证视频的流畅性。

3.2 音频流量优化策略

针对音频全部订阅有以下几种优化音频流量的方法。

3.2.1 发送端静音时不发送数据
WebRTC 的音频 codec 如果采用 Opus,可以开启 Opus 的 DTX(Discontinuous Transmission)。SDP 对应的设置为 usedtx=1。但测试中发现流量下降不如预期,因为用户的使用环境多少有点背景音。背景音量很容易超出静音阈值。像 Android/iOS 这种定制开发端可以手动调整静音阈值,而 PC 的 Web 端因为是浏览器,则无法调整静音阈值。

3.2.2 调整音频码率
通过设置客户端上音频码率,降低客户端上行的音频码率。当音频路数跟多的时候,限定每一路的音频码率后,总的音频码率会减少很多。SDP 设置方式 b=AS:码率。下面是摘自 RFC3556 的原文:

The Session Description Protocol includes an optional bandwidth
   attribute with the following syntax:

      b=<modifier>:<bandwidth-value>

   where <modifier> is a single alphanumeric word giving the meaning of
   the bandwidth figure, and where the default units for <bandwidth-
   value> are kilobits per second.  This attribute specifies the
   proposed bandwidth to be used by the session or media.

   A typical use is with the modifier "AS" (for Application Specific
   Maximum) which may be used to specify the total bandwidth for a
   single media stream from one site (source).
3.2.3 服务器下发音量 Top N 路

客户端收到音频流,在音频解码后,默认一般仅混流播放音量最大的 3(WebRTC 中的 kMaximumAmountOfMixedAudioSources 值)路声音。所以避免不必要的音频包的转发可以减少服务流量的。步骤如下:
发送端通过 Audio Level 标识音频能量。
音频包进入 SFU 转发队列,先进入计算队列,定期弹出 Top N 的音频包。
只有有效音频包,会进入到下行分发队列。
 
下面介绍音频如何转发音量最大几路的方法实践。

4. 音频 Top N 选择


4.1 客户端处理

客户端会计算出音量大小,并把值记录在 RTP 包中。所以客户端需要开启 audio-level 的 RTP 扩展, 如下: a=extmap:1urn:ietf:params:rtp-hdrext:ssrc-audio-level 开启这个 RTP 扩展后,WebRTC 客户端机会计算 audio 包的音量大小。这个音量大小计算方法 RFC6464 有明确定义。WebRTC 中的计算方法为 modules/audio_processing/rms_level.cc 的 ComputeRms 方法:

// Calculates the normalized RMS value from a mean square value. The input
// should be the sum of squared samples divided by the number of samples. The
// value will be normalized to full range before computing the RMS, wich is
// returned as a negated dBfs. That is, 0 is full amplitude while 127 is very
// faint.
int ComputeRms(float mean_square) {
  if (mean_square <= kMinLevel * kMaxSquaredLevel) {
    // Very faint; simply return the minimum value.
    return RmsLevel::kMinLevelDb;
  }
  // Normalize by the max level.
  const float mean_square_norm = mean_square / kMaxSquaredLevel;
  RTC_DCHECK_GT(mean_square_norm, kMinLevel);
  // 20log_10(x^0.5) = 10log_10(x)
  const float rms = 10.f * log10(mean_square_norm);
  RTC_DCHECK_LE(rms, 0.f);
  RTC_DCHECK_GT(rms, -RmsLevel::kMinLevelDb);
  // Return the negated value.
  return static_cast<int>(-rms + 0.5f);
}
客户端告诉服务器音频包的音量大小。服务器收到音频包后不用做解码,就能知道从客户端上来的音频包的音量值,为后面的服务器音频包下发策略奠定了基础。


4.2 服务器处理

下面用 Publisher 表示发布者的音频流,Subscriber 表示订阅者的音频流。RtpAudioPacket 表示一个音频包。RtpAudioPacket 里有个 mute 属性,标记这个音频包时是否静音。

在没有音频根据音量大小转发的逻辑前,Publisher 和 Subscriber 的处理关系如下。


2.png

Subscriber1、Subscriber2、Subscriber3 订阅 Publisher1、Publisher2、Publisher3。Publisher 发上来的音频包都会转发给各自的订阅者。


音频根据音量大小转发的逻辑如下:
AudioLevelHandler 表示每个 Publisher 的音频处理单元。AudioLevelHandler 里有两个音频包缓冲队列,计算队列 calculate_queue 和发送队列 send_queue。Publisher 的音频包先进入计算队列 calculate_queue 中。有个定时计算任务 AudioLevelCalculator。AudioLevelCalculator 会每隔一个音频打包时间 ptime 进行一次对所有 Publisher 的计算队列里音频包的 audio_level 均值(因为均值表示这个 Publisher 收到的若干个音频包的音量)做排序计算,选出音量值最大的几路。这几路的音频包 RtpAudioPacket 的 mute 被标记为 false,而其他音频包标记为 true。
排序后,这些音频包会从计算队列里移入到发送队列 send_queue 中。
之后音频包从 send_queue 出队,转发给 Subscriber。Subscriber 中的 MuteHandler 有以下两个作用:
a. 根据 RtpAudioPacket 的 mute 属性,mute 为 true 时,这个音频包直接被吞掉,false 表示转发给订阅者。
b. 因为下发给订阅者的音频包 RTP 序号 SeqNum 不是连续的,需要做连续化处理。

下面图中 Subscriber1、Subscriber2、Subscriber3 订阅 Publisher1、Publisher2、Publisher3。假设 Publisher1 收到的当前音量最大,最终只有它的音频包会转发给 Subscriber1、Subscriber2、Subscriber3。

3.png

4.3 级联的考虑


比如下面的图中,Subscriber4 通过级联服务器连接到当前 MediaServer 上。Publisher1、Publisher2、Publisher3 的音频包都会直接转发级联服务器。由级联服务器负责计算 Top N 音频包的计算下发给 Subscriber4。

5.png

下面是这部逻辑的伪代码:
void Publisher::Process(RtpAudioPacket packet, AudioLevelHandler handler) {
    handler.calculate_queue.enqueue(packet)

    RtpAudioPacket packetSend = handler.send_queue.dequeue();
    for (对当前Publisher的所有Subscriber subscriber) {
        if (subscriber是级联服务器) {
            转发packet
        } else {
            转发packetSend
        }
    }
}
4.4 音频下发策略优化


现实中人的说话是有停顿的。比如停顿前后人声比较大,如果简单的排序下发音频包,客户端会收到连续的非静音包。经测试,这样的体验并不理想,因此需要加入平滑处理。这里 history 为过去若干次的音频是否进入 Top N。音频包是最大的几路中的,加入 history 队列尾部加入 true,转发表示此次声音大而发。否则,加入 history 队列尾部加入 false。因为本次静音,还需判断过去的静音情况,若 history 中有 true 值,转发可表示过去一小段说过话,所以需要转发。若 history 中全为 false, 不转发则表示本次声音不大,过去一小段声音也不大,所以不转。

4.5 其他相关策略

当会议中的人数相对比较的少的时候,音频包为上面所述的正常转发。而当多个 Publisher 的订阅人数超过某个阈值(比如 50),此时 MediaServer 发的音频码率很大,对应客户端也要收相应的音频流量。这时可以走超大会议音频最大几路转发逻辑。而当会议中多个 Publisher 的订阅人数下降到阈值之下,再回归正常的转发逻辑。
经过选取最大几路流的下发方式,音频流量已经大大降低了。而在此基础上实际设置的选取路数做少许冗余,可以多发一些有音量的音频包,提高接收方体验。
当参会者增加时,相应的 MediaServer 也需要动态调度。通过把参会者音视频流打到多个 MediaServer 上,通过级联的方式解决问题,保证每台 MediaServer 服务器上的 CPU、内存、带宽的正常。

5. 总结


以上是基于超大规模会议技术优化进行的策略方面的探索。其主要思想是视频按需订阅,音频降低不必要的流量。其中涉及客户端音量值的上传、服务器端音量选择、级联、优化体验、减少音频流量等多个方面。研发过程中,超大会议需要多测试,才能暴露其中的问题,从而提高最终的会议体验。


RTC vs RTMP,适合的才是最好的!

WebRTC赵炳东 发表了文章 • 0 个评论 • 262 次浏览 • 2021-01-29 16:17 • 来自相关话题

随着在线教育、电商直播、泛娱乐社交等 App 的普及,实时音视频技术的应用需求也越来越多元化。目前,市场中能够支持音视频通信的主流技术有“RTMP+CDN”和“RTC”两大阵营。选型时,开发者如何根据场景选择更适合自己的通信技术?这就要从两者的技术特点、价格、... ...查看全部

随着在线教育、电商直播、泛娱乐社交等 App 的普及,实时音视频技术的应用需求也越来越多元化。目前,市场中能够支持音视频通信的主流技术有“RTMP+CDN”和“RTC”两大阵营。选型时,开发者如何根据场景选择更适合自己的通信技术?这就要从两者的技术特点、价格、厂商服务综合考虑。1.png

RTMP+CDN 技术特点与适用场景

RTMP (Real Time Messaging Protocol)基于 TCP 的流媒体传输协议,最大的特点是与 CDN 的强绑定,需要借助 CDN 的负载均衡系统将内容推送到接近用户的边缘节点,使用户就近取得所需内容,提高用户访问的响应速度和成功率,解决因分布、带宽、服务器性能带来的访问延迟问题。更多适用于站点加速、点播、短视频等场景。

对于初次通过 CDN 服务来实现音视频通信的开发者来说,技术指标应主要关注延时、卡顿率、下载速度、打开速度、回源率、宽带冗余提升率等几个维度。

有研究表明,在 0.1s 以下的延迟,用户几乎是无感知的;1s 左右的延迟,用户会明显注意到延时的发生,但在该时间内思维依然是连贯的;超过 10s 的延时,用户会失去等待的耐心。在所有关键技术指标中,控制延时是 CDN 最需要提升的。

以直播场景为例,延时主要看 2 个核心指标:首播时间和再缓存时间。首播时间即从打开到看到视频画面的时间,会受域名解析、连接、第一包时间的影响,首播时间控制在 1 秒内算是不错的效果。其次是再缓冲时间,是用户观看视频时的卡顿时间。由于实际服务中视频长度不一,一般会做播放的体验统计,主要监测的是卡顿率。行业内而言,直播首播时间 300ms,卡顿率在 15% 以下算是优质的通信服务。

目前的 CDN,通常有 3-5 秒的延迟,在浏览图片、短视频等内容时用户感知不明显,对于不需要实时强互动的直播,比如体育赛事网络直播、演唱会网络直播、新闻现场直播,延迟是可以接受的,并不会影响用户体验。

2.png

而在线视频会议、在线教育、电商直播、远程医疗会诊这些对互动有非常高要求的场景,RTMP+CDN 的模式与这些场景对于低延时、无卡顿的要求有一定差距。这时,选择 RTC 技术才能更好地满足开发者的需求。

RTC 技术特点与适用场景

说到 RTC(Real Time Communication)实时音视频通信,它最大的特点就是低延时和无卡顿。从功能流程上说,它包含了采集、编码、前后处理、传输、解码、缓冲、渲染等诸多环节,RTC 不是靠“优化”各环节去实现的实时互动,而是依靠推流端实时的传输机制。

3.png

很多实时音视频服务专业厂商使用的就是 WebRTC 标准,这是一种基于浏览器的实时通信的开源解决方案,使用 UDP 私有协议来进行媒体推流,而不需要创建离散的媒体段;并且它是面向无连接的,没有 TCP 连接断开时的挥手确认连接关闭的机制,基于这两点,WebRTC 能够做到毫秒级的低延迟,远远低于基于 RTMP 协议的 CDN 分发的延迟。而且,它直接通过浏览器就可以完成推流和播放,对于开发者接入来说实在太方便。

因此,WebRTC 标准针对有高互动性要求的直播场景尤为适宜。以直播连麦为例,主播端把通信直播流发到观众端,同时也可以把观众端拉上麦,实现主播和观众的互动。使用 WebRTC,内容实时传输,主播和观众可以进行音视频连麦互动,实时沟通,延时一般低至 400ms 以内。

4.png

基于 WebRTC 标准的融云实时音视频服务,拥有超低延迟的优势,同时也支持将 RTC 音视频流合流(MCU)转码为 RTMP,并推流到第三方 CDN 上,保留了标准协议普遍被 CDN 网络支持的好处。目前,融云音视频通话,可做到全球端到端延时小于 400ms,最低延时 66ms;低延时互动直播的直播推流可以做到主播观众间延迟在 300ms 左右,保障端到端之间延迟无感知的实时互动。

CDN vs RTC 选型还需看价格服务综合比

一套实时音视频通信能力的搭建,除了要根据场景选择适合的技术外,还要看价格、服务的综合性价比。通常来说,使用 RTC 技术的成本比 RTMP+CDN 高。因为,从实践来看,UDP 传输比 TCP 传输对资源消耗要多,而且重传、封包、FEC 冗余计算等都会额外增加计算量,在多进程模式下可能还会遇到内存资源的过多消耗,这些都导致开发及使用成本的增加。

开发者选型中,性价比需综合技术特点、适用场景、价格和服务四个方面的全面考量。服务在产品上线前后的开发阶段和运营阶段,都要发挥重要作用。目前,开发者服务做得比较好的厂商比如融云,会与开发者共建开发文档,技术手册短视频化,提供场景化的 Demo,以及在官网搭建开发者专区,帮助开发者更便捷、更快速的理解 SDK。

融云全新升级的实时音视频服务,提出“以一套 SDK 解决所有通信场景”,使用融云 RTC 的开发者,同时可以用融云 IM 作为信令通道,而不用自己重新搭建或选择第三方信令通道,这样可以大大提升开发效率,减少 SDK 文档学习时间。

总体而言,RTC 低延迟直播是未来发展的趋势,而 RTMP 在当前依然拥有价格上的优势,而两者作为音视频领域的实用技术,无论是适用场景、还是贴近开发的服务都越来越多样化,开发者未来选型之路也将更顺畅。



【融云分析】WebRTC如何通过STUN、ICE协议实现P2P连接

WebRTC赵炳东 发表了文章 • 0 个评论 • 302 次浏览 • 2021-01-21 11:04 • 来自相关话题

WebRTC中两个或多个主机进行P2P连接是通过STUN、TURN、ICE等技术实现的。主机往往都是在NAT之后,且不同的NAT导致外部主机向内网主机发送数据的可见性不同。 内网主机通过STUN协议可以获得NAT分配的外部地址。ICE是主机之间发现P2P传输路... ...查看全部

WebRTC中两个或多个主机进行P2P连接是通过STUN、TURN、ICE等技术实现的。主机往往都是在NAT之后,且不同的NAT导致外部主机向内网主机发送数据的可见性不同。 内网主机通过STUN协议可以获得NAT分配的外部地址。ICE是主机之间发现P2P传输路径机制,ICE中使用了STUN协议进行连通检测、传输路径的指定和保活。 本文将对STUN和ICE协议进行分析和解读,希望能为开发者们带来一些启发和帮助

1. NAT类型

网络地址转换, 简称NAT,节省了IPv4地址空间的使用并且隔离了内网和外网。NAT对待UDP的实现方式有4种,分别如下:

1.1完全圆锥型

一个内网地址(iAddr:iPort)被映射到一个外网地址 (eAddr:ePort)。这个内网(iAddr:iPort)地址发送的数据包都会通过这个外网地址(eAddr:ePort)。外部主机可以通过这个外网地址(eAddr:ePort)向这个内网地址(iAddr:iPort)发送数据包

1.png

1.2地址受限锥型

一个内网地址(iAddr:iPort)被映射到一个外网地址 (eAddr:ePort)。这个内网(iAddr:iPort)地址发送的数据包都会通过这个外网地址(eAddr:ePort)。外部主机 (hAddr:any) 只有接收过从内网(iAddr:iPort)发送来的数据包后,才能通过外部地址 (eAddr:ePort)发送数据包给内网地址(iAddr:iPort)。其中外部主机的端口可以是任意的。

2.png

1.3端口受限锥型

一个内网地址(iAddr:iPort)被映射到一个外网地址 (eAddr:ePort)。这个内网(iAddr:iPort)地址发送的数据包都会通过这个外网地址(eAddr:ePort)。外部主机 (hAddr:hPort) 只有接收过从内网(iAddr:iPort)发送来的数据包后,才能通过外部地址 (eAddr:ePort)发送数据包给内网地址(iAddr:iPort)。其中外部主机的端口hPort是受限的。

3.png

1.4对称型

一个内网地址(iAddr:iPort)向外网地址 (sAddr1:sPort1)发送的多次请求时,NAT会分配同一个外网地址(eAddr1:ePort1)。若向不同的外网地址如(sAddr2:sPort2)发送数据包时,NAT分配另外一个外网地址(eAddr2:ePort2)。外网地址 (sAddr1:sPort1)只有接收过从内网(iAddr:iPort)发送来的数据后,才能通过已经在NAT上开辟的(eAddr1:ePort1)发送数据包给内网.

4.png

2. STUN简介

STUN是Session Traversal Utilities for NAT简写,RFC5389规定了具体内容。STUN协议是用来获取内网地址对应在NAT上的外网地址,NAT穿越。 STUN是C/S模式的协议,由客户端发送STUN请求;STUN服务响应,告知由NAT分配给主机的IP地址和端口号。

2.1 STUN消息结构

STUN消息头为20字节,后面紧跟0或多个属性。STUN头部包含一STUN消息类型、magic cookie、事务ID和消息长度。 

5.png

(图)STUN消息结构

每个STUN消息的最高位前2位必须为0。当多个协议复用同一个端口的时候,这个可以用于与其他协议区分STUN数据包。 消息类型确定消息的类别(如请求、成功回应、失败回应、指示indication)。虽然这里有四种消息类型,但可以分为2类事务:请求/响应事务、指示事务。

magic cookie为固定值0x2112A442。

Transaction ID标识同一个事务的请求和响应。当客户端发送多个STUN请求,通过Transaction ID识别对应的STUN响应。

2.2 STUN消息类型

6.png

(图)STUN消息类型

C0和C1位置的bit指明了消息的分类。其余的12位置标示不同的请求类型,比如绑定请求。

2.3 STUN属性

STUN头之后是0或多个属性。每个属性都采用TLV编码,type为16位的类型、lenght为16位的长度、value为属性值。每个STUN属性必须是4字节对齐。

7.png

(图)STUN属性

STUN属性格式

STUN服务器请求和响应都包含消息属性。一些属性不是强制性的,其中一些只能出现在绑定请求中,而其他一些只能出现在绑定响应中。  属性空间被划分为2个范围。强制理解属性STUN代理必须处理,否则STUN代理将无法正常处理该属性的消息;STUN代理不能理解可选理解属性的话,这些属性可以被忽略。

强制理解属性 (0x0000-0x7FFF):

8.png

 可选理解属性 (0x8000-0xFFFF)

9.png

具体说明如下: MAPPED-ADDRESS属性标识了NAT映射后的地址。

XOR-MAPPED-ADDRESS属性与MAPPED-ADDRESS属性一致,映射后的地址要做异或处理。

USERNAME属性用于消息完整性。用户名和密码包含在消息完整性中。

MESSAGE-INTEGRITY属性是STUN消息的HMAC-SHA1值,长度20字节。MESSAGE-INTEGRITY属性可以出现在任何类型的STUN消息中。用作HMAC输入的文本是STUN消息,包括头部,直到且包括MESSAGE-INTEGRITY属性前面的属性。FINGERPRINT属性出现MESSAGE-INTEGRITY后。所以FINGERPRINT属性外,STUN代理忽略其他出现在MESSAGE-INTEGRITY属性后的任何属性。

FINGERPRINT属性可以出现在所有的STUN消息中,该属性用于区分STUN数据包与其他协议的包。属性的值为采用CRC32方式计算STUN消息直到但不包括FINGERPRINT属性的的结果,并与32位的值0x5354554e异或。

ERROR-CODE属性被用于错误响应消息中。它包含一个在300至699范围内的错误响应号。

REALM属性出现在请求中,表示认证时要用长期资格。出现在响应中,表示服务器希望客户端使用长期资格进行认证。

NONCE属性是出现在请求和响应消息中的一段字符串。

UNKNOWN-ATTRIBUTES属性出现在错误代码为420的的错误响应,表示服务器端无法理解的属性。

SOFTWARE属性用于代理发送消息时所使用的软件的描述。

ALTERNATE-SERVER属性表示STUN客户可以尝试的不同的STUN服务器地址。属性格式与MAPPED-ADDRESS相同。

2.4 STUN示例

下面是Wireshark抓取的一对STUN绑定请求和响应。STUN绑定请求,源地址192.168.2.36:47798,目标地址180.76.137.157:30001。

10.png

STUN绑定响应,源地址180.76.137.157:30001,目标地址192.168.2.36:47798

11.png

其中ICE-CONTROLLING、PRIORITY属性是下面提到的ICE中扩充的属性。

3. ICE简介

ICE两端并不知道所处的网络的位置和NAT类型,通过ICE能够动态的发现最优的传输路径。如下图L和R是ICE代理,下面简称L和R。L和R有各自的传输地址,包括主机的网卡地址、NAT上的外网地址、 TURN服务地址。ICE就是要从这些地址中,找到L和R的候选地址对,实现两端高效连通。

12.png

(图)ICE部署图举例

ICE两端可以通过信令服务器交换SDP信息。ICE使用STUN,TURN等协议来建立会话。

3.1收集候选地址

ICE端收集本地地址。通过STUN服务收集NAT外网地址;通过TURN收集中继地址。

所以有四种候选地址:

13.png

如下图: 主机候选X:x 服务器反射候选X1':x1' 中继候选Y:y 这里称主机候选地址是服务器候选地址的BASE。

14.png

(图)ICE端口

3.2连通检测

L收集了所有的候选地址后,按优先级从高到低排序,通过信令服务器发送SDP offer给R。R收到offer后,收集获选地址,并将自己候选地址放入SDP answer发送给L。此时两端都有了对端的和本端的候选地址。然后配对,生成candidate pair。为了确保candidate pair的有效性,两端都要做连通检测。根据candidate pair,从本地candidate发送STUN请求到远端candidate;接收端返回STUN响应给发送端。如下图。

15.png

(图)ICE基本连通检测

两端都按照各自checklist分别进行检查。

当R收到L的检测时,R发送向L的检测被称为Triggered检测。

3.3 Candidates pair排序

将连通性检查成功的candidate pair按优先级排序加入check list。两端定期遍历这个check list, 发送STUN请求给对端称为Ordinary检测。优先级的计算根据以下原则: 每端给自己的candidate一个优先级数值。本端优先级和远端优先级结合,得到candidate pair的优先级优先级。

公式 priority = (2^24)*(type preference) + (2^8)*(local preference) + (2^0)*(256 - component ID)

16.png

再根据candidate的优先级计算candidate pair的优先级。

priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0)

G:controlling candidate 优先级 D:controlled candidate 优先级

3.4提名Candidates

ICE中有两种角色, controlling角色可以选取最终的candidate pair;controlled角色会等待controlling角色选取的candidate pair。 ICE指定一个ICE代理为controlling角色,其他ICE代理为controlled角色。ICE优先检测优先级高的candidate pair。

Controlling角色有两中提名方案:REGULAR提名:当得到至少一对有效的pair的时候,Controlling角色就会选择其中的一个pair作为候选,此次连通检测发送一个带flag的请求,告诉对端这个就是被选中的pair。

17.png

(图)REGULAR提名

AGGRESSIVE提名:Controlling角色会在每个STUN请求之中添加flag标志,最先成功的那个被选为媒体传输通道。

18.png

(图)AGGRESSIVE提名

3.5 ICE示例

下面是例子中,L和R都是full模式ICE代理,采用aggressive提名,传输媒体为RTP。full模式为双方都要进行连通性检查,都要的走一遍流程;lite模式为,full模式ICE一方进行连通性检查,lite一方只需回应response消息。

19.png

(图)ICE举例

便于理解,采用"主机类型-网络类型-序号"的格式表示传输的地址。地址有两个分量,分别是IP和PORT。L,R,STUN,NAT代表不同的主机类型;PUB代表外网,PRV代表内网; L处在内网中,内网地址是10.0.1.1,R处在外网,外网地址是192.0.2.1。L和R都配置了STUN服务,地址是192.0.2.2,端口是3478。L在NAT后面,NAT外网地址是192.0.2.3。序号表示不同的媒体类型,这里只有RTP所以序号为1。 "S="表示STUN消息的发送地址、"D=" 表示STUN消息的接收地址。 "MA=" 表示STUN绑定响应的中mapped address。"USE-CAND" 表示带有"USE-CANDIDATE" STUN消息。

L收集本地候选地址,并发起STUN绑定请求给STUN服务器,L得到 NAT-PUB-1作为服务器反射候选地址。 L计算候选的优先级,主机候选地址type preference为126;服务器反射候选地址type preference为100。local preference为65535。component ID为1 套用公式priority = (2^24)*(type preference) + (2^8)*(local preference) + (2^0)*(256 - component ID) 得主机候选地址的优先级为2130706431,服务器反射候选地址的优先级为1694498815。 L设置主机候选地址的foundation为1,服务器反射候选地址foundation为2。  L将服务器反射候选地址作为default候选地址。对应的offer sdp为

20.png

替换地址后

21.png

因为L和R都采用的是full-mode,这种情况下ICE协议规定发送offer为controlling端,L为controlling端。 L和R生成candidate pair,两端都有2个candidate pair。L会裁减掉包含服务映射候选地址,保留candidate pair为本端$L_PRIV_1、远端$R_PUB_1

22.png

消息9表示R做连通检测,因为R是controlled角色,所以无需设置USE-CANDIDATE。L处于NAT后面,且没有向R发送过请求,所以此次连通检测会失败。

当L收到answer sdp后,开始连通检测(消息10-13)。L采用的是aggressive提名,所以每个请求都会有USE-CANDIDATE。L使用candidate pair为$L_PRIV_1/$R_PUB_1发起的连通检测成功后,L创建一个新的candidate pair,本端为NAT-PUB-1(消息13中得到) 、远端为R-PUB-1(消息10中得到),加入valid list中。这个连通检测中设置了USE-CANDIDA属性,该candidate pair为选中的候选。L的RTP流在valid list中有选中的candidate pair,所以L进入完成状态。

R收到L的STUN绑定请求(消息11)后,R发起消息11对应的Triggered检测,其candidate pair的本端为R-PUB-1、远端为NAT-PUB-1。检测成功后,R创建本端为R-PUB-1、远端为NAT-PUB-1的candidate pair,加入valid list。因为消息11中包含了USE-CANDIDATE,所以这个candidate pair就被选中为这个RTP流的传输通道。R进入完成状态。

4. 总结

本文介绍了NAT、STUN、ICE等基本概念。STUN部分介绍了STUN的消息结构、消息类型和消息属性ICE协议中STUN消息要遵循STUN协议。 ICE部分介绍了ICE代理之间是如何根据各自的网络地址建立连接的步骤有收集候选地址、连通检测、Candidates pair生成与排序、提名Candidates。 详细内容还需查看ICE协议rfc5245以及webrtc的p2p部分的具体实现。


万人群聊的消息分发控速方案

IM即时通讯徐凤年 发表了文章 • 0 个评论 • 186 次浏览 • 2021-01-21 11:04 • 来自相关话题

当前阶段,群聊已经成为主流IM软件的基本功能,不管是亲属群,朋友群亦或是工作群,都是非常常见的场景。随着移动互联网的发展,即时通讯服务被广泛应用到各个行业,客户业务快速发展,传统百人甚至千人上限的群聊已经无法满足很多业务发展需求,所以超大群的业务应运而生。&n... ...查看全部

当前阶段,群聊已经成为主流IM软件的基本功能,不管是亲属群,朋友群亦或是工作群,都是非常常见的场景。随着移动互联网的发展,即时通讯服务被广泛应用到各个行业,客户业务快速发展,传统百人甚至千人上限的群聊已经无法满足很多业务发展需求,所以超大群的业务应运而生。

 

1超大群面临的挑战

我们以一个万人群的模型进行举例:

1、如果群中有人发了消息,那么这条消息需要按照1:9999的比例进行分发投递,如果我们按照常规消息的处理流程,那么消息处理服务压力巨大。

2、消息量大的情况下,服务端向客户端直推消息的处理速度将会成为系统瓶颈,而一旦用户的消息下发队列造成了挤压,会影响到正常的消息分发,也会导致服务缓存使用量激增。

3、在微服务架构中,服务以及存储(DB,缓存)之间的QPS和网络流量也会急剧增高。

4、以群为单位的消息缓存,内存和存储开销较大(消息体的存储被放大了万倍)。

基于这些挑战,我们的服务势必要做一定的优化来应对。

 

2群消息分发模型

整体的群聊服务架构如下图所示:

1.png

   用户在群里发了一条群消息后,消息先到群组服务,然后通过群组服务缓存的群关系,锁定这条消息最终需要分发的目标用户,然后根据一定的策略分发到消息服务上,消息服务再根据用户的在线状态和消息状态来判断这条消息是直推、通知拉取还是转Push,最终投递给目标用户。

 

3超大群消息分发解决方案

3.1分发控速:

第一,首先我们会根据服务器的核数来建立多个群消息分发队列,这些队列我们设置了不同的休眠时间以及不同的消费线程数,这里可以理解为快、中、慢等队列。如下图所示:

2.png

第二,我们根据群成员数量的大小来将所有群映射到相应的队列中,规则是小群映射到快队列中,大群映射到相应的慢队列中。

第三,小群由于人数少,对服务的影响很小,所以服务利用快队列快速的将群消息分发出去,而大群群消息则利用慢队列的相对高延时来起到控速的作用。

3.2 合并分发:

一条群消息发送到IM服务器后,需要从群组服务投递给消息服务,如果每一个群成员都投递一次,并且投递的群消息内容是一致的话,那肯定会造成相应的资源浪费和服务压力。

服务落点计算中我们使用的是一致性哈希,群成员落点相对固定,所以落点一致的群成员我们可以合并成一次请求进行投递,这样就大幅提高了投递效率同时减少了服务的压力。

3.3 超大规模群的处理方案

在实际群聊业务中,还有一种业务场景是超大规模群,这种群的群人数达到了数十万甚至上百万,这种群如果按照上述的分发方案,势必也会造成消息节点的巨大压力。比如我们有一个十万人的群,消息节点五台,消息服务处理消息的上限是一秒钟4000条,那每台消息节点大约会分到2万条群消息,这超出了消息节点的处理能力。

所以为了避免上述问题,我们的超大群(群成员上线超过3000,可以根据服务器数量和服务器配置相应做调整)会用特殊的队列来处理群消息的分发,这个特殊的队列一秒钟往后端消息服务投递的消息数是消息服务处理上限的一半(留相应的能力处理其他消息),如果单台消息服务处理的QPS上限是4000,那群组服务一秒往单台消息服务最多投递2000条。

 

结束语

我们后续也会针对群消息进行引用分发,对于大群里发的消息体比较大的消息,我们给群成员只分发和缓存消息的索引,比如MessageID,等群成员真正拉取群消息时再从将消息组装好给客户端分发下去。这样做会节省分发的流量以及存储的空间。

随着互联网的发展,群组业务的模型和压力也在不停地扩展,后续可能还会遇到更多的挑战,届时我们服务器也会通过更优的处理方式来应对。

 

感兴趣的开发者可以扫码下载融云的 IM 即时通讯 Demo 产品:SealTalk,体验融云的群聊、聊天室等通信能力。

3.png

集成融云 Web 音视频通话踩坑之旅

WebRTC苏道 发表了文章 • 0 个评论 • 578 次浏览 • 2020-12-29 16:44 • 来自相关话题

前言最近有个项目需要使用的融云的 CallLib SDK 实现类似微信的视频通话,所以在项目还未正式启动的时候,我已经偷偷的开始进行集成了,以免到时候不熟一顿加班那真的欲哭无泪了,好消息就是我已经使用过融云家的 IMLib SDK 做过即时通讯的功能,所以整个... ...查看全部

前言

最近有个项目需要使用的融云的 CallLib SDK 实现类似微信的视频通话,所以在项目还未正式启动的时候,我已经偷偷的开始进行集成了,以免到时候不熟一顿加班那真的欲哭无泪了,好消息就是我已经使用过融云家的 IMLib SDK 做过即时通讯的功能,所以整个注册流程和开发者后台的使用已经比较熟了,当然,即时不熟也没关系,跟着他们的文档一步一步来,也能很快的就上手了。
融云官网:https://www.rongcloud.cn/

下面是集成的时候碰到的一些需要注意的问题:

1、Web 站点必须为 localhost 或 https
2、必须成功连接 IM 后, 才可进行 CallLib 通话
3、新版谷歌浏览器(86版本)会报错,我集成的 RTC 版本是 3.2.3
4、音视频通话接通不了

综上问题,我会逐一解答,关于具体的集成可以直接参考:https://docs.rongcloud.cn/v4/views/rtc/call/noui/quick/web.html

还有具体的 demo 也可以参考一下 https://github.com/rongcloud-snippets/web-call-quickstart

Web 站点必须为 localhost 或 https:
这个是融云的使用音视频通话的前置条件,本来在本地调试的时候好好的,可是发布到线上的时候就不能用了,最后提交工单询问融云的技术人员上线是否还需要配置什么,最后排查一圈发现生产环境使用的站点是 http(欲哭无泪。。。),童鞋们引以为戒啊!!

必须成功连接 IM 后, 才可进行 CallLib 通话:
直接看代码:

// appKey 可在融云开发者后台获取
const im = RongIMLib.init({ appkey: '<your-appkey>' })
// 添加事件监听器
im.watch({
  // 连接状态监听
  status(evt) {
    console.log('连接状态码:', evt.status);
  },
  // 消息监听
  message(evt) {
    console.log('收到新消息:', evt.message);
  }
})
// CallLib 初始化
var config = {
    timeout: 20000,
    RongIMLib: RongIMLib,
    RongRTC: RongRTC
};
rongCallLib = RongCallLib.init(config);
//token 可从开发者后台获取 或 Server API
const token = ''
im.connect({ token }).then(user => {
  console.log('链接成功, 链接用户 id 为: ', user.id);
}).catch(error => {
  console.log('链接失败: ', error.code, error.msg);
});

新版谷歌浏览器会报错:
由于浏览器更新,导致 SDK 需要升级,升级到最新版本的 RTC SDK 下载地址:https://cdn.ronghub.com/RongRTC-3.2.6.min.js
需要注意,如果使用的 SDK 2.X 也需要升级到 2.5.10 以上

音视频通话接通不了:
这种情况我总结分析了一下几种情况,如下:

代码传参错误或者书写错误
这个好像没什么说的,只能怪自己不仔细吧!跟着文档来呗

结束通话没有调用挂断方法 hungup
用户主动发起挂断,在 rongCallLib.commandWatch 监听中收到 HungupMessage 消息,可以调用 rongCallLib.hungup 来挂断通话,不然下次呼叫时会出现报错,提示对方正忙

如何识别挂断原因
HungupMessage 消息中 reason 字段及 SummaryMessage 消息中 status 字段都为挂断原因,详情地址参考:https://docs.rongcloud.cn/rtc/calllib/web/code/

因为对音视频的集成也刚开始,还在学习当中。后续随着继续深入,也会同步音视频相关的集成问题,方便复习记录也希望能帮到需要的童鞋!!!


融云 CallLib 集成遇到的问题

IM即时通讯苏道 发表了文章 • 0 个评论 • 549 次浏览 • 2020-12-29 16:41 • 来自相关话题

近期选用融云音视频产品实现类似微信的通话功能, 经过几天的调试, 终于完成了基本功能, 以下总结集成中遇到的问题查看文档首先先查看融云的文档, 介绍不是很详细, 如果不参考 Demo, 集成起来还是比较困难但有一个亮点, 文档内就直接能体验融云 CallLib... ...查看全部

近期选用融云音视频产品实现类似微信的通话功能, 经过几天的调试, 终于完成了基本功能, 以下总结集成中遇到的问题

查看文档

首先先查看融云的文档, 介绍不是很详细, 如果不参考 Demo, 集成起来还是比较困难

但有一个亮点, 文档内就直接能体验融云 CallLib 的效果

融云 CallLib 文档: https://docs.rongcloud.cn/v4/views/rtc/call/noui/intro.html

Demo 参考

Demo 找到两个. 代码都很简单, 没有太多业务代码, 参考起来比较友好

文档中的 Demo: https://github.com/rongcloud-snippets/web-call-quickstart

教程中的 Demo: https://github.com/rongcloud/websdk-demo/tree/master/calllib-v3/

教程类 Demo 包含一个完整的启动教程, 可参考: https://tutorials.rongcloud.cn/tutorial/web-calllib-demo#0

遇到的问题

1、未找到错误码的完整解释

在文档中搜索多遍, 都没有找到错误码的列表. 提工单询问后, 得知只有旧文档中有解释. 新文档还正在添加中

旧文档: https://docs.rongcloud.cn/rtc/calllib/web/code/

2、单对单通话, 一方挂断, 另一方必须也调用挂断方法

设计有些不合理. 应该是考虑兼容多人音视频, 希望单人、多人调用方式保持一致

3、Web 多端登录时, 需要额外处理错误码 8

如果同一个用户在 Web1、Web2 同时登录, 如果用户收到音视频呼叫, Web1 接通后, Web2 会自动挂断, 并抛出一个挂断码 8. 此处逻辑需要额外处理, 给客户一个提示


WebRTC