超低延時直播RTS是以WebRTC信令交互方式為基礎(chǔ),借助阿里云直播節(jié)點的全球覆蓋及優(yōu)秀調(diào)度算法能力,實現(xiàn)功能。通過閱讀本文,您可以了解WebRTC標準接入GRTN信令協(xié)議的詳細信息。本文適合具有WebRTC基礎(chǔ)的開發(fā)人員閱讀。

背景信息

阿里云視頻直播服務(wù)(ApsaraVideo Live)為解決使用TCP協(xié)議引起的3~6秒以上延時的問題,提供使用UDP協(xié)議的超低延時直播RTS(Real-time Streaming)增值功能,具備易接入、毫秒級別延遲、千萬級高并發(fā)、高清流暢的直播觀看體驗。RTS產(chǎn)品設(shè)計重視開放、標準的生態(tài)建設(shè),在使用阿里云提供的專用RTS SDK基礎(chǔ)上,還支持自研客戶端以類似WebRTC信令交互方式從直播節(jié)點推拉音視頻流,借助阿里云直播節(jié)點的全球覆蓋及優(yōu)秀調(diào)度算法能力,幫助客戶大規(guī)模實現(xiàn)自主可控方式便利地使用阿里云超低延時直播服務(wù)。

目前GRTN對外開放抗弱網(wǎng)能力。

前提條件

信令交互流程

信令交互圖如下所示:

001

信令交互流程

  1. 客戶端發(fā)送offer請求。
    1. 客戶端本地創(chuàng)建RTCPeerConnection,設(shè)置接收音視頻屬性Stream Direction,并創(chuàng)建offer SDP。
      // 開啟音視頻, recvonly or sendonly
      { offerToReceiveVideo: true, offerToReceiveAudio: true }
    2. 客戶端向直播服務(wù)發(fā)送拉流請求,通過HTTPS POST協(xié)議方式將JSON格式的請求信息發(fā)送至直播服務(wù)。協(xié)議格式請參見信令協(xié)議定義
      • version字段為協(xié)議版本,當(dāng)前版本固定為2。
      • sdk_version字段為SDK版本,您可以自定義該字段。
    3. 生成協(xié)議內(nèi)容后,通過POST方式將信令地址給直播服務(wù)完成信令交互,在請求的JSON包體中包含要拉取的流地址。
      POST /app/streamname?auth=xxx HTTP/1.1
      Host: domain
      Connection: keep-alive
      Content-Length: 2205
      Content-Type: application/json
      說明 信令地址與流地址基本一致,協(xié)議頭不同,如下所示:
      • 信令地址:https://domain/app/streamname?auth=xxx
      • 流地址:artc://domain/app/streamname?auth=xxx
  2. 服務(wù)端SDP Answer響應(yīng)。

    直播服務(wù)端校驗安全性后生成SDP Answer, 節(jié)點信息封裝在響應(yīng)包體中返回給客戶端。協(xié)議格式請參見信令協(xié)議定義

  3. 客戶端ICE建聯(lián)。
    1. 客戶端收到SDP Answer響應(yīng)后,設(shè)置到RTCPeerConnection中。
      peerConnection.setRemoteDescription(new RTCSessionDescription(answer.jsep));
    2. RTCPeerConnection啟動ICE建連流程以及后續(xù)的DTLS流程,媒體通道建立成功后可以獲取到直播服務(wù)輸出的媒體流,實現(xiàn)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);
}
                

信令協(xié)議定義

RTS信令協(xié)議通道為HTTPS(短鏈接),格式為JSON。樣例如下所示:

{
    "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以下省略"
    }
}

播放

  • 播放相關(guān)協(xié)議描述
    表 1. 請求參數(shù)
    參數(shù) 類型 是否必選 描述
    mode string 模式,取值:live。
    version int 協(xié)議版本號,取值:2。
    push_stream string 推流URL。
    pull_streams []object 拉流對象,支持多個拉流。詳情請參見下表。
    sdk_version string SDK版本號。
    jsep.type string SDP類型,取值:offer。
    jsep.sdp string SDP描述。
    表 2. pull_stream參數(shù)
    字段 類型 是否必填 描述
    url string 拉流URL,例如:artc://<拉流地址>
    amsid []string 拉流音頻msid,直播場景取值rts audio
    vmsid []string 拉流視頻msid,直播場景取值rts video
    表 3. 應(yīng)答參數(shù)
    字段 類型 是否必填 描述
    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 以下省略"
        }
    }

    sps-pps-idr-in-keyframe:推薦以下操作,可以避免瀏覽器在弱網(wǎng)場景播放部分直播流的時候出現(xiàn)視頻花屏。

    在H5訂閱流(recvonly)生成offer之后(createOfferOnSuccess)調(diào)用setLocalDescription之前,修改SDP,將H.264視頻屬性中類似下面的行:
    a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
    添加sps-pps-idr-in-keyframe=1,變?yōu)椋?pre class="pre codeblock" id="codeblock-idq-n4d-tf7">a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f;sps-pps-idr-in-keyframe=1

    GRTN會進行響應(yīng),讓瀏覽器開啟本特性。

  • 錯誤處理

    信令請求合法的情況下響應(yīng)200 ,具體的處理結(jié)果需要解析響應(yīng)body的JSON內(nèi)的code屬性。code為HTTP響應(yīng)碼模式,具體定義如下:

    Response:
    {
       "code": 200, // 200-成功 非200-見后續(xù)定義
       "message": "success"  // 非200錯誤碼描述
    }
    表 4. 應(yīng)答參數(shù)
    參數(shù) 類型 描述
    code int 響應(yīng)碼,格式和定義參見下表。
    message string 錯誤描述。
    表 5. 錯誤碼描述
    錯誤碼 描述
    403 鑒權(quán)失敗。
    404 流不存在。
    611 需要客戶端強制降級到TCP播放。
    302 需要客戶端向新的服務(wù)地址發(fā)起信令請求。

推流

  • 推流相關(guān)協(xié)議描述
    表 6. 請求參數(shù)
    參數(shù) 類型 是否必選 描述
    mode string 模式,取值:live。
    version int 協(xié)議版本號,取值:2。
    push_stream string 推流URL。
    sdk_version string SDK版本號。
    jsep.type string SDP類型,取值:offer。
    jsep.sdp string SDP描述。
    表 7. 應(yīng)答參數(shù)
    字段 類型 是否必填 描述
    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":"rtc",
        "push_stream":"artc://host/app/name",
        "jsep":{
            "type":"offer",
            "sdp":"v=0\r\no=- 1385856200224536561 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1 2\r\na=extmap-allow-mixed\r\na=msid-semantic: WMS rts\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111 63 103 104 9 0 8 106 105 13 110 112 113 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:iQyM\r\na=ice-pwd:D3GXKCcUGvW9djaAozff5ppT\r\na=ice-options:trickle\r\na=fingerprint:sha-256 20:50:72:9B:A2:C0:D8:50:AD:D0:EF:A7:62:8F:EF:C3:AB:86:D5:B6:3E:17:22:69:79:5B:CE:E8:42:33:B5:E4\r\na=setup:actpass\r\na=mid:0\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=sendrecv\r\na=msid:rts audio\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=rtcp-fb:111 transport-cc\r\na=rtcp-fb:111 nack\r\na=fmtp:111 minptime=10;useinbandfec=1\r\na=rtpmap:63 red/48000/2\r\na=fmtp:63 111/111\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:110 telephone-event/48000\r\na=rtpmap:112 telephone-event/32000\r\na=rtpmap:113 telephone-event/16000\r\na=rtpmap:126 telephone-event/8000\r\na=ssrc:3411287802 cname:s4eR7OuKnnPL0vKS\r\na=ssrc:3411287802 msid:rts audio\r\na=ssrc:3411287802 mslabel:rts\r\na=ssrc:3411287802 label:audio\r\nm=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 127 121 125 107 108 109 124 120 123 119 35 36 41 42 114 115 116 117 118\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:iQyM\r\na=ice-pwd:D3GXKCcUGvW9djaAozff5ppT\r\na=ice-options:trickle\r\na=fingerprint:sha-256 20:50:72:9B:A2:C0:D8:50:AD:D0:EF:A7:62:8F:EF:C3:AB:86:D5:B6:3E:17:22:69:79:5B:CE:E8:42:33:B5:E4\r\na=setup:actpass\r\na=mid:1\r\na=extmap:14 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:13 urn:3gpp:video-orientation\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\r\na=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\r\na=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\r\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\na=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\na=sendrecv\r\na=msid:rts video\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:96 VP8/90000\r\na=rtcp-fb:96 goog-remb\r\na=rtcp-fb:96 transport-cc\r\na=rtcp-fb:96 ccm fir\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=96\r\na=rtpmap:98 VP9/90000\r\na=rtcp-fb:98 goog-remb\r\na=rtcp-fb:98 transport-cc\r\na=rtcp-fb:98 ccm fir\r\na=rtcp-fb:98 nack\r\na=rtcp-fb:98 nack pli\r\na=fmtp:98 profile-id=0\r\na=rtpmap:99 rtx/90000\r\na=fmtp:99 apt=98\r\na=rtpmap:100 VP9/90000\r\na=rtcp-fb:100 goog-remb\r\na=rtcp-fb:100 transport-cc\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 nack pli\r\na=fmtp:100 profile-id=2\r\na=rtpmap:101 rtx/90000\r\na=fmtp:101 apt=100\r\na=rtpmap:127 H264/90000\r\na=rtcp-fb:127 goog-remb\r\na=rtcp-fb:127 transport-cc\r\na=rtcp-fb:127 ccm fir\r\na=rtcp-fb:127 nack\r\na=rtcp-fb:127 nack pli\r\na=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f\r\na=rtpmap:121 rtx/90000\r\na=fmtp:121 apt=127\r\na=rtpmap:125 H264/90000\r\na=rtcp-fb:125 goog-remb\r\na=rtcp-fb:125 transport-cc\r\na=rtcp-fb:125 ccm fir\r\na=rtcp-fb:125 nack\r\na=rtcp-fb:125 nack pli\r\na=fmtp:125 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f\r\na=rtpmap:107 rtx/90000\r\na=fmtp:107 apt=125\r\na=rtpmap:108 H264/90000\r\na=rtcp-fb:108 goog-remb\r\na=rtcp-fb:108 transport-cc\r\na=rtcp-fb:108 ccm fir\r\na=rtcp-fb:108 nack\r\na=rtcp-fb:108 nack pli\r\na=fmtp:108 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\r\na=rtpmap:109 rtx/90000\r\na=fmtp:109 apt=108\r\na=rtpmap:124 H264/90000\r\na=rtcp-fb:124 goog-remb\r\na=rtcp-fb:124 transport-cc\r\na=rtcp-fb:124 ccm fir\r\na=rtcp-fb:124 nack\r\na=rtcp-fb:124 nack pli\r\na=fmtp:124 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f\r\na=rtpmap:120 rtx/90000\r\na=fmtp:120 apt=124\r\na=rtpmap:123 H264/90000\r\na=rtcp-fb:123 goog-remb\r\na=rtcp-fb:123 transport-cc\r\na=rtcp-fb:123 ccm fir\r\na=rtcp-fb:123 nack\r\na=rtcp-fb:123 nack pli\r\na=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f\r\na=rtpmap:119 rtx/90000\r\na=fmtp:119 apt=123\r\na=rtpmap:35 H264/90000\r\na=rtcp-fb:35 goog-remb\r\na=rtcp-fb:35 transport-cc\r\na=rtcp-fb:35 ccm fir\r\na=rtcp-fb:35 nack\r\na=rtcp-fb:35 nack pli\r\na=fmtp:35 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=4d001f\r\na=rtpmap:36 rtx/90000\r\na=fmtp:36 apt=35\r\na=rtpmap:41 AV1/90000\r\na=rtcp-fb:41 goog-remb\r\na=rtcp-fb:41 transport-cc\r\na=rtcp-fb:41 ccm fir\r\na=rtcp-fb:41 nack\r\na=rtcp-fb:41 nack pli\r\na=rtpmap:42 rtx/90000\r\na=fmtp:42 apt=41\r\na=rtpmap:114 H264/90000\r\na=rtcp-fb:114 goog-remb\r\na=rtcp-fb:114 transport-cc\r\na=rtcp-fb:114 ccm fir\r\na=rtcp-fb:114 nack\r\na=rtcp-fb:114 nack pli\r\na=fmtp:114 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f\r\na=rtpmap:115 rtx/90000\r\na=fmtp:115 apt=114\r\na=rtpmap:116 red/90000\r\na=rtpmap:117 rtx/90000\r\na=fmtp:117 apt=116\r\na=rtpmap:118 ulpfec/90000\r\na=ssrc-group:FID 4075787827 945566690\r\na=ssrc:4075787827 cname:s4eR7OuKnnPL0vKS\r\na=ssrc:4075787827 msid:rts video\r\na=ssrc:4075787827 mslabel:rts\r\na=ssrc:4075787827 label:video\r\na=ssrc:945566690 cname:s4eR7OuKnnPL0vKS\r\na=ssrc:945566690 msid:rts video\r\na=ssrc:945566690 mslabel:rts\r\na=ssrc:945566690 label:video\r\nm=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\nc=IN IP4 0.0.0.0\r\na=ice-ufrag:iQyM\r\na=ice-pwd:D3GXKCcUGvW9djaAozff5ppT\r\na=ice-options:trickle\r\na=fingerprint:sha-256 20:50:72:9B:A2:C0:D8:50:AD:D0:EF:A7:62:8F:EF:C3:AB:86:D5:B6:3E:17:22:69:79:5B:CE:E8:42:33:B5:E4\r\na=setup:actpass\r\na=mid:2\r\na=sctp-port:5000\r\na=max-message-size:262144\r\n"
        }
    }
    
    Response:
    {
        "trace_id":"...",
        "code":200,
        "jsep":{
            "type":"answer",
            "sdp":"v=0\r\no=- 1657264764 2 IN IP4 127.0.0.1 以下省略"
        }
    }
                        
    上述信令中,push_stream表明了推流的url, 與RTMP推流是類似的。需注意:
    • SDP中需要指定好msid, GRTN使用msid作為媒體的唯一標識。
    • 推流的媒體不支持協(xié)商,客戶端指定的同一個媒體msid ,只允許發(fā)送一種編碼,GRTN不進行選擇。目前GRTN支持AAC、OPUS、H.264和H.265。
    • audioaudio1audio2
    • videovideo1video2
  • 錯誤處理

    信令請求合法的情況下響應(yīng)200 ,具體的處理結(jié)果需要解析響應(yīng)body的JSON內(nèi)的code屬性。code為HTTP響應(yīng)碼模式,具體定義如下:

    Response:
    {
       "code": 200, // 200-成功 非200-見后續(xù)定義
       "message": "success"  // 非200錯誤碼描述
    }
    表 8. 應(yīng)答參數(shù)
    參數(shù) 類型 描述
    code int 響應(yīng)碼,格式和定義參見下表。
    message string 錯誤描述。
    表 9. 錯誤碼描述
    錯誤碼 描述
    403 鑒權(quán)失敗。
    611 需要客戶端強制降級到TCP。
    302 需要客戶端向新的服務(wù)地址發(fā)起信令請求。

增強的SDP

在信令交互中,SDP用來描述媒體信息。通用的SDP協(xié)商是基于RFC 4566展開的,阿里云RTS在其基礎(chǔ)上擴展出了更多豐富的語義,兼容直播行業(yè)的特點,支持更多的音視頻封裝和通信協(xié)議,突破了WebRTC僅支持音頻OPUS、不支持視頻B幀等的窘境,滿足了如今流媒體業(yè)界日益擴大的協(xié)議族。

推拉流支持AAC音頻

RTS支持傳輸任何能在RTMP中傳輸?shù)腁AC格式的音頻,包括AAC-LC、HE-AACv1和HE-AACv2。

RTS支持以LATM格式進行AAC音頻傳輸。LATM可根據(jù)傳輸中的音頻是否自帶音頻編碼信息來決定是帶內(nèi)(每個音頻都發(fā))或帶外(只發(fā)一次)音頻編碼信息,即由Audio Mux Element中的muxconfigPresent決定AudioSpecificConfig是帶內(nèi)或帶外傳輸。因此,LATM相對ADTS更靈活,其AudioSpecificConfig如果保持不變,則可以通過SDP會話先傳輸StreamMuxConfig(AudioSpecificConfig)信息。

  • 推流支持AAC音頻

    支持offer SDP中攜帶AAC信息告知服務(wù)端所推音頻格式。另外,也支持通過在FMTP中添加config=StreamMuxConfig(其由推流AudioSpecificConfig信息組裝而來),將AudioSpecificConfig信息攜帶給服務(wù)端,生成AAC Header。

    offer SDP:
    a=rtpmap:125 MP4A-LATM/48000/2
    a=fmtp:125 config=4000232000;cpresent=0;object=2;profile-level-id=1
  • 拉流支持AAC音頻

    在信令交互階段,RTS會解析推流側(cè)音頻編碼信息,并在協(xié)商響應(yīng)中返回對應(yīng)的信息。如下所示:

    offer SDP answer SDP
    AAC-LC HE-AACv1 HE-AACv2
    m=audio 9 UDP/RTP/AVPF 120 96 
    a=rtpmap:120 MP4A-LATM/44100/2   
    AudioSpecificConfig = 0x1210
    AudioSpecificConfig = 2b920800
    AudioSpecificConfig = eb8a0800
    a=rtpmap:120 MP4A-LATM/44100/2
    a=fmtp:120 cpresent=0;profile-level-id=1;object=2;config=400024203fc0
    a=rtpmap:120 MP4A-LATM/44100/2 
    a=fmtp:120 cpresent=0;profile-level-id=1;object=2;config=4000572410003fc0;SBR-enabled=1
    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

    此處,通過在answer SDP音頻MP4A-LATM的fmtp中添加SBR-enabled=1表示AAC-HE,添加SBR-enabled=1PS-enabled=1表示HE-AACv2。由于從AAC-LC到HE-AACv2有技術(shù)遞進關(guān)系,因此在表示fmtp時,遞進地增加SBR、PS的標識來表示不同的AAC格式。此外,在fmtp中添加config=StreamMuxConfig,其由推流AudioSpecificConfig信息組裝而來,具體的描述了音頻編碼的各種參數(shù)信息,客戶端可以各取所需。

    002

推拉流支持H.265視頻

  • 推流支持H.265視頻

    支持offer SDP中攜帶H.265信息告知服務(wù)端所推視頻格式。

    Offer SDP:
    a=rtpmap:102 H265/90000 
  • 拉流支持H.265視頻

    在拉流的信令交互階段,服務(wù)端會獲取源流的視頻編碼信息(H.264、H.265等),并在依據(jù)此進行協(xié)商。

    offer SDP answer SDP
    a=rtpmap:102 H265/90000
    a=rtpmap:122 H265/90000
    a=fmtp:122

推拉流支持帶B幀視頻

  • 推流支持B幀

    支持推流源流中攜帶B幀。

  • 拉流支持B幀

    在信令交互階段,客戶端可以在offer SDP中增加字段標識其是否支持解析B幀視頻。例如:在視頻fmtp中增加BFrame-enabled = 1標識以表示支持B幀,此時,RTP timestamp = PTS,sequence number遞增,正常情況下客戶端按照sequence number解碼即可。如果不支持B幀,RTS可以對視頻源流進行轉(zhuǎn)碼,去掉B幀。

    在帶B幀的情況下,RTP timestamp = PTS,sequence number遞增,正常情況下客戶端按照sequence number解碼即可。

    此外,服務(wù)端還支持額外返回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給予客戶端充分的表達能力,將決定權(quán)下放給客戶,讓其決定是否接受視頻帶B幀,以及是否需要額外的CTS信息。以更通用的方式構(gòu)建通信能力也是RTS的初衷。

offer SDP片段及拉流抓包示例如下所示:

Offer SDP片段004

推流支持通過信令攜帶metadata

RTMP推流會通過RTMP metadata攜帶相關(guān)元信息,可用于給推流回調(diào)、拉流客戶端提供元信息。由于WebRTC傳輸本身沒有metadata,RTS支持通過在信令中攜帶額外信息,從而在推流源流中生成metadata。

在推流信令body中添加metadata字段:

{
    "version":2,
    "sdk_version":"0.0.1",
    "mode":"rtc",
    "push_stream":"artc://host/app/name",
    "jsep":{
        "type":"offer",
        "sdp":"..."
    },
    "metadata":{
        "framerate":"20",
        "platform":"iOS",
        "audiodatarate":"200",
        "videodatarate":"2000"
    }
}

MSID相關(guān)概念

關(guān)于MSID詳細信息,請參見The Msid Mechanism。請重點關(guān)注以下內(nèi)容:Msid