Help us understand the problem. What is going on with this article?

peer.js(SkyWay版)でH.264によるビデオチャットを行う

More than 3 years have passed since last update.

はじめに

Google ChromeがM52からH.264サポートを開始しました。すでに対応しているFirefoxと合わせて、やっと利用できる環境が整ってきました。しかし、普通にChromeやFirefoxを利用してもH.264は選択してくれません。WebRTCではシグナリングの過程で、SDPというプロトコルを利用して、ブラウザ同士しゃべることができるコーデックを列挙し、予め設定された優先度に従って最適な物を選択しているからです。

この記事ではSDPを書き換えて、強制的に H.264 で繋がせる方法を解説します。検証などに役立てば幸いです。

SDPについて

Chrome(52.0.2743.116)で生成したSDP

v=0
o=- 7873620119917935879 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS bYvp3dKb7ZtFACFh5eBeicol5WcOcpaEr5UB
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:Xcn23/VduEyHSDiF
a=ice-pwd:bVgn5UOhyAjHWySy9C0otLmi
a=fingerprint:sha-256 47:6D:93:03:82:4A:22:6F:A2:65:4E:26:7E:D9:ED:0E:51:54:8F:D8:EE:DF:62:C1:36:E4:0C:97:49:32:BE:C3
a=setup:actpass
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=sendrecv
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:126 telephone-event/8000
a=ssrc:3891783014 cname:W1HJvf2XgnidpBC3
a=ssrc:3891783014 msid:bYvp3dKb7ZtFACFh5eBeicol5WcOcpaEr5UB 3f5313a0-d017-44ba-b677-4a8fdbb02931
a=ssrc:3891783014 mslabel:bYvp3dKb7ZtFACFh5eBeicol5WcOcpaEr5UB
a=ssrc:3891783014 label:3f5313a0-d017-44ba-b677-4a8fdbb02931
m=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96 97 99 98
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:Xcn23/VduEyHSDiF
a=ice-pwd:bVgn5UOhyAjHWySy9C0otLmi
a=fingerprint:sha-256 47:6D:93:03:82:4A:22:6F:A2:65:4E:26:7E:D9:ED:0E:51:54:8F:D8:EE:DF:62:C1:36:E4:0C:97:49:32:BE:C3
a=setup:actpass
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=sendrecv
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtpmap:101 VP9/90000
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 goog-remb
a=rtcp-fb:101 transport-cc
a=rtpmap:107 H264/90000
a=rtcp-fb:107 ccm fir
a=rtcp-fb:107 nack
a=rtcp-fb:107 nack pli
a=rtcp-fb:107 goog-remb
a=rtcp-fb:107 transport-cc
a=fmtp:107 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=101
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=107
a=rtpmap:98 rtx/90000
a=fmtp:98 apt=116
a=ssrc-group:FID 4217613779 2917256657
a=ssrc:4217613779 cname:W1HJvf2XgnidpBC3
a=ssrc:4217613779 msid:bYvp3dKb7ZtFACFh5eBeicol5WcOcpaEr5UB 7a0e0d0a-5d70-4efc-b21a-9fa55e1167bb
a=ssrc:4217613779 mslabel:bYvp3dKb7ZtFACFh5eBeicol5WcOcpaEr5UB
a=ssrc:4217613779 label:7a0e0d0a-5d70-4efc-b21a-9fa55e1167bb
a=ssrc:2917256657 cname:W1HJvf2XgnidpBC3
a=ssrc:2917256657 msid:bYvp3dKb7ZtFACFh5eBeicol5WcOcpaEr5UB 7a0e0d0a-5d70-4efc-b21a-9fa55e1167bb
a=ssrc:2917256657 mslabel:bYvp3dKb7ZtFACFh5eBeicol5WcOcpaEr5UB
a=ssrc:2917256657 label:7a0e0d0a-5d70-4efc-b21a-9fa55e1167bb
  • m=video の最後に並んでいる数値は利用可能なコーデックの番号である。左に行くほど優先度が高い
  • a=rtpmap:xx / a=fmtp:xx のxxは上記のコーデック番号と紐付いている

Firefox(48.0.3)

v=0
o=mozilla...THIS_IS_SDPARTA-48.0.2 3802126275164462711 0 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 29:A1:9A:33:9C:E3:2A:B4:44:1F:A3:43:E0:63:F4:F0:0F:08:9D:E7:2A:01:60:55:47:C6:0C:E2:08:73:C7:5C
a=group:BUNDLE sdparta_0 sdparta_1
a=ice-options:trickle
a=msid-semantic:WMS *
m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8
c=IN IP4 0.0.0.0
a=sendrecv
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=fmtp:109 maxplaybackrate=48000;stereo=1
a=ice-pwd:822186629cb33e040c095e688fa27f29
a=ice-ufrag:b9198a10
a=mid:sdparta_0
a=msid:{43a74c16-adc8-754f-841c-9b6c20377ca1} {8a30401d-b469-7b45-b89f-ccfc937be996}
a=rtcp-mux
a=rtpmap:109 opus/48000/2
a=rtpmap:9 G722/8000/1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=setup:actpass
a=ssrc:2837427922 cname:{c5a2b7e1-0cb3-a546-b176-88d22b67064a}
m=video 9 UDP/TLS/RTP/SAVPF 120 126 97
c=IN IP4 0.0.0.0
a=sendrecv
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=ice-pwd:822186629cb33e040c095e688fa27f29
a=ice-ufrag:b9198a10
a=mid:sdparta_1
a=msid:{43a74c16-adc8-754f-841c-9b6c20377ca1} {9e466081-83c7-344d-8b28-088a73dc512c}
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=rtcp-fb:126 nack
a=rtcp-fb:126 nack pli
a=rtcp-fb:126 ccm fir
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=rtcp-mux
a=rtpmap:120 VP8/90000
a=rtpmap:126 H264/90000
a=rtpmap:97 H264/90000
a=setup:actpass
a=ssrc:1210838478 cname:{c5a2b7e1-0cb3-a546-b176-88d22b67064a}
  • m=videoの文法はChromeと同じ
  • a=rtcp-fb:xx / a=rtpmap:xx のxxは上記のコーデック番号と紐付いている

peer.jsでSDPを書き換える

  • 640行目辺りに追記
      if(window.webkitRTCPeerConnection){
          var _sdp = offer.sdp;
          _sdp = _sdp.replace("m=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96 97 99 98","m=video 9 UDP/TLS/RTP/SAVPF 107");
          _sdp = _sdp.replace("a=rtpmap:100 VP8/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 nack pli\r\na=rtcp-fb:100 goog-remb\r\na=rtcp-fb:100 transport-cc\r\na=rtpmap:101 VP9/90000\r\na=rtcp-fb:101 ccm fir\r\na=rtcp-fb:101 nack\r\na=rtcp-fb:101 nack pli\r\na=rtcp-fb:101 goog-remb\r\na=rtcp-fb:101 transport-cc\r\n","");
          _sdp = _sdp.replace("a=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\na=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=100\r\na=rtpmap:97 rtx/90000\r\na=fmtp:97 apt=101\r\na=rtpmap:99 rtx/90000\r\na=fmtp:99 apt=107\r\na=rtpmap:98 rtx/90000\r\na=fmtp:98 apt=116\r\n","");
          offer.sdp = _sdp;
      }else if(window.mozRTCPeerConnection){
          var _sdp = offer.sdp;
          _sdp = _sdp.replace("m=video 9 UDP/TLS/RTP/SAVPF 120 126 97","m=video 9 UDP/TLS/RTP/SAVPF 126 97");
          _sdp = _sdp.replace("a=fmtp:120 max-fs=12288;max-fr=60\r\n","");
          _sdp = _sdp.replace("a=rtcp-fb:120 nack\r\na=rtcp-fb:120 nack pli\r\na=rtcp-fb:120 ccm fir\r\n","");
          _sdp = _sdp.replace("a=rtpmap:120 VP8/90000\r\n","");
          offer.sdp = _sdp;
      }

  • H264以外のコーデックに関する情報を全て削除している
  • 上記例ではOffer側のみ書き換えている(これで十分なはず)

動作確認

Offer側 Answer側 結果
Chrome Chrome
Firefox Firefox
Chrome Firefox
メディアは通るがエラー発生
Firefox Chrome

Chromeのchrome://webrtc-internals/の結果(Firefox→Chroneの場合)

  • recv
    recv.png

  • send
    send.png

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした