Skip to content

Instantly share code, notes, and snippets.

@voluntas
Last active April 6, 2024 12:00
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save voluntas/088bc3cc62094730647b to your computer and use it in GitHub Desktop.
Save voluntas/088bc3cc62094730647b to your computer and use it in GitHub Desktop.
Firefox の Simulcast 実装について

Firefox の Simulcast 実装について

こちらの資料は古いので WebRTC Simulcast コトハジメ をどうぞ。

Simulcast とは

WebRTC の Simulcast という仕組みは、複数の品質で映像を配信する仕組みのことです。

P2P で必要かどうかというと、必要ではありません。Simulcast はクライアント・サーバモデル、さらに SFU モデルでの利用を前提としています。

配信者は複数の品質でサーバに配信します。例えば 300kbps と 500kbps と 800kbps という感じです。3 種類の画質で変換するので、もちろんその分配信側には負担がかかります。

では、この Simulcast のメリットですが、視聴側にあります。視聴側の回線が細かったりする場合サーバは品質の低い 300kbps の配信します。 それとは別に安定して視聴できている人には 800kbps で配信します。

WebRTC SFU は映像を転送するだけしかできないため、このような「配信側への負担」を強いる仕組み採用するしかありません。

Simulcast の図が付いた説明を書いた記事があるので、こちらを御覧ください。

WebRTC を利用した配信の現実 – V – Medium

Chrome と Firefox の違い

Simulcast ですが、Chrome と Firefox では取っているアプローチが異なります。

  • Chrome は Google 独自の仕様
  • Firefox は IETF や W3C 沿った仕様

そのため、もし Simulcast に対応する場合はブラウザ間の差異を吸収する必要があります。

ただ、Firefox は正しい方向に進んでいます。これは忘れないでください。

Chrome のスタンス

ここはうろ覚えを文章にしているため、信頼性はありません

Chrome は Firefox 、つまり正式な Simulcast の実装からははみ出ています。

SDP に独自の拡張を入れることで動作するようになります。これはクライアント側で SDP の書き換えをする必要があります。

a=x-google-flag:conference
a=ssrc-group:SIM 1 2 3
a=ssrc:1 
a=ssrc:2
a=ssrc:3
a=ssrc-group:FID 1 4
a=ssrc:1 
a=ssrc:4
a=ssrc-group:FID 2 5
a=ssrc:2 
a=ssrc:5
a=ssrc-group:FID 3 6
a=ssrc:3 
a=ssrc:6

さらに、Chrome 側は正式実装には興味はほとんどないようです。実装自体も対応する雰囲気も見せていません。 理由として、彼らは VP9/SVC に力を入れていることが上げられます。これについては、ぐぐってください。

Firefox の Simulcast 実装について

a=rid と a=simulcast を利用します。

a=rid はエンコードの仕様を指定できます。つまり品質を指定する仕組みです。

a=simulcast はそれらの rid をまとめる仕組みです。

a=rid:0 send max-width=1280;max-height=720;max-fps=15
a=rid:1 send max-width=1280;max-height=720;max-fps=30
a=rid:2 recv max-width=1280;max-height=720;max-fps=30
a=rid:5 send max-width=640;max-height=360;max-fps=15
a=rid:6 send max-width=320;max-height=180;max-fps=15
a=simulcast: send rid=0;1;5;6 recv rid=2

自分はこの種類を配信する、受信はこれをくれという感じですね。これは全員が Simulcast で配信している前提の例です。

まとめ

Simulcast はクライアント・サーバモデルでさらに SFU を利用した場合で、さらにサーバ側が視聴側の帯域推定を行える場合のみ有効なモデルです。

かなり限定的なモデルのため、各ブラウザはあまり積極的ではなかったのですが、ここにきて Firefox が頑張っています。

少し気にしておいてもいいかもしれません。

サンプル

Simulcast な SDP を生成するためのサンプルです。コードが汚いのは気にしないでください。

var pc = new RTCPeerConnection({});

var sender;
var parameters;

navigator.mediaDevices.enumerateDevices()
.then(function (devices) {
  return navigator.mediaDevices.getUserMedia({audio: false, video: true})
})
.then(function (stream) {
  console.log(stream);
  pc.addTrack(stream.getVideoTracks()[0], stream);
  sender = pc.getSenders()[0];
  console.log(sender);
  parameters = sender.getParameters();
  console.log(parameters);
  sender.setParameters({encodings: [{ rid: "spam", active: true, priority: "high", maxBitrate: 40000 },
                                    { rid: "egg", active: true, priority: "medium", maxBitrate: 10000 }]})
  
  pc.createOffer()
  .then(function (offer) {
      console.log(offer.sdp);
  })
})
.catch(function (error) {
});

出力される SDP

v=0
o=mozilla...THIS_IS_SDPARTA-57.0.1 4439473149147144035 0 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 2C:74:50:1B:47:76:57:E0:C1:D8:D3:F1:76:52:1E:E8:C9:24:37:22:96:34:7A:07:03:9F:36:29:7F:A2:B4:AF
a=group:BUNDLE sdparta_0
a=ice-options:trickle
a=msid-semantic:WMS *
m=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97
c=IN IP4 0.0.0.0
a=sendrecv
a=extmap:1 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
a=fmtp:120 max-fs=12288;max-fr=60
a=fmtp:121 max-fs=12288;max-fr=60
a=ice-pwd:53e694529986500711443aa9fac84011
a=ice-ufrag:7939d9ba
a=mid:sdparta_0
a=msid:{5ba51dcf-0879-cc4d-8ca5-dc64e611bf2a} {1b1f5d70-ede8-9f4a-8e1c-81036454189e}
a=rid:spam send
a=rid:egg send
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=rtcp-fb:120 goog-remb
a=rtcp-fb:121 nack
a=rtcp-fb:121 nack pli
a=rtcp-fb:121 ccm fir
a=rtcp-fb:121 goog-remb
a=rtcp-fb:126 nack
a=rtcp-fb:126 nack pli
a=rtcp-fb:126 ccm fir
a=rtcp-fb:126 goog-remb
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=rtcp-fb:97 goog-remb
a=rtcp-mux
a=rtpmap:120 VP8/90000
a=rtpmap:121 VP9/90000
a=rtpmap:126 H264/90000
a=rtpmap:97 H264/90000
a=setup:actpass
a=simulcast: send rid=spam;egg
a=ssrc:4039161908 cname:{6098ff0c-bca1-e740-a72a-e3db492212ec}
a=ssrc:4029456389 cname:{6098ff0c-bca1-e740-a72a-e3db492212ec}

資料

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment