WebRTC

WebRTC

前端音视频之WebRTC初探

技术交流大兴 发表了文章 • 0 个评论 • 54 次浏览 • 2020-10-22 17:35 • 来自相关话题

今天,我们来一起学习一下 WebRTC,相信你已经对这个前端音视频网红儿有所耳闻了。WebRTC Web Real-Time Communication 网页即时通信WebRTC 于 2011 年 6 月 1 日开源,并在 Google、Mozilla、Ope... ...查看全部

今天,我们来一起学习一下 WebRTC,相信你已经对这个前端音视频网红儿有所耳闻了。

WebRTC Web Real-Time Communication 网页即时通信

WebRTC 于 2011 年 6 月 1 日开源,并在 Google、Mozilla、Opera 等大佬们的支持下被纳入 W3C 推荐标准,它给浏览器和移动应用提供了即时通信的能力。

WebRTC 优势及应用场景

优势

  • 跨平台(Web、Windows、MacOS、Linux、iOS、Android)
  • 实时传输
  • 音视频引擎
  • 免费、免插件、免安装
  • 主流浏览器支持
  • 强大的打洞能力

应用场景

在线教育、在线医疗、音视频会议、即时通讯工具、直播、共享远程桌面、P2P网络加速、游戏(狼人杀、线上KTV)等。

1.png

(有喜欢玩狼人杀的同学吗?有时间可以一起来一局,给我一轮听发言的时间,给你裸点狼坑,一个坑容错。)

WebRTC 整体架构

拉回来,我们看一看 WebRTC 的整体架构,我用不同的颜色标识出了各层级所代表的含义。

2.png

  • Web 应用
  • Web API
  • WebRTC C++ API
  • Session Management 信令管理
  • Transport 传输层
  • Voice Engine 音频引擎
  • Video Engine 视频处理引擎

我们再来看下核心的模块:

Voice Engine 音频引擎

VoIP 软件开发商 Global IP Solutions 提供的 GIPS 引擎可以说是世界上最好的语音引擎,谷歌大佬一举将其收购并开源,也就是 WebRTC 中的 音频引擎。

  • iSAC:WebRTC 音频引擎的默认编解码器,针对 VoIP 和音频流的宽带和超宽带音频编解码器。
  • iLBC:VoIP 音频流的窄带语音编解码器。
  • NetEQ For Voice:针对音频软件实现的语音信号处理元件。NetEQ 算法是自适应抖动控制算法以及语音包丢失隐藏算法,能够有效的处理网络抖动和语音包丢失时对语音质量产生的影响。
  • Acoustic Echo Canceler:AEC,回声消除器。
  • Noise Reduction:NR,噪声抑制。

Video Engine 视频处理引擎

VPx 系列视频编解码器是 Google 大佬收购 ON2 公司后开源的。

  • VP8:视频图像编解码器,WebRTC 视频引擎默认的编解码器。
  • Video Jitter Buffer:视频抖动缓冲器模块。
  • Image Enhancements:图像质量增强模块。

WebRTC 通信原理

媒体协商

媒体协商也就是让双方可以找到共同支持的媒体能力,比如双方都支持的编解码器,这样才能实现彼此之间的音视频通信。

SDP Session Description Protocal

媒体协商所交换的数据就是 SDP,说是协议,其实 SDP 并不是一个真正的协议,它就是一种描述各端“能力”的数据格式。

3.png

上图所示就是 SDP 的一部分,详细内容请参考:SDP: Session Description Protocol

https://tools.ietf.org/html/rfc4566

或者参考卡神的这篇文章:WebRTC:会话描述协议SDP

https://zhuanlan.zhihu.com/p/75492311

网络协商

ICE Interactive Connectivity Establishment 互动式连接建立

想要建立连接,我们要需要拿到双方 IP 和端口的信息,在当下复杂的网络环境下,ICE 统一了各种 NAT 穿越技术(STUN、TURN),可以让客户端成功地穿透远程用户与网络之间可能存在的各类防火墙。

STUN、TURN

STUN:简单 UDP 穿透 NAT,可以使位于 NAT(或多重 NAT) 后的客户端找出自己的公网 IP 地址,以及查出自己位于哪种类型的 NAT 及 NAT 所绑定的 Internet 端口。

我们知道,NAT 主要有以下四个种类:

  • 完全锥型 NAT
  • IP 限制锥型
  • 端口限制锥型
  • 对称型

前三种都可以使用 STUN 穿透,而面对第四种类型,也是大型公司网络中经常采用的对称型 NAT ,这时的路由器只会接受之前连线过的节点所建立的连线。

那么想要处理这种网络情况,我们就需要使用 TURN (中继穿透 NAT) 技术。

TURN 是 STUN 的一个扩展,其主要添加了中继功能。在 STUN 服务器的基础上,再添加几台 TURN 服务器,如果 STUN 分配公网 IP 失败,则可以通过 TURN 服务器请求公网 IP 地址作为中继地址,将媒体数据通过 TURN 服务器进行中转。

信令服务器 Signal Server

拿到了双方的媒体信息(SDP)和网络信息(Candidate)后,我们还需要一台信令服务器作为中间商来转发交换它们。

信令服务器还可以实现一些 IM 功能,比如房间管理,用户进入、退出等。

小结

本文我们了解了 WebRTC 优势及应用场景、WebRTC 的整体架构及主要模块构成以及 WebRTC 的通信原理。这些基础知识和概念是需要我们牢记的,大家要记牢~

参考

  • 《从 0 打造音视频直播系统》 李超
  • 《WebRTC 音视频开发 React+Flutter+Go 实战》 亢少军
  • https://webrtc.github.io/webrtc-org/architecture/
  • https://developer.mozilla.org/zh-CN/docs/Web/API/WebRTC_API
  • https://www.w3.org/TR/webrtc/


本文转自公众号“前端食堂”,作者霍语佳

融云 WebRTC 首帧显示优化策略到底有多强?

技术交流admin 发表了文章 • 0 个评论 • 81 次浏览 • 2020-09-29 17:47 • 来自相关话题

作者:融云 WebRTC 高级工程师 苏道音视频实时通话首帧的显示是一项重要的用户体验标准。本文主要通过对接收端的分析来了解和优化视频首帧的显示时间。流程介绍发送端采集音视频数据,通过编码器生成帧数据。这数据被打包成 RTP 包,通过 ICE 通道发送到接收端... ...查看全部

timg.jpg

作者:融云 WebRTC 高级工程师 苏道


音视频实时通话首帧的显示是一项重要的用户体验标准。本文主要通过对接收端的分析来了解和优化视频首帧的显示时间。


流程介绍

发送端采集音视频数据,通过编码器生成帧数据。这数据被打包成 RTP 包,通过 ICE 通道发送到接收端。接收端接收 RTP 包,取出 RTP payload,完成组帧的操作。之后音视频解码器解码帧数据,生成视频图像或音频 PCM 数据。

640.png


本文参数调整谈论的部分位于上图中的第 4 步。因为是接收端,所以会收到对方的 Offer 请求。先设置 SetRemoteDescription 再 SetLocalDescription。如下图蓝色部分:

2.png


参数调整

视频参数调整

当收到 Signal 线程 SetRemoteDescription 后,会在 Worker 线程中创建 VideoReceiveStream 对象。具体流程为 SetRemoteDescription

VideoChannel::SetRemoteContent_w 创建 WebRtcVideoReceiveStream。

WebRtcVideoReceiveStream 包含了一个 VideoReceiveStream 类型 stream_ 对象,通过 webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream 创建。创建后立即启动 VideoReceiveStream 工作,即调用 Start() 方法。此时 VideoReceiveStream 包含一个 RtpVideoStreamReceiver 对象准备开始处理 video RTP 包。接收方创建 createAnswer 后通过 setLocalDescription 设置 local descritpion。对应会在 Worker 线程中 setLocalContent_w 方法中根据 SDP 设置 channel 的接收参数,最终会调用到 WebRtcVideoReceiveStream::SetRecvParameters。


WebRtcVideoReceiveStream::SetRecvParameters 实现如下:

void WebRtcVideoChannel::WebRtcVideoReceiveStream::SetRecvParameters(
    const ChangedRecvParameters& params) {
  bool video_needs_recreation = false;
  bool flexfec_needs_recreation = false;
  if (params.codec_settings) {
    ConfigureCodecs(*params.codec_settings);
    video_needs_recreation = true;
  }
  if (params.rtp_header_extensions) {
    config_.rtp.extensions = *params.rtp_header_extensions;
    flexfec_config_.rtp_header_extensions = *params.rtp_header_extensions;
    video_needs_recreation = true;
    flexfec_needs_recreation = true;
  }
  if (params.flexfec_payload_type) {
    ConfigureFlexfecCodec(*params.flexfec_payload_type);
    flexfec_needs_recreation = true;
  }
  if (flexfec_needs_recreation) {
    RTC_LOG(LS_INFO) << "MaybeRecreateWebRtcFlexfecStream (recv) because of "
                        "SetRecvParameters";
    MaybeRecreateWebRtcFlexfecStream();
  }
  if (video_needs_recreation) {
    RTC_LOG(LS_INFO)
        << "RecreateWebRtcVideoStream (recv) because of SetRecvParameters";
    RecreateWebRtcVideoStream();
  }
}

根据上图中 SetRecvParameters 代码,如果 codec_settings 不为空、rtp_header_extensions 不为空、flexfec_payload_type 不为空都会重启 VideoReceiveStream。video_needs_recreation 表示是否要重启 VideoReceiveStream。重启过程为,把先前创建的释放掉,然后重建新的 VideoReceiveStream。以 codec_settings 为例,初始 video codec 支持 H264 和 VP8。若对端只支持 H264,协商后的 codec 仅支持 H264。SetRecvParameters 中的 codec_settings 为 H264 不空。其实前后 VideoReceiveStream 的都有 H264 codec,没有必要重建 VideoReceiveStream。可以通过配置本地支持的 video codec 初始列表和 rtp extensions,从而生成的 local SDP 和 remote SDP 中影响接收参数部分调整一致,并且判断 codec_settings 是否相等。如果不相等再 video_needs_recreation 为 true。这样设置就会使 SetRecvParameters 避免触发重启 VideoReceiveStream 逻辑。在 debug 模式下,修改后,验证没有“RecreateWebRtcVideoStream (recv) because of SetRecvParameters”的打印, 即可证明没有 VideoReceiveStream 重启。


音频参数调整

和上面的视频类似,音频也会有因为 rtp extensions 不一致导致重新创建 AudioReceiveStream,也是释放先前的 AudioReceiveStream,再重新创建 AudioReceiveStream。参考代码:

bool WebRtcVoiceMediaChannel::SetRecvParameters(
    const AudioRecvParameters& params) {
  TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetRecvParameters");
  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
  RTC_LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
                   << params.ToString();
  // TODO(pthatcher): Refactor this to be more clean now that we have
  // all the information at once.
  if (!SetRecvCodecs(params.codecs)) {
    return false;
  }
  if (!ValidateRtpExtensions(params.extensions)) {
    return false;
  }
  std::vector<webrtc::RtpExtension> filtered_extensions = FilterRtpExtensions(
      params.extensions, webrtc::RtpExtension::IsSupportedForAudio, false);
  if (recv_rtp_extensions_ != filtered_extensions) {
    recv_rtp_extensions_.swap(filtered_extensions);
    for (auto& it : recv_streams_) {
      it.second->SetRtpExtensionsAndRecreateStream(recv_rtp_extensions_);
    }
  }
  return true;
}

AudioReceiveStream 的构造方法会启动音频设备,即调用 AudioDeviceModule 的 StartPlayout。AudioReceiveStream 的析构方法会停止音频设备,即调用 AudioDeviceModule 的 StopPlayout。因此重启 AudioReceiveStream 会触发多次 StartPlayout/StopPlayout。经测试,这些不必要的操作会导致进入视频会议的房间时,播放的音频有一小段间断的情况。解决方法同样是通过配置本地支持的 audio codec 初始列表和 rtp extensions,从而生成的 local SDP 和 remote SDP 中影响接收参数部分调整一致,避免 AudioReceiveStream 重启逻辑。另外 audio codec 多为 WebRTC 内部实现,去掉一些不用的 Audio Codec,可以减小 WebRTC 对应的库文件。


音视频相互影响

WebRTC 内部有三个非常重要的线程,woker 线程、signal 线程和 network 线程。

调用 PeerConnection 的 API 的调用会由 signal 线程进入到 worker 线程。

worker 线程内完成媒体数据的处理,network 线程处理网络相关的事务,channel.h 文件中有说明,以 _w 结尾的方法为 worker 线程的方法,signal 线程的到 worker 线程的调用是同步操作。如下图中的 InvokerOnWorker 是同步操作,setLocalContent_w 和 setRemoteContent_w 是 worker 线程中的方法。

bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
                                  SdpType type,
                                  std::string* error_desc) {
  TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
  return InvokeOnWorker<bool>(
      RTC_FROM_HERE,
      Bind(&BaseChannel::SetLocalContent_w, this, content, type, error_desc));
}
bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
                                   SdpType type,
                                   std::string* error_desc) {
  TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
  return InvokeOnWorker<bool>(
      RTC_FROM_HERE,
      Bind(&BaseChannel::SetRemoteContent_w, this, content, type, error_desc));
}

setLocalDescription 和 setRemoteDescription 中的 SDP 信息都会通过 PeerConnection 的 PushdownMediaDescription 方法依次下发给 audio/video RtpTransceiver 设置 SDP 信息。举例,执行 audio 的 SetRemoteContent_w 执行很长(比如音频 AudioDeviceModule 的 InitPlayout 执行耗时), 会影响后面的 video SetRemoteContent_w 的设置时间。PushdownMediaDescription 代码:

RTCError PeerConnection::PushdownMediaDescription(
    SdpType type,
    cricket::ContentSource source) {
  const SessionDescriptionInterface* sdesc =
      (source == cricket::CS_LOCAL ? local_description()
                                   : remote_description());
  RTC_DCHECK(sdesc);
  // Push down the new SDP media section for each audio/video transceiver.
  for (const auto& transceiver : transceivers_) {
    const ContentInfo* content_info =
        FindMediaSectionForTransceiver(transceiver, sdesc);
    cricket::ChannelInterface* channel = transceiver->internal()->channel();
    if (!channel || !content_info || content_info->rejected) {
      continue;
    }
    const MediaContentDescription* content_desc =
        content_info->media_description();
    if (!content_desc) {
      continue;
    }
    std::string error;
    bool success = (source == cricket::CS_LOCAL)
                       ? channel->SetLocalContent(content_desc, type, &error)
                       : channel->SetRemoteContent(content_desc, type, &error);
    if (!success) {
      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, error);
    }
  }
  ...
}

其他影响首帧显示的问题


Android图像宽高16字节对齐


AndroidVideoDecoder 是 WebRTC Android 平台上的视频硬解类。AndroidVideoDecoder 利用 MediaCodec API 完成对硬件解码器的调用。

MediaCodec 有已下解码相关的 API:

  •  dequeueInputBuffer:若大于 0,则是返回填充编码数据的缓冲区的索引,该操作为同步操作。

  • getInputBuffer:填充编码数据的 ByteBuffer 数组,结合 dequeueInputBuffer 返回值,可获取一个可填充编码数据的 ByteBuffer。

  • queueInputBuffer:应用将编码数据拷贝到 ByteBuffer 后,通过该方法告知 MediaCodec 已经填写的编码数据的缓冲区索引。

  • dequeueOutputBuffer:若大于 0,则是返回填充解码数据的缓冲区的索引,该操作为同步操作。

  • getOutputBuffer:填充解码数据的 ByteBuffer 数组,结合 dequeueOutputBuffer 返回值,可获取一个可填充解码数据的 ByteBuffer。

  • releaseOutputBuffer:告诉编码器数据处理完成,释放 ByteBuffer 数据。

在实践当中发现,发送端发送的视频宽高需要 16 字节对齐。因为在某些 Android 手机上解码器需要 16 字节对齐。Android 上视频解码先是把待解码的数据通过 queueInputBuffer 给到 MediaCodec。然后通过 dequeueOutputBuffer 反复查看是否有解完的视频帧。若非 16 字节对齐,dequeueOutputBuffer 会有一次 MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED。而不是一上来就能成功解码一帧。经测试发现,帧宽高非 16 字节对齐会比 16 字节对齐的慢 100 ms 左右。


服务器需转发关键帧请求

iOS 移动设备上,WebRTC App应用进入后台后,视频解码由 VTDecompressionSessionDecodeFrame 返回 kVTInvalidSessionErr,表示解码session 无效。从而会触发观看端的关键帧请求给服务器。这里要求服务器必须转发接收端发来的关键帧请求给发送端。若服务器没有转发关键帧给发送端,接收端就会长时间没有可以渲染的图像,从而出现黑屏问题。这种情况下只能等待发送端自己生成关键帧,发送个接收端,从而使黑屏的接收端恢复正常。


WebRTC内部的一些丢弃数据逻辑举例


Webrtc从接受报数据到、给到解码器之间的过程中也会有很多验证数据的正确性。

举例1

PacketBuffer 中记录着当前缓存的最小的序号 first_seq_num_(这个值也是会被更新的)。当 PacketBuffer 中 InsertPacket 时候,如果即将要插入的 packet 的序号 seq_num 小于 first_seq_num,这个 packet 会被丢弃掉。如果因此持续丢弃 packet,就会有视频不显示或卡顿的情况。

举例2

正常情况下 FrameBuffer 中帧的 picture id,时间戳都是一直正增长的。如果 FrameBuffer 收到 picture_id 比最后解码帧的 picture id 小时,分两种情况:

  • 1. 时间戳比最后解码帧的时间戳大,且是关键帧,就会保存下来;

  • 2. 除情况 1 之外的帧都会丢弃掉;

     

代码如下:

auto last_decoded_frame = decoded_frames_history_.GetLastDecodedFrameId();
auto last_decoded_frame_timestamp =
 decoded_frames_history_.GetLastDecodedFrameTimestamp();
if (last_decoded_frame && id <= *last_decoded_frame) {
if (AheadOf(frame->Timestamp(), *last_decoded_frame_timestamp) &&
   frame->is_keyframe()) {
 // If this frame has a newer timestamp but an earlier picture id then we
 // assume there has been a jump in the picture id due to some encoder
 // reconfiguration or some other reason. Even though this is not according
 // to spec we can still continue to decode from this frame if it is a
 // keyframe.
 RTC_LOG(LS_WARNING)
     << "A jump in picture id was detected, clearing buffer.";
 ClearFramesAndHistory();
 last_continuous_picture_id = -1;
} else {
 RTC_LOG(LS_WARNING) << "Frame with (picture_id:spatial_id) ("
                     << id.picture_id << ":"
                     << static_cast<int>(id.spatial_layer)
                     << ") inserted after frame ("
                     << last_decoded_frame->picture_id << ":"
                     << static_cast<int>(last_decoded_frame->spatial_layer)
                     << ") was handed off for decoding, dropping frame.";
 return last_continuous_picture_id;
}
}

因此为了能让收到了流顺利播放,发送端和中转的服务端需要确保视频帧的 picture_id, 时间戳正确性。

WebRTC 还有其他很多丢帧逻辑,若网络正常且有持续有接收数据,但是视频卡顿或黑屏无显示,多为流本身的问题。


Ending


本文通过分析 WebRTC 音视频接收端的处理逻辑,列举了一些可以优化首帧显示的点,比如通过调整 local SDP 和 remote SDP 中与影响接收端处理的相关部分,从而避免 Audio/Video ReceiveStream 的重启。另外列举了 Android 解码器对视频宽高的要求、服务端对关键帧请求处理、以及 WebRTC 代码内部的一些丢帧逻辑等多个方面对视频显示的影响。这些点都提高了融云 SDK 视频首帧的显示时间,改善了用户体验。


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

科技前线融云那些事 发表了文章 • 0 个评论 • 127 次浏览 • 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 时代的创新发展。

融云亮相2019音视频技术大会 深度解析 WebRTC 服务架构设计

科技前线融云那些事 发表了文章 • 0 个评论 • 28 次浏览 • 2020-06-16 18:21 • 来自相关话题

“基于 WebRTC 的低延迟直播将会是未来直播行业的主流解决方案!”这是融云联合创始人兼CTO杨攀在 LiveVideoStackCon 2019 音视频技术大会上对于未来行业趋势的判断。2019年8月23 – 24日,LiveVideoStackCon 音... ...查看全部

“基于 WebRTC 的低延迟直播将会是未来直播行业的主流解决方案!”这是融云联合创始人兼CTO杨攀在 LiveVideoStackCon 2019 音视频技术大会上对于未来行业趋势的判断。

2019年8月23 – 24日,LiveVideoStackCon 音视频技术大会在北京举办,本届大会以“多媒体技术赋能新世界”为主题,聚焦音视频、图像等技术在全行业领域的最新探索与应用实践。融云联合创始人兼 CTO 杨攀应邀参会并发表了题为《可扩展的公有云媒体服务设计解析》的精彩演讲。


融云联合创始人兼 CTO 杨攀
在演讲中,杨攀向参会者介绍了融云 WebRTC 在服务端架构设计上的基本理念和思路,并将融云 WebRTC 的设计理念归纳为四点:复用 IM 消息通道;核心服务专注通信、能力服务专注业务;全球互联;部署简单、方便运维。同时在演讲中,杨攀还详细介绍了媒体服务和能力服务相关的架构设计、数据中心内服务集群的设计理念及遍布全球的服务网络。

杨攀在演讲中表示:“融云架构设计的核心理念就是解耦,让各项功能各司其职,避免互相依赖,这样就可以做到简单方便的部署和运维,让故障问题的排查更加方便,极大地降低企业的管理成本和运维成本。”而另一个核心理念是“全球互联”,融云为此专门构建了一张全球通信网络。


融云CTO杨攀解析媒体服务的架构设计
对于融云的媒体服务,杨攀在现场风趣地将其形容为“三无服务”。何谓“三无”?第一个“无”是媒体服务对其他媒体服务无依赖,第二个“无”是其他媒体服务对媒体服务自身无依赖,第三个“无”是每一个媒体服务自身无中心化配置。杨攀表示,这样“三无”化设计的目的同样是为了让系统足够简单易用,方便全球化的部署和运维。

在能力服务层面,杨攀表示,“解耦”作为核心设计理念贯穿在能力服务的设计中。首先是与媒体服务或信令服务解耦,不形成依赖关系,保持独立的架构设计。其次,不靠中央配置控制任何功能,而是通过接口和数据形成调用关系来实现。目前,融云可以为客户提供音视频混流、音视频审核、云端录像、视频标注等多样化的能力。


融云全球网络设计原则
在演讲的最后,杨攀就融云的全球网络设计原则进行了解析。他表示,当前全球网络环境仍亟待提升,特别是在国外,跨区域、跨运营商很容易导致音视频的延时和丢包,在这种客观的现实条件下,对于企业的全球通信能力提出了更高的要求。杨攀表示,融云在全球网络设计上有三个原则:一、客户端就近接入,多链路选择;二、数据中心间同源音视频只有一路级联;三、利用 IaaS 能力,进行中心间级联链路的优化。

目前,融云在全球设立了多个数据中心,并拥有数千个加速节点,覆盖全球所有国家及地区(共 233 个),构建起了一张安全、可靠、低延时、高并发的全球通信网。通过遍布全球的优质接入点,结合融云自研的最优链路调度算法,可将消息快速分发给终端用户,解决因跨国、跨运营商、大规模用户访问而导致的响应慢、丢包高、服务不稳定等问题。


参与嘉宾在融云展位交流
在本次大会上,杨攀将融云在 WebRTC 领域的架构设计理念和思路分享给所有参会者,旨在与业内技术人员进行思维上的交流、启发和碰撞,不断开拓视野、拓宽思路,与全球开发者一道加速音视频领域的创新发展。除了精彩的干货分享外,融云还在大会现场设立了服务展台,大屏实时播放融云产品的 Demo 视频,并由工作人员在现场向感兴趣的参会者介绍融云的产品和技术服务能力。

【关于融云】

融云,安全、可靠的全球互联网通信云服务商,向开发者和企业提供即时通讯和实时音视频通信云服务。iResearch 艾瑞权威数据报告显示,融云即时通讯云市场份额连续多年稳居头位。

融云构建了一张覆盖全球所有国家及地区(共 233 个)的通信云网络,在全球各地设立多个数据中心及数千个加速节点。基于客户业务需求,融云可提供多种部署模式——公有云、私有云、混合云,为全球企业提供稳定的互联网通信云服务。针对企业级用户,融云将业务垂直到各个行业,为社交、直播、金融、交通运输、教育、电商、医疗等多个行业领域推出了针对性解决方案。

融云基于海量业务的技术锤炼,从基础架构到精细化运营,充分体现平台实力;凭借卓越的产品和优质的服务,在开发者规模、行业覆盖率、平台日活跃用户数、日均消息量等方面超越全行业。目前,已有数十万互联网用户及上千家企业级用户通过融云实现了场景化沟通。

【融云分析】WebRTC P2P 连接技术之 STUN 和 ICE 协议解密

科技前线苏道 发表了文章 • 0 个评论 • 29 次浏览 • 2020-06-16 18:16 • 来自相关话题

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

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.2 地址受限锥型

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


1.3 端口受限锥型

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


1.4 对称型

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


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 和消息长度。


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

magic cookie 为固定值 0x2112A442。

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

2.2 STUN 消息类型


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

2.3 STUN 属性

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


(图)STUN 属性
STUN 属性格式:

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

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


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


具体说明如下:

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。


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


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

3. ICE 简介

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


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

3.1 收集候选地址

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

所以有四种候选地址:


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


(图)ICE 端口
3.2 连通检测

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


(图)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)


再根据 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。


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


(图)AGGRESSIVE 提名
3.5 ICE 示例

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


(图)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 为


替换地址后


因为 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。


消息 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 协议 RTC5245 以及 WebRTC 的 P2P 部分的具体实现。

【融云分析】做好 WebRTC 的两大必备要素

科技前线融云那些事 发表了文章 • 0 个评论 • 29 次浏览 • 2020-06-16 18:01 • 来自相关话题

| 什么是 WebRTCWebRTC 是一个可以使我们在浏览器或移动 App 中直接进行音频/视频交流的技术,它可以进行 P2P 文件共享,处理大量音频数据,实现在线视频会议等,WebRTC 使设备能够在平台和浏览器之间传输音频和视频。使用特定的 API ,开... ...查看全部

| 什么是 WebRTC

WebRTC 是一个可以使我们在浏览器或移动 App 中直接进行音频/视频交流的技术,它可以进行 P2P 文件共享,处理大量音频数据,实现在线视频会议等,WebRTC 使设备能够在平台和浏览器之间传输音频和视频。使用特定的 API ,开发人员可以允许他们的用户通过简单的浏览器连接设备,而无需任何额外的插件、扩展或软件安装。这种多功能性使得 WebRTC 成为各种物联网设备开发人员的热门选择。

| WebRTC 的应用前景

从 2G 时代的文字信息传输到 3G 时代的图片传输再到 4G 时代的直播热潮,每个网速时代的变革都将我们的梦想一步步实现;随着 5G 即将到来,更好的上网体验将会极大地推动音视频行业的发展和创新。

WebRTC 也将激活人与人、人与物、物与物之间的信息纽带,解决互联网音视频通信的技术门槛问题,成为应用场景创新的强大技术保障,为社交、监控、视频会议、物联网、在线教育、远程医疗等场景注入新的活力。随之,互联网尤其是移动互联网上基于 WebRTC 的各种应用创新也将层出不穷。

| 如何做好 WebRTC

一款音视频产品通常会包含信令服务、媒体服务、网络服务等几部分;而一款运行稳定、性能出色的 WebRTC 产品,则需要满足以下几个要求。

1、稳定的信令系统

我们需要通过信令来控制 WebRTC ,并且在此基础上构建各种业务逻辑。信令即协调通讯的过程,应用要发起一个音视频通话,通常需要在客户端之间交换如下信息:

1) 会话的信息

2) 设备的能力,编解码、分辨率、码率等

3) 秘钥信息,用于创建安全连接

4) 网络信息,如外部能访问的主机 IP 和端口

5) 传递信息,通过信令来实现业务场景中的通话控制

……


如上图:如果 A 和 B 要发起音视频通话,需要将双方的 SDP 信息做交换,才能建立连接。由此可见信令系统若想保证足够的稳定,连通率、到达率、高并发、高可用等技术指标需全部达标,才能确保 WebRTC 通话的建立和通话过程中的逻辑控制。

2、高可用的媒体服务器

WebRTC 常见的几种模式如下:

1) Mesh 网状结构

通过搭建 Turn/Stun 服务直接发起端到端的 P2P 通话。


优点:不需要搭建 MediaServer 。

缺点:对于多人通话需要每个客户端都跟其他两个端分别建立 P2P 连接,每新增一个客户端,所有的客户端都需要新增一路数据上行,导致客户端上行带宽占用太大。因此,通话人数越多,效果越差,也无法在服务端对视频进行额外处理,如:录制存储回放、实时转码、智能分析、多路合流、转推直播等。

2)MCU

服务端负责把参与者的视频做混流,多人参会每个人只有一个上行视频,同时接收一个下行视频流。


优点:客户端压力较小,带宽消耗小,服务端可以控制下发的视频数据,从而可以发起更多参与者的视频会议。

缺点:服务器资源消耗较大,对服务器的性能要求高,服务器成本高昂。

3)SFU

SFU 的全称是:Selective Forwarding Unit,是一种通过服务器来路由和转发 WebRTC 客户端音视频数据流的方法。 SFU 服务器最核心的特点是把自己“伪装”成一个 WebRTC 的客户端,将一个 Client 端的数据转发到其他多个 Client 端。


优点:对服务器性能要求不高。

缺点:对服务器和客户端带宽要求高。

| 融云音视频的实践

音视频领域飞速发展的今天,融云也通过在音视频领域多年的摸爬滚打,充分借助融云 IM 通道的稳定性和数年来逐步优化的覆盖全球的专有网络优势,打造出了自己的音视频解决方案。

1、信令系统

1)可靠性

融云对分布式 RTC 网络的活用,让信令服务与媒体服务不需要状态同步,媒体中心间不需要状态同步;音视频复用融云即时通讯信令通道,信令服务与媒体服务解耦、无依赖;弱网环境下,消息发送方只要将消息发送到服务器端,服务器端能确保消息不丢、不乱、不重。

2)安全性

基于融云自有知识产权的连接加密技术,可以防止黑客以中间人方式进行数据窃听,数据在传输过程中不可破解, NAV 导航服务与 CMP 连接管理服务的安全算法一致,每个客户端从导航服务获取到加密校验值( SM2 标准),均按照安全算法与所连接的 CMP 服务进行安全协商,针对校验值 CMP 会进行合法性验证( SM3标准),协商的校验值不能在其他 CMP 连接管理服务上使用。消息在传输之前,通过 SM4 对数据进行加密,并且通过加密连接传输将信息发送到发送方所在 CMP 连接管理服务,之后,由发送方所在 CMP 连接管理服务进行解密并将解密后的消息发给消息服务,依据协议内容,由消息服务负责将信息传递给接收方所在 CMP 连接管理服务,而后 CMP 连接管理服务依据接收方的密钥进行信息加密,最后通过加密连接下发信息。

2、MediaServer


1) 全球化部署,低延迟

全球部署多个 MediaServer 数据中心,用户就近接入;跨国网络之间通过专线连接,保证媒体数据传输延迟低。

2) 动态扩展

信令和 MediaServer 完全解耦,随时随地部署,通过监测服务器负载情况可以随着业务量级增长动态横向扩容,保证业务的高可用性。

3) 高质量音视频流

通过高效的处理,提高服务器吞吐量,减少丢包率,通过丢包重传和网络探测机制,提高在弱网环境下的音视频质量和用户体验。

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

科技前线融云那些事 发表了文章 • 0 个评论 • 127 次浏览 • 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 个评论 • 54 次浏览 • 2020-10-22 17:35 • 来自相关话题

今天,我们来一起学习一下 WebRTC,相信你已经对这个前端音视频网红儿有所耳闻了。WebRTC Web Real-Time Communication 网页即时通信WebRTC 于 2011 年 6 月 1 日开源,并在 Google、Mozilla、Ope... ...查看全部

今天,我们来一起学习一下 WebRTC,相信你已经对这个前端音视频网红儿有所耳闻了。

WebRTC Web Real-Time Communication 网页即时通信

WebRTC 于 2011 年 6 月 1 日开源,并在 Google、Mozilla、Opera 等大佬们的支持下被纳入 W3C 推荐标准,它给浏览器和移动应用提供了即时通信的能力。

WebRTC 优势及应用场景

优势

  • 跨平台(Web、Windows、MacOS、Linux、iOS、Android)
  • 实时传输
  • 音视频引擎
  • 免费、免插件、免安装
  • 主流浏览器支持
  • 强大的打洞能力

应用场景

在线教育、在线医疗、音视频会议、即时通讯工具、直播、共享远程桌面、P2P网络加速、游戏(狼人杀、线上KTV)等。

1.png

(有喜欢玩狼人杀的同学吗?有时间可以一起来一局,给我一轮听发言的时间,给你裸点狼坑,一个坑容错。)

WebRTC 整体架构

拉回来,我们看一看 WebRTC 的整体架构,我用不同的颜色标识出了各层级所代表的含义。

2.png

  • Web 应用
  • Web API
  • WebRTC C++ API
  • Session Management 信令管理
  • Transport 传输层
  • Voice Engine 音频引擎
  • Video Engine 视频处理引擎

我们再来看下核心的模块:

Voice Engine 音频引擎

VoIP 软件开发商 Global IP Solutions 提供的 GIPS 引擎可以说是世界上最好的语音引擎,谷歌大佬一举将其收购并开源,也就是 WebRTC 中的 音频引擎。

  • iSAC:WebRTC 音频引擎的默认编解码器,针对 VoIP 和音频流的宽带和超宽带音频编解码器。
  • iLBC:VoIP 音频流的窄带语音编解码器。
  • NetEQ For Voice:针对音频软件实现的语音信号处理元件。NetEQ 算法是自适应抖动控制算法以及语音包丢失隐藏算法,能够有效的处理网络抖动和语音包丢失时对语音质量产生的影响。
  • Acoustic Echo Canceler:AEC,回声消除器。
  • Noise Reduction:NR,噪声抑制。

Video Engine 视频处理引擎

VPx 系列视频编解码器是 Google 大佬收购 ON2 公司后开源的。

  • VP8:视频图像编解码器,WebRTC 视频引擎默认的编解码器。
  • Video Jitter Buffer:视频抖动缓冲器模块。
  • Image Enhancements:图像质量增强模块。

WebRTC 通信原理

媒体协商

媒体协商也就是让双方可以找到共同支持的媒体能力,比如双方都支持的编解码器,这样才能实现彼此之间的音视频通信。

SDP Session Description Protocal

媒体协商所交换的数据就是 SDP,说是协议,其实 SDP 并不是一个真正的协议,它就是一种描述各端“能力”的数据格式。

3.png

上图所示就是 SDP 的一部分,详细内容请参考:SDP: Session Description Protocol

https://tools.ietf.org/html/rfc4566

或者参考卡神的这篇文章:WebRTC:会话描述协议SDP

https://zhuanlan.zhihu.com/p/75492311

网络协商

ICE Interactive Connectivity Establishment 互动式连接建立

想要建立连接,我们要需要拿到双方 IP 和端口的信息,在当下复杂的网络环境下,ICE 统一了各种 NAT 穿越技术(STUN、TURN),可以让客户端成功地穿透远程用户与网络之间可能存在的各类防火墙。

STUN、TURN

STUN:简单 UDP 穿透 NAT,可以使位于 NAT(或多重 NAT) 后的客户端找出自己的公网 IP 地址,以及查出自己位于哪种类型的 NAT 及 NAT 所绑定的 Internet 端口。

我们知道,NAT 主要有以下四个种类:

  • 完全锥型 NAT
  • IP 限制锥型
  • 端口限制锥型
  • 对称型

前三种都可以使用 STUN 穿透,而面对第四种类型,也是大型公司网络中经常采用的对称型 NAT ,这时的路由器只会接受之前连线过的节点所建立的连线。

那么想要处理这种网络情况,我们就需要使用 TURN (中继穿透 NAT) 技术。

TURN 是 STUN 的一个扩展,其主要添加了中继功能。在 STUN 服务器的基础上,再添加几台 TURN 服务器,如果 STUN 分配公网 IP 失败,则可以通过 TURN 服务器请求公网 IP 地址作为中继地址,将媒体数据通过 TURN 服务器进行中转。

信令服务器 Signal Server

拿到了双方的媒体信息(SDP)和网络信息(Candidate)后,我们还需要一台信令服务器作为中间商来转发交换它们。

信令服务器还可以实现一些 IM 功能,比如房间管理,用户进入、退出等。

小结

本文我们了解了 WebRTC 优势及应用场景、WebRTC 的整体架构及主要模块构成以及 WebRTC 的通信原理。这些基础知识和概念是需要我们牢记的,大家要记牢~

参考

  • 《从 0 打造音视频直播系统》 李超
  • 《WebRTC 音视频开发 React+Flutter+Go 实战》 亢少军
  • https://webrtc.github.io/webrtc-org/architecture/
  • https://developer.mozilla.org/zh-CN/docs/Web/API/WebRTC_API
  • https://www.w3.org/TR/webrtc/


本文转自公众号“前端食堂”,作者霍语佳

融云 WebRTC 首帧显示优化策略到底有多强?

技术交流admin 发表了文章 • 0 个评论 • 81 次浏览 • 2020-09-29 17:47 • 来自相关话题

作者:融云 WebRTC 高级工程师 苏道音视频实时通话首帧的显示是一项重要的用户体验标准。本文主要通过对接收端的分析来了解和优化视频首帧的显示时间。流程介绍发送端采集音视频数据,通过编码器生成帧数据。这数据被打包成 RTP 包,通过 ICE 通道发送到接收端... ...查看全部

timg.jpg

作者:融云 WebRTC 高级工程师 苏道


音视频实时通话首帧的显示是一项重要的用户体验标准。本文主要通过对接收端的分析来了解和优化视频首帧的显示时间。


流程介绍

发送端采集音视频数据,通过编码器生成帧数据。这数据被打包成 RTP 包,通过 ICE 通道发送到接收端。接收端接收 RTP 包,取出 RTP payload,完成组帧的操作。之后音视频解码器解码帧数据,生成视频图像或音频 PCM 数据。

640.png


本文参数调整谈论的部分位于上图中的第 4 步。因为是接收端,所以会收到对方的 Offer 请求。先设置 SetRemoteDescription 再 SetLocalDescription。如下图蓝色部分:

2.png


参数调整

视频参数调整

当收到 Signal 线程 SetRemoteDescription 后,会在 Worker 线程中创建 VideoReceiveStream 对象。具体流程为 SetRemoteDescription

VideoChannel::SetRemoteContent_w 创建 WebRtcVideoReceiveStream。

WebRtcVideoReceiveStream 包含了一个 VideoReceiveStream 类型 stream_ 对象,通过 webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream 创建。创建后立即启动 VideoReceiveStream 工作,即调用 Start() 方法。此时 VideoReceiveStream 包含一个 RtpVideoStreamReceiver 对象准备开始处理 video RTP 包。接收方创建 createAnswer 后通过 setLocalDescription 设置 local descritpion。对应会在 Worker 线程中 setLocalContent_w 方法中根据 SDP 设置 channel 的接收参数,最终会调用到 WebRtcVideoReceiveStream::SetRecvParameters。


WebRtcVideoReceiveStream::SetRecvParameters 实现如下:

void WebRtcVideoChannel::WebRtcVideoReceiveStream::SetRecvParameters(
    const ChangedRecvParameters& params) {
  bool video_needs_recreation = false;
  bool flexfec_needs_recreation = false;
  if (params.codec_settings) {
    ConfigureCodecs(*params.codec_settings);
    video_needs_recreation = true;
  }
  if (params.rtp_header_extensions) {
    config_.rtp.extensions = *params.rtp_header_extensions;
    flexfec_config_.rtp_header_extensions = *params.rtp_header_extensions;
    video_needs_recreation = true;
    flexfec_needs_recreation = true;
  }
  if (params.flexfec_payload_type) {
    ConfigureFlexfecCodec(*params.flexfec_payload_type);
    flexfec_needs_recreation = true;
  }
  if (flexfec_needs_recreation) {
    RTC_LOG(LS_INFO) << "MaybeRecreateWebRtcFlexfecStream (recv) because of "
                        "SetRecvParameters";
    MaybeRecreateWebRtcFlexfecStream();
  }
  if (video_needs_recreation) {
    RTC_LOG(LS_INFO)
        << "RecreateWebRtcVideoStream (recv) because of SetRecvParameters";
    RecreateWebRtcVideoStream();
  }
}

根据上图中 SetRecvParameters 代码,如果 codec_settings 不为空、rtp_header_extensions 不为空、flexfec_payload_type 不为空都会重启 VideoReceiveStream。video_needs_recreation 表示是否要重启 VideoReceiveStream。重启过程为,把先前创建的释放掉,然后重建新的 VideoReceiveStream。以 codec_settings 为例,初始 video codec 支持 H264 和 VP8。若对端只支持 H264,协商后的 codec 仅支持 H264。SetRecvParameters 中的 codec_settings 为 H264 不空。其实前后 VideoReceiveStream 的都有 H264 codec,没有必要重建 VideoReceiveStream。可以通过配置本地支持的 video codec 初始列表和 rtp extensions,从而生成的 local SDP 和 remote SDP 中影响接收参数部分调整一致,并且判断 codec_settings 是否相等。如果不相等再 video_needs_recreation 为 true。这样设置就会使 SetRecvParameters 避免触发重启 VideoReceiveStream 逻辑。在 debug 模式下,修改后,验证没有“RecreateWebRtcVideoStream (recv) because of SetRecvParameters”的打印, 即可证明没有 VideoReceiveStream 重启。


音频参数调整

和上面的视频类似,音频也会有因为 rtp extensions 不一致导致重新创建 AudioReceiveStream,也是释放先前的 AudioReceiveStream,再重新创建 AudioReceiveStream。参考代码:

bool WebRtcVoiceMediaChannel::SetRecvParameters(
    const AudioRecvParameters& params) {
  TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetRecvParameters");
  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
  RTC_LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
                   << params.ToString();
  // TODO(pthatcher): Refactor this to be more clean now that we have
  // all the information at once.
  if (!SetRecvCodecs(params.codecs)) {
    return false;
  }
  if (!ValidateRtpExtensions(params.extensions)) {
    return false;
  }
  std::vector<webrtc::RtpExtension> filtered_extensions = FilterRtpExtensions(
      params.extensions, webrtc::RtpExtension::IsSupportedForAudio, false);
  if (recv_rtp_extensions_ != filtered_extensions) {
    recv_rtp_extensions_.swap(filtered_extensions);
    for (auto& it : recv_streams_) {
      it.second->SetRtpExtensionsAndRecreateStream(recv_rtp_extensions_);
    }
  }
  return true;
}

AudioReceiveStream 的构造方法会启动音频设备,即调用 AudioDeviceModule 的 StartPlayout。AudioReceiveStream 的析构方法会停止音频设备,即调用 AudioDeviceModule 的 StopPlayout。因此重启 AudioReceiveStream 会触发多次 StartPlayout/StopPlayout。经测试,这些不必要的操作会导致进入视频会议的房间时,播放的音频有一小段间断的情况。解决方法同样是通过配置本地支持的 audio codec 初始列表和 rtp extensions,从而生成的 local SDP 和 remote SDP 中影响接收参数部分调整一致,避免 AudioReceiveStream 重启逻辑。另外 audio codec 多为 WebRTC 内部实现,去掉一些不用的 Audio Codec,可以减小 WebRTC 对应的库文件。


音视频相互影响

WebRTC 内部有三个非常重要的线程,woker 线程、signal 线程和 network 线程。

调用 PeerConnection 的 API 的调用会由 signal 线程进入到 worker 线程。

worker 线程内完成媒体数据的处理,network 线程处理网络相关的事务,channel.h 文件中有说明,以 _w 结尾的方法为 worker 线程的方法,signal 线程的到 worker 线程的调用是同步操作。如下图中的 InvokerOnWorker 是同步操作,setLocalContent_w 和 setRemoteContent_w 是 worker 线程中的方法。

bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
                                  SdpType type,
                                  std::string* error_desc) {
  TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
  return InvokeOnWorker<bool>(
      RTC_FROM_HERE,
      Bind(&BaseChannel::SetLocalContent_w, this, content, type, error_desc));
}
bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
                                   SdpType type,
                                   std::string* error_desc) {
  TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
  return InvokeOnWorker<bool>(
      RTC_FROM_HERE,
      Bind(&BaseChannel::SetRemoteContent_w, this, content, type, error_desc));
}

setLocalDescription 和 setRemoteDescription 中的 SDP 信息都会通过 PeerConnection 的 PushdownMediaDescription 方法依次下发给 audio/video RtpTransceiver 设置 SDP 信息。举例,执行 audio 的 SetRemoteContent_w 执行很长(比如音频 AudioDeviceModule 的 InitPlayout 执行耗时), 会影响后面的 video SetRemoteContent_w 的设置时间。PushdownMediaDescription 代码:

RTCError PeerConnection::PushdownMediaDescription(
    SdpType type,
    cricket::ContentSource source) {
  const SessionDescriptionInterface* sdesc =
      (source == cricket::CS_LOCAL ? local_description()
                                   : remote_description());
  RTC_DCHECK(sdesc);
  // Push down the new SDP media section for each audio/video transceiver.
  for (const auto& transceiver : transceivers_) {
    const ContentInfo* content_info =
        FindMediaSectionForTransceiver(transceiver, sdesc);
    cricket::ChannelInterface* channel = transceiver->internal()->channel();
    if (!channel || !content_info || content_info->rejected) {
      continue;
    }
    const MediaContentDescription* content_desc =
        content_info->media_description();
    if (!content_desc) {
      continue;
    }
    std::string error;
    bool success = (source == cricket::CS_LOCAL)
                       ? channel->SetLocalContent(content_desc, type, &error)
                       : channel->SetRemoteContent(content_desc, type, &error);
    if (!success) {
      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, error);
    }
  }
  ...
}

其他影响首帧显示的问题


Android图像宽高16字节对齐


AndroidVideoDecoder 是 WebRTC Android 平台上的视频硬解类。AndroidVideoDecoder 利用 MediaCodec API 完成对硬件解码器的调用。

MediaCodec 有已下解码相关的 API:

  •  dequeueInputBuffer:若大于 0,则是返回填充编码数据的缓冲区的索引,该操作为同步操作。

  • getInputBuffer:填充编码数据的 ByteBuffer 数组,结合 dequeueInputBuffer 返回值,可获取一个可填充编码数据的 ByteBuffer。

  • queueInputBuffer:应用将编码数据拷贝到 ByteBuffer 后,通过该方法告知 MediaCodec 已经填写的编码数据的缓冲区索引。

  • dequeueOutputBuffer:若大于 0,则是返回填充解码数据的缓冲区的索引,该操作为同步操作。

  • getOutputBuffer:填充解码数据的 ByteBuffer 数组,结合 dequeueOutputBuffer 返回值,可获取一个可填充解码数据的 ByteBuffer。

  • releaseOutputBuffer:告诉编码器数据处理完成,释放 ByteBuffer 数据。

在实践当中发现,发送端发送的视频宽高需要 16 字节对齐。因为在某些 Android 手机上解码器需要 16 字节对齐。Android 上视频解码先是把待解码的数据通过 queueInputBuffer 给到 MediaCodec。然后通过 dequeueOutputBuffer 反复查看是否有解完的视频帧。若非 16 字节对齐,dequeueOutputBuffer 会有一次 MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED。而不是一上来就能成功解码一帧。经测试发现,帧宽高非 16 字节对齐会比 16 字节对齐的慢 100 ms 左右。


服务器需转发关键帧请求

iOS 移动设备上,WebRTC App应用进入后台后,视频解码由 VTDecompressionSessionDecodeFrame 返回 kVTInvalidSessionErr,表示解码session 无效。从而会触发观看端的关键帧请求给服务器。这里要求服务器必须转发接收端发来的关键帧请求给发送端。若服务器没有转发关键帧给发送端,接收端就会长时间没有可以渲染的图像,从而出现黑屏问题。这种情况下只能等待发送端自己生成关键帧,发送个接收端,从而使黑屏的接收端恢复正常。


WebRTC内部的一些丢弃数据逻辑举例


Webrtc从接受报数据到、给到解码器之间的过程中也会有很多验证数据的正确性。

举例1

PacketBuffer 中记录着当前缓存的最小的序号 first_seq_num_(这个值也是会被更新的)。当 PacketBuffer 中 InsertPacket 时候,如果即将要插入的 packet 的序号 seq_num 小于 first_seq_num,这个 packet 会被丢弃掉。如果因此持续丢弃 packet,就会有视频不显示或卡顿的情况。

举例2

正常情况下 FrameBuffer 中帧的 picture id,时间戳都是一直正增长的。如果 FrameBuffer 收到 picture_id 比最后解码帧的 picture id 小时,分两种情况:

  • 1. 时间戳比最后解码帧的时间戳大,且是关键帧,就会保存下来;

  • 2. 除情况 1 之外的帧都会丢弃掉;

     

代码如下:

auto last_decoded_frame = decoded_frames_history_.GetLastDecodedFrameId();
auto last_decoded_frame_timestamp =
 decoded_frames_history_.GetLastDecodedFrameTimestamp();
if (last_decoded_frame && id <= *last_decoded_frame) {
if (AheadOf(frame->Timestamp(), *last_decoded_frame_timestamp) &&
   frame->is_keyframe()) {
 // If this frame has a newer timestamp but an earlier picture id then we
 // assume there has been a jump in the picture id due to some encoder
 // reconfiguration or some other reason. Even though this is not according
 // to spec we can still continue to decode from this frame if it is a
 // keyframe.
 RTC_LOG(LS_WARNING)
     << "A jump in picture id was detected, clearing buffer.";
 ClearFramesAndHistory();
 last_continuous_picture_id = -1;
} else {
 RTC_LOG(LS_WARNING) << "Frame with (picture_id:spatial_id) ("
                     << id.picture_id << ":"
                     << static_cast<int>(id.spatial_layer)
                     << ") inserted after frame ("
                     << last_decoded_frame->picture_id << ":"
                     << static_cast<int>(last_decoded_frame->spatial_layer)
                     << ") was handed off for decoding, dropping frame.";
 return last_continuous_picture_id;
}
}

因此为了能让收到了流顺利播放,发送端和中转的服务端需要确保视频帧的 picture_id, 时间戳正确性。

WebRTC 还有其他很多丢帧逻辑,若网络正常且有持续有接收数据,但是视频卡顿或黑屏无显示,多为流本身的问题。


Ending


本文通过分析 WebRTC 音视频接收端的处理逻辑,列举了一些可以优化首帧显示的点,比如通过调整 local SDP 和 remote SDP 中与影响接收端处理的相关部分,从而避免 Audio/Video ReceiveStream 的重启。另外列举了 Android 解码器对视频宽高的要求、服务端对关键帧请求处理、以及 WebRTC 代码内部的一些丢帧逻辑等多个方面对视频显示的影响。这些点都提高了融云 SDK 视频首帧的显示时间,改善了用户体验。


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

科技前线融云那些事 发表了文章 • 0 个评论 • 127 次浏览 • 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 时代的创新发展。

融云亮相2019音视频技术大会 深度解析 WebRTC 服务架构设计

科技前线融云那些事 发表了文章 • 0 个评论 • 28 次浏览 • 2020-06-16 18:21 • 来自相关话题

“基于 WebRTC 的低延迟直播将会是未来直播行业的主流解决方案!”这是融云联合创始人兼CTO杨攀在 LiveVideoStackCon 2019 音视频技术大会上对于未来行业趋势的判断。2019年8月23 – 24日,LiveVideoStackCon 音... ...查看全部

“基于 WebRTC 的低延迟直播将会是未来直播行业的主流解决方案!”这是融云联合创始人兼CTO杨攀在 LiveVideoStackCon 2019 音视频技术大会上对于未来行业趋势的判断。

2019年8月23 – 24日,LiveVideoStackCon 音视频技术大会在北京举办,本届大会以“多媒体技术赋能新世界”为主题,聚焦音视频、图像等技术在全行业领域的最新探索与应用实践。融云联合创始人兼 CTO 杨攀应邀参会并发表了题为《可扩展的公有云媒体服务设计解析》的精彩演讲。


融云联合创始人兼 CTO 杨攀
在演讲中,杨攀向参会者介绍了融云 WebRTC 在服务端架构设计上的基本理念和思路,并将融云 WebRTC 的设计理念归纳为四点:复用 IM 消息通道;核心服务专注通信、能力服务专注业务;全球互联;部署简单、方便运维。同时在演讲中,杨攀还详细介绍了媒体服务和能力服务相关的架构设计、数据中心内服务集群的设计理念及遍布全球的服务网络。

杨攀在演讲中表示:“融云架构设计的核心理念就是解耦,让各项功能各司其职,避免互相依赖,这样就可以做到简单方便的部署和运维,让故障问题的排查更加方便,极大地降低企业的管理成本和运维成本。”而另一个核心理念是“全球互联”,融云为此专门构建了一张全球通信网络。


融云CTO杨攀解析媒体服务的架构设计
对于融云的媒体服务,杨攀在现场风趣地将其形容为“三无服务”。何谓“三无”?第一个“无”是媒体服务对其他媒体服务无依赖,第二个“无”是其他媒体服务对媒体服务自身无依赖,第三个“无”是每一个媒体服务自身无中心化配置。杨攀表示,这样“三无”化设计的目的同样是为了让系统足够简单易用,方便全球化的部署和运维。

在能力服务层面,杨攀表示,“解耦”作为核心设计理念贯穿在能力服务的设计中。首先是与媒体服务或信令服务解耦,不形成依赖关系,保持独立的架构设计。其次,不靠中央配置控制任何功能,而是通过接口和数据形成调用关系来实现。目前,融云可以为客户提供音视频混流、音视频审核、云端录像、视频标注等多样化的能力。


融云全球网络设计原则
在演讲的最后,杨攀就融云的全球网络设计原则进行了解析。他表示,当前全球网络环境仍亟待提升,特别是在国外,跨区域、跨运营商很容易导致音视频的延时和丢包,在这种客观的现实条件下,对于企业的全球通信能力提出了更高的要求。杨攀表示,融云在全球网络设计上有三个原则:一、客户端就近接入,多链路选择;二、数据中心间同源音视频只有一路级联;三、利用 IaaS 能力,进行中心间级联链路的优化。

目前,融云在全球设立了多个数据中心,并拥有数千个加速节点,覆盖全球所有国家及地区(共 233 个),构建起了一张安全、可靠、低延时、高并发的全球通信网。通过遍布全球的优质接入点,结合融云自研的最优链路调度算法,可将消息快速分发给终端用户,解决因跨国、跨运营商、大规模用户访问而导致的响应慢、丢包高、服务不稳定等问题。


参与嘉宾在融云展位交流
在本次大会上,杨攀将融云在 WebRTC 领域的架构设计理念和思路分享给所有参会者,旨在与业内技术人员进行思维上的交流、启发和碰撞,不断开拓视野、拓宽思路,与全球开发者一道加速音视频领域的创新发展。除了精彩的干货分享外,融云还在大会现场设立了服务展台,大屏实时播放融云产品的 Demo 视频,并由工作人员在现场向感兴趣的参会者介绍融云的产品和技术服务能力。

【关于融云】

融云,安全、可靠的全球互联网通信云服务商,向开发者和企业提供即时通讯和实时音视频通信云服务。iResearch 艾瑞权威数据报告显示,融云即时通讯云市场份额连续多年稳居头位。

融云构建了一张覆盖全球所有国家及地区(共 233 个)的通信云网络,在全球各地设立多个数据中心及数千个加速节点。基于客户业务需求,融云可提供多种部署模式——公有云、私有云、混合云,为全球企业提供稳定的互联网通信云服务。针对企业级用户,融云将业务垂直到各个行业,为社交、直播、金融、交通运输、教育、电商、医疗等多个行业领域推出了针对性解决方案。

融云基于海量业务的技术锤炼,从基础架构到精细化运营,充分体现平台实力;凭借卓越的产品和优质的服务,在开发者规模、行业覆盖率、平台日活跃用户数、日均消息量等方面超越全行业。目前,已有数十万互联网用户及上千家企业级用户通过融云实现了场景化沟通。

【融云分析】WebRTC P2P 连接技术之 STUN 和 ICE 协议解密

科技前线苏道 发表了文章 • 0 个评论 • 29 次浏览 • 2020-06-16 18:16 • 来自相关话题

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

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.2 地址受限锥型

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


1.3 端口受限锥型

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


1.4 对称型

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


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 和消息长度。


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

magic cookie 为固定值 0x2112A442。

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

2.2 STUN 消息类型


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

2.3 STUN 属性

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


(图)STUN 属性
STUN 属性格式:

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

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


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


具体说明如下:

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。


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


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

3. ICE 简介

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


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

3.1 收集候选地址

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

所以有四种候选地址:


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


(图)ICE 端口
3.2 连通检测

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


(图)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)


再根据 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。


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


(图)AGGRESSIVE 提名
3.5 ICE 示例

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


(图)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 为


替换地址后


因为 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。


消息 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 协议 RTC5245 以及 WebRTC 的 P2P 部分的具体实现。

【融云分析】做好 WebRTC 的两大必备要素

科技前线融云那些事 发表了文章 • 0 个评论 • 29 次浏览 • 2020-06-16 18:01 • 来自相关话题

| 什么是 WebRTCWebRTC 是一个可以使我们在浏览器或移动 App 中直接进行音频/视频交流的技术,它可以进行 P2P 文件共享,处理大量音频数据,实现在线视频会议等,WebRTC 使设备能够在平台和浏览器之间传输音频和视频。使用特定的 API ,开... ...查看全部

| 什么是 WebRTC

WebRTC 是一个可以使我们在浏览器或移动 App 中直接进行音频/视频交流的技术,它可以进行 P2P 文件共享,处理大量音频数据,实现在线视频会议等,WebRTC 使设备能够在平台和浏览器之间传输音频和视频。使用特定的 API ,开发人员可以允许他们的用户通过简单的浏览器连接设备,而无需任何额外的插件、扩展或软件安装。这种多功能性使得 WebRTC 成为各种物联网设备开发人员的热门选择。

| WebRTC 的应用前景

从 2G 时代的文字信息传输到 3G 时代的图片传输再到 4G 时代的直播热潮,每个网速时代的变革都将我们的梦想一步步实现;随着 5G 即将到来,更好的上网体验将会极大地推动音视频行业的发展和创新。

WebRTC 也将激活人与人、人与物、物与物之间的信息纽带,解决互联网音视频通信的技术门槛问题,成为应用场景创新的强大技术保障,为社交、监控、视频会议、物联网、在线教育、远程医疗等场景注入新的活力。随之,互联网尤其是移动互联网上基于 WebRTC 的各种应用创新也将层出不穷。

| 如何做好 WebRTC

一款音视频产品通常会包含信令服务、媒体服务、网络服务等几部分;而一款运行稳定、性能出色的 WebRTC 产品,则需要满足以下几个要求。

1、稳定的信令系统

我们需要通过信令来控制 WebRTC ,并且在此基础上构建各种业务逻辑。信令即协调通讯的过程,应用要发起一个音视频通话,通常需要在客户端之间交换如下信息:

1) 会话的信息

2) 设备的能力,编解码、分辨率、码率等

3) 秘钥信息,用于创建安全连接

4) 网络信息,如外部能访问的主机 IP 和端口

5) 传递信息,通过信令来实现业务场景中的通话控制

……


如上图:如果 A 和 B 要发起音视频通话,需要将双方的 SDP 信息做交换,才能建立连接。由此可见信令系统若想保证足够的稳定,连通率、到达率、高并发、高可用等技术指标需全部达标,才能确保 WebRTC 通话的建立和通话过程中的逻辑控制。

2、高可用的媒体服务器

WebRTC 常见的几种模式如下:

1) Mesh 网状结构

通过搭建 Turn/Stun 服务直接发起端到端的 P2P 通话。


优点:不需要搭建 MediaServer 。

缺点:对于多人通话需要每个客户端都跟其他两个端分别建立 P2P 连接,每新增一个客户端,所有的客户端都需要新增一路数据上行,导致客户端上行带宽占用太大。因此,通话人数越多,效果越差,也无法在服务端对视频进行额外处理,如:录制存储回放、实时转码、智能分析、多路合流、转推直播等。

2)MCU

服务端负责把参与者的视频做混流,多人参会每个人只有一个上行视频,同时接收一个下行视频流。


优点:客户端压力较小,带宽消耗小,服务端可以控制下发的视频数据,从而可以发起更多参与者的视频会议。

缺点:服务器资源消耗较大,对服务器的性能要求高,服务器成本高昂。

3)SFU

SFU 的全称是:Selective Forwarding Unit,是一种通过服务器来路由和转发 WebRTC 客户端音视频数据流的方法。 SFU 服务器最核心的特点是把自己“伪装”成一个 WebRTC 的客户端,将一个 Client 端的数据转发到其他多个 Client 端。


优点:对服务器性能要求不高。

缺点:对服务器和客户端带宽要求高。

| 融云音视频的实践

音视频领域飞速发展的今天,融云也通过在音视频领域多年的摸爬滚打,充分借助融云 IM 通道的稳定性和数年来逐步优化的覆盖全球的专有网络优势,打造出了自己的音视频解决方案。

1、信令系统

1)可靠性

融云对分布式 RTC 网络的活用,让信令服务与媒体服务不需要状态同步,媒体中心间不需要状态同步;音视频复用融云即时通讯信令通道,信令服务与媒体服务解耦、无依赖;弱网环境下,消息发送方只要将消息发送到服务器端,服务器端能确保消息不丢、不乱、不重。

2)安全性

基于融云自有知识产权的连接加密技术,可以防止黑客以中间人方式进行数据窃听,数据在传输过程中不可破解, NAV 导航服务与 CMP 连接管理服务的安全算法一致,每个客户端从导航服务获取到加密校验值( SM2 标准),均按照安全算法与所连接的 CMP 服务进行安全协商,针对校验值 CMP 会进行合法性验证( SM3标准),协商的校验值不能在其他 CMP 连接管理服务上使用。消息在传输之前,通过 SM4 对数据进行加密,并且通过加密连接传输将信息发送到发送方所在 CMP 连接管理服务,之后,由发送方所在 CMP 连接管理服务进行解密并将解密后的消息发给消息服务,依据协议内容,由消息服务负责将信息传递给接收方所在 CMP 连接管理服务,而后 CMP 连接管理服务依据接收方的密钥进行信息加密,最后通过加密连接下发信息。

2、MediaServer


1) 全球化部署,低延迟

全球部署多个 MediaServer 数据中心,用户就近接入;跨国网络之间通过专线连接,保证媒体数据传输延迟低。

2) 动态扩展

信令和 MediaServer 完全解耦,随时随地部署,通过监测服务器负载情况可以随着业务量级增长动态横向扩容,保证业务的高可用性。

3) 高质量音视频流

通过高效的处理,提高服务器吞吐量,减少丢包率,通过丢包重传和网络探测机制,提高在弱网环境下的音视频质量和用户体验。

WebRTC