本文介绍RTS信令交互流程、信令协议定义和增强的SDP。

说明 本文适合有WebRTC基础的开发人员阅读。

背景描述

使用TCP协议会引起3秒~6秒以上的延时,为解决此问题,阿里云视频直播提供了增值功能——使用UDP协议的低延时直播(RTS,Real-time Streaming)功能。

优势
  • 易接入、毫秒级别延迟、千万级高并发、高清流畅的直播观看体验。
  • RTS产品设计重视开放、标准的生态建设。

    在使用阿里云提供的专用RTS SDK基础上,还支持自研客户端以类似WebRTC信令交互方式从直播节点推拉音视频流,借助阿里云直播节点的全球覆盖及优秀调度算法能力,帮助客户实现自主可控方式便利地使用阿里云大规模低延迟直播服务。

前提条件

  • 您已开通阿里云视频直播服务。具体操作,请参见开通服务
  • 您已开通低延时直播RTS服务。具体操作,请参见使用指南
  • 域名已配置HTTPS证书。具体操作,请参见配置HTTPS安全加速

信令交互流程

信令交互流程
  1. 客户端发送Offer请求
    1. 客户端本地创建RTCPeerConnection,设置接收音视频属性Stream Direction,并创建offer SDP。
      // 开启音视频, recvonly or sendonly
      
      { offerToReceiveVideo: true, offerToReceiveAudio: true }
    2. 客户端向直播服务发送拉流请求,通过HTTPS POST方式将JSON格式的请求信息发送至直播服务。
      协议格式请参见 信令协议定义
      • version字段为协议版本,当前版本固定为2。
      • sdk_version字段为SDK版本,用户可以自定义该字段。
    3. 生成协议内容后,通过信令地址POST给直播服务完成信令交互,在请求的JSON包体中表明要拉取的流地址。信令地址与媒体地址基本一致,协议头不同。
      • 信令地址如:https://domain/app/streamname?auth=xxx
      • 流地址如:artc://domain/app/streamname?auth=xxx
      POST /app/streamname?auth=xxx HTTP/1.1
      Host: domain
      Connection: keep-alive
      Content-Length: 2205
      Content-Type: application/json
  2. 服务端Answer响应

    直播服务端校验安全性后生成SDP answer, 节点信息封装在响应包体中返回给客户端。协议格式请参见信令协议定义

  3. 客户端ICE建联
    1. 客户端收到SDP Answer响应后,设置到RTCPeerConnection中。
      peerConnection.setRemoteDescription(new RTCSessionDescription(answer.jsep));
    2. RTCPeerConnection启动ICE建连流程以及后续的DTLS流程,媒体通道建立成功后可以获取到直播服务输出的媒体流,实现WebRTC标准接入拉流播放。
  4. 断开连接
    客户端需要断开连接以停止推流或者播放时,使用DTLS的Alert消息表达。 断开连接
H5 Demo示例
// Create peer connection and local offer sdp.
peerConnection = new RTCPeerConnection();
peerConnection.onicecandidate = iceCandidateCallback;
peerConnection.ontrack = remoteStreamCallback;
peerConnection.createOffer({ offerToReceiveVideo: true, offerToReceiveAudio: true })
      .then(signaling_pull).catch(errorHandler);


// CDN live post pull stream request.
function signaling_pull(offer_sdp) {
  console.log('local offer sdp', offer_sdp);

  peerConnection.setLocalDescription(offer_sdp).then(function() {
    // Get pull stream url.
    var stream_url = $("#stream_url").val();
    console.log("stream url:" , stream_url);

    // Add sdk and protocol versions.
    var protocol_version = 2;
    var sdk_version = "0.0.1";

    $.ajax({url: stream_url, data: JSON.stringify({
          mode: "live",
          version: protocol_version,
          sdk_version: sdk_version,
          jsep:description,
      }),
      type: "post",
      success:function(result){
          var signal = JSON.parse(result);
          peerConnection.setRemoteDescription(new RTCSessionDescription(signal.jsep)).then(function() {
              console.log("get remote answer sdp: ", signal.jsep.sdp);
          }).catch(errorHandler);
      }});
  }).catch(errorHandler);
}

信令协议定义

  • 协议通道:HTTPS,短连接。
  • 协议格式:JSON。
  • 协议描述
    • 请求参数
      参数 类型 是否必选 描述 取值范围
      mode string 模式:直播。 live
      version int 协议版本号。 2
      push_stream string 推流URL。 文本
      pull_streams []object 拉流对象,支持多个拉流。 请参见pull_stream参数
      sdk_version string SDK版本号。 文本
      jsep.type string sdp类型:offer。 offer
      jsep.sdp string sdp描述。
      表 1. pull_stream参数
      字段 类型 是否必填 描述
      url string 拉流URL,artc://
      amsid []string 拉流音频msid,直播场景填写一个成员“rts audio”。
      vmsid []string 拉流视频msid,直播场景填写一个成员“rts video”。
    • 应答参数
      字段 类型 是否必需 描述
      code int 正确返回200,错误参考错误处理。
      trace_id string 全局唯一请求标识ID。由CDN生成,请尽量做好保存,用于对请求进行定位和问题排查。
      jsep.type string sdp类型:answer。
      jsep.sdp string 直播CDN回源拉流生成SDP。
  • 示例
    • 请求示例
      Request:
      {
          "version":2,
          "sdk_version":"0.0.1",
          "mode":"live",
          "pull_streams":[
              {
                  "url":"artc://your.domain.com/live/testname",
                  "amsid":[
                      "rts audio"
                  ],
                  "vmsid":[
                      "rts video"
                  ]
              }
          ],
          "jsep":{
              "type":"offer",
              "sdp":"v=0\n\ro=- 6839248142876176651 2 IN IP4 127.0.0.1\n\rs=-\n\r以下省略"
          }
      }
    • 应答示例
      Response:
      {
          "trace_id":"2_1591173296_101.227.0.169_702080732320_dec327eb6eed0e0b07b349c8a5653eca",
          "code":200,
          "jsep":{
              "type":"answer",
              "sdp":"v=0\r\no=- 1591173291 2 IN IP4 127.0.0.1\n\r 以下省略"
          }
      }
  • 错误处理
    信令请求合法的情况下响应200 ,具体的处理结果需要解析响应body的JSON内的code属性。code为HTTP响应码模式,具体定义如下:
    Response:
    {
       "code": 200, // 200-成功 非200-见后续定义
       "message": "success"  // 非200错误码描述
    }
    表 2. 应答参数
    参数 类型 描述
    code int 响应码,格式和定义请参见错误码描述
    message string 错误描述。
    表 3. 错误码描述
    错误码 描述
    200 success,成功。
    403 鉴权失败。
    404 流不存在。
    611 需要客户端强制降级到TCP播放。
    302 需要客户端向新的服务地址发起信令请求。

增强的SDP

在信令交互中,SDP用来描述媒体信息。通用的SDP协商是基于RFC 4566展开的,阿里RTS在其基础上扩展出了更多丰富的语义,兼容直播行业的特点,足以支持更多的音视频封装、通信协议,突破了WebRTC仅支持音频OPUS、不支持视频B帧等的窘境,从而满足如今流媒体业界日益扩大的协议族。

  • 支持AAC音频

    RTS支持传输任何能在RTMP中传输的AAC格式的音频,包括 AAC-LC、AAC-HE、AAC-HEv2。AAC格式请参见ISO IEC 14496-3。RTS支持以LATM格式进行AAC音频传输,LATM可根据传输中的音频是否自带音频编码信息来决定是带内(每个音频都发)还是带外(只发一次)音频编码信息。

    具体:由Audio Mux Element中的muxconfigPresent决定AudioSpecificConfig是带内/带外传输。因此LATM相对ADTS更灵活,其AudioSpecificConfig若保持不变,则可以通过SDP会话先传输StreamMuxConfig(AudioSpecificConfig)信息。LATM请参见Application-Bulletin_AAC-Transport-Format

    在信令交互阶段,RTS会解析推流侧音频编码信息,并在协商响应中返回对应的信息。

    Offer SDP:
    m=audio 9 UDP/RTP/AVPF 120 96 
    a=rtpmap:120 MP4A-LATM/44100/2  
    • Case1:AAC-LC
      • AudioSpecificConfig = 0x1210
      • Answer SDP:
        a=rtpmap:120 MP4A-LATM/44100/2
        a=fmtp:120 cpresent=0;profile-level-id=1;object=2;config=400024203fc0
    • Case2:AAC-HE
      • AudioSpecificConfig = 2b920800
      • Answer SDP:
        a=rtpmap:120 MP4A-LATM/44100/2 
        a=fmtp:120 cpresent=0;profile-level-id=1;object=2;config=4000572410003fc0;SBR-enabled=1
    • Case3:AAC-HEv2
      • AudioSpecificConfig = eb8a0800
      • Answer SDP:
        a=rtpmap:120 MP4A-LATM/44100/2 
        a=fmtp:120 cpresent=0;object=2;profile-level-id=1;config=4001d71410003fc0;PS-enabled=1;SBR-enabled=1
    AAC

    REF:AAC / HE-AAC Parameters

    此处,我们通过在Answer SDP音频MP4A-LATM fmtp的fmtp中添加SBR-enabled=1表示AAC-HE,添加SBR-enabled=1PS-enabled=1表示AAC-HEv2。如上图,由于从AAC-LC到AAC-HEv2有技术递进关系,因此在fmtp的表示上,我们也递进地增加SBR、PS的标识来表示不同的AAC格式。此外,在fmtp中添加config=StreamMuxConfig,其由推流AudioSpecificConfig信息组装而来,则更具体地描述了音频编码的各种参数信息,客户端可以各取所需。

  • 支持H.265视频

    RTS会解析推流侧视频编码信息(H.264、H.265),在Answer SDP中根据推流侧实际的编码方式,返回H264H265

    Case:H.265
    • Offer SDP:
      a=rtpmap:102 H265/90000
    • Answer SDP:
      a=rtpmap:122 H265/90000
      a=fmtp:122
  • 支持带B帧视频
    在信令交互阶段,客户端可以在Offer SDP中增加字段来标识其是否支持解析B帧视频。
    • 例如在视频fmtp中增加BFrame-enabled = 1标识以表示支持B帧。
    • 若不支持B帧,RTS可以对视频源流进行转码,去掉B帧。

    在带B帧的情况下,RTP timestamp = PTS,sequence number递增,正常情况下客户端按照sequence number解码即可。

    此外,RTS还支持额外返回CTS扩展头以支持需要精确计算DTS的客户端(PTS=DTS+CTS),若Offer SDP中带有a=extmap:{$id} uri:webrtc:rtc:rtp-hdrext:video:CompositionTime,RTS会在每一帧视频的第一个RTP包上增加extension identifier = {$id}的cts扩展头,id由客户的Offer SDP来决定。

    RTS给予客户端充分的表达能力,将决定权下放给客户,让其决定是否接受视频带B帧,以及是否需要额外的CTS信息。以更通用的方式构建通信能力也是RTS的初衷。

    Offer SDP片段: Offer SDP片段
    拉流抓包: 拉流抓包

关于MSID的关键概念描述

请阅读The Msid Mechanism

摘选如下内容:

This document defines a new SDP [RFC4566] media-level "msid" attribute. This new attribute allows endpoints to associate RTP streams that are described in different media descriptions with the same MediaStreams as defined in [W3C.WD-webrtc-20160531] carry an identifier for each MediaStreamTrack in its "appdata" field.

The value of the "msid" attribute consists of an identifier and an optional "appdata" field.

The name of the attribute is "msid".

The value of the attribute is specified by the following ABNF [RFC5234] grammar:

  • msid-value = msid-id [ SP msid-appdata ]
  • msid-id = 1*64token-char ; see RFC 4566
  • msid-appdata = 1*64token-char ; see RFC 4566

An example msid value for a group with the identifier "examplefoo" and application data "examplebar" might look like this:

msid:examplefoo examplebar

The identifier is a string of ASCII characters that are legal in a "token", consisting of between 1 and 64 characters.

Application data (msid-appdata) is carried on the same line as the identifier, separated from the identifier by a space.

The identifier (msid-id) uniquely identifies a group within the scope of an SDP description.