Upload
mganeko
View
512
Download
2
Embed Size (px)
Citation preview
WebRTC Meetup Tokyo #14
ブラウザで iOS ゲートウェイ作ってみたBuild WebRTC - iOS Gateway on Browser
2017.03.23インフォコム株式会社がねこまさし@massie_g
1
自己紹介• がねこまさし / @massie_g
• インフォコム株式会社 に所属– 技術調査と社内での利用を推進するチーム
• WebRTC Meetup Tokyo スタッフの一人• WebRTC Beginners Tokyo 講師の一人• WebRTC 入門 2016 を HTML5Experts.jp に連載してました
– https://html5experts.jp/series/webrtc2016/
2
今日のお題• iOS のブラウザでは、まだ WebRTC が使えない
– Webkit では WebRTC 対応が進んでいる様子。が、 Safari に入るかは Apple 次第• でも、今ある技術を使って、無理やりコミュニケーションできる!
– Canvas, Web Audio, WebSocket を利用• 先行している試みを パクって 手本にして実現
– 音声: @leader22 「 WebAudio でなんちゃって WebRTC 」• http://leader22.github.io/slides/webaudio_tokyo-1/
– 画像: @voluntas 「 WebRTC SFU Sora ノススメ」のスナップショット機能• https://gist.github.com/voluntas/0d6621d15947a24e710b0610093a5d20
3
DEMO• PC Chrome iOS Safari
– ぱくたそ の写真を使わせていただいています– https://www.pakutaso.com
• ソースコード– https://github.com/mganeko/webrtcexpjp/tree/master/gateway
• ちょっと残念な部分もありますが…– 縦の写真が上手く扱えない 4
PC Chrome iOS Safari (1) Video
5
getUserMedia()
MediaStream
<video>
<canvas>
Blob JPEB
setInterval()
drawImage()
toBlob()
WorkerWebSocket(socket.io)
BlobJPEB
socket.ioServer
postMessage()
WorkerWebSocket(socket.io) ArrayBuffer
postMessage()
ArrayBuffer
<img>
Blob
createObjectURL()
PC Chrome iOS Safari
PC Chrome iOS Safari (2) Audio
6
getUserMedia()
MediaStream
Worker
WebSocket(socket.io)
socket.ioServer
Worker a
WebSocket(socket.io)
PC Chrome iOS Safari
WebAudio
ScriptProcessor [Float32Array]
MediaStreamAudioSourceNode
[Uint8Array]
compress
postMessage()
ArrayBuffer
(decompress)
WebAudio
6
AudioBufferSource
ArrayBuffer
decoceAudioData()
AudioDestinationNode
postMessage()
PC Chrome iOS Safari : Image
7
<img>
toDataURL ()
WorkerWebSocket(socket.io) DataURL
socket.io Server
postMessage()
<img>
<img>
<img>
<canvas>
drawImage()
DataURL
toBlob ()
<img>
DataURL
img.src
WorkerWebSocket(socket.io)
postMessage()
DataURL
iOS SafariPC Chrome
通信データ量の削減:画像• TCP の通信では、条件が厳しくなると、どんどん遅延が発生
– 本来はリアルタイム映像、音声通信には不向き– なるべく通信に余力ができるよう、データ量の削減が必須
• 画像 240x180 / 毎秒– RGB の RAW… 240x180x24bit = 1 Mbit, 129 kb
– PNG … 約 760 kbit, 96 kb
– JPEG … 約 110 kbit, 14 kb
– → 最終的に、 2 秒に 1 回に … 56 kbit/sec8
通信データ量の削減:画像
9
1/8
通信データ量の削減:音声
10
• サンプリング周波数はプラットフォーム依存(※ブラウザ依存ではない)– 44.1kHz (Mac) ← こちらの例で計算– 48kHz (Windows, Linux, iOS)
• 圧縮– WebAudio 元データ… 44.1kHz × 32bit 実数 = 1411 kbps– 16bit リニア PCM 化 … 44.1kHz × 16bit 整数 = 705 kbps
• ※CD は 44.1kHz ×16bit × 2ch(Stereo) = 1411 kbps– サンプリング周波数を半分の 22 kHz に … 350 kbps– μ-law 圧縮 22kHz, 8bit 整数 … 175 kbps
• ※G.711 は 8kHz, 8bit 整数 … 64kbps– mp3 圧縮 … 36 kbps を指定
11
1/40
通信データ量の削減:音声
μ-law アルゴリズム• 音声圧縮アルゴリズム、非可逆• サンプル当たりのビット数を削減 … 今回は 8bit• IP 電話の G.711 規格で使われるアルゴリズム
– G.711 では、サンプリング周波数は 8kHz → 64kbps • Wikipedia
• https://ja.wikipedia.org/wiki/%CE%9C-law%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0
– 北アメリカと日本のデジタル通信システムで μ-law 使用 … PCMU
– ヨーロッパでは類似の A-law アルゴリズムを使用 … PCMA• WiFi では使えなくはないが、 LTE ではまだキツイ(圧縮不足)• 参考: WebAudio で原始的な音声圧縮をやってみた
– http://qiita.com/massie_g/items/49183a03b015b9ea27eb– ソース: https://github.com/mganeko/webrtcexpjp/blob/master/tool/mulow.html
12
μ-law アルゴリズムでは対数を利用
13
リニア PCM :直線的な 8 段階 対数:小さい音は細かく、大きい音は粗く
μ-law アルゴリズム
14
μ = 255 ( 8 ビット)
WebRTC と PCMU/PCMA
15
[Firefox の SDP]
a=rtpmap:109 opus/48000/2a=rtpmap:9 G722/8000/1a=rtpmap:0 PCMU/8000a=rtpmap:8 PCMA/8000
[Chrome の SDP]
a=rtpmap:111 opus/48000/2a=rtcp-fb:111 transport-cca=fmtp:111 minptime=10;useinbandfec=1a=rtpmap:103 ISAC/16000a=rtpmap:104 ISAC/32000a=rtpmap:9 G722/8000a=rtpmap:0 PCMU/8000a=rtpmap:8 PCMA/8000a=rtpmap:106 CN/32000a=rtpmap:105 CN/16000a=rtpmap:13 CN/8000a=rtpmap:126 telephone-event/8000
オマケ: G.722 • サンプリング周波数 16kHz 、 48, 56, 64kbps
• ADPCM (adaptive differential pulse code modulation)
• 圧縮のアルゴリズム(たぶんこんな感じ)– 前のサンプルとの差分
• 小さい値になりやすい– 差分を対数的に表現
• 小さい差分は細かく• 大きい差分はおおざっぱに
16
リニア PCM ADPCM
ケータイ Watch ケータイ用語の基礎知識よりhttp://k-tai.watch.impress.co.jp/cda/article/keyword/2936.html
lamejs による MP3 圧縮• より音声データを圧縮するために MP3 を利用• lamejs
– https://github.com/zhuker/lamejs
• ストリーミングではなく、細切れの MP3 データを生成• 入力は 16bit 整数の配列
– チャネル(ステレオ /モノ)、サンプルレート を指定可能• 圧縮後は 8bit 整数の配列
– ビットレート (kbps) を指定可能– 下限あり: 22kHz の場合 >= 32kbps 、 24kHz の場合 >= 36kbpsぐらい
17
Sample from GitHubvar channels = 1, sampleRate = 44100, kbps = 128; // mono, 44.1kHz, 128kbps
var mp3encoder = new lamejs.Mp3Encoder(channels, sampleRate, kbps);
var sampleBlockSize = 1152; // better to use 576 * n
var samples = new Int16Array(44100); // 1sec sample
var mp3Data = [];
for (var i = 0; i < samples.length; i += sampleBlockSize) {
sampleChunk = samples.subarray(i, i + sampleBlockSize);
var mp3buf = mp3encoder.encodeBuffer(sampleChunk);
if (mp3buf.length > 0) { mp3Data.push(mp3buf); }
}
var mp3buf = mp3encoder.flush(); //finish writing mp3
if (mp3buf.length > 0) { mp3Data.push(new Int8Array(mp3buf)); }18
lamejs 利用にあたっての工夫• MP3 データのオーバーヘッドの抑制
– ヘッダ + タグ = 132byte
– 一度に変換する音声ブロックを、なるべく長く– WebAudio の ScriptProcessor の上限 (16384 サンプル / 回 ) で取得
• 370 ms (44.1kHz), 340 ms (48kHz)
19
ヘッダ 圧縮後データ MP3 タグ4byte 128byte1500~ 2000 byte
• 圧縮前のサンプルの半減: 44.1kHz→22.05kHz, 48kHz→24kHz に• ビットレート下限の調整
– 下限あり: 22kHz の場合 >= 32kbps 、 24kHz の場合 >= 36kbpsぐらい• WebWorker で圧縮 … 1 ブロックあたり 50ms ~ 100ms
通信量の削減→安定して動作• 画像 … 56kbps
• 音声 … 36 kbps
20
トータル 92kbps
1/401/8
ブラウザ MCU と iOS ゲートウェイの結合
21
ブラウザA
ブラウザB
ブラウザC
MCU
iOS Safari
画像 /2 秒ごと、 MP3 音声画像
参考: WebRTC Meetup Tokyo #11ブラウザで MCU 作ってみたBuild MCU on browserhttps://www.slideshare.net/mganeko/webrtc-build-mcu-on-browserhttps://speakerdeck.com/mganeko/build-webrtc-mcu-on-browser
ブラウザ
DEMO
• PC Chrome ブラウザ MCU iOS Safari
• PC Chrome
22
MCUサーバー役の仕組み:Video
23
RTCPeerConnection A
MediaStream<video> タグ
<canvas> タグ
drawImage()
requestAnimationFrame() で継続的に描画
<img> タグ drawImage()WorkerWebSocket(socket.io) DataURL
Blob JPEB
toBlob()Blob JPEB
from iOS
to iOS setInterval()
MCU サーバー役の仕組み:Audio
24
RTCPeerConnection A
MediaStream
AudioContext .createMediaStreamSource()で生成
MediaStreamAudioSourceNode MediaStreamAudioSourceNode
MediaStreamAudioSourceNode
ScriptProcessor
合成(合算)
WorkerWebSocket(socket.io)
MP3[Uint8Array]
[Uint16Array]
[Flaoat32Array]
lamejs
to iOS
MCU サーバー役の仕組み:録画も可能
25
MediaStream(Video A+B+C+D)
<canvas> タグ 配信用のものを利用
Web Audio API
MediaStream(Audio A+B+C)
録画用に改めて準備videoTracks[] MediaStreamTrack
MediaStreamTrackaidioTracks[]
MediaStream
新しく生成
MediaStream.addTrack()で追加
MediaStream.addTrack()で追加
MediaRecorder
WebM
まとめ• iOS ブラウザで WebRTC が動かない… それがどうした!
– やりたいのは WebRTC ではなく、コミュニケーション• 今使えるもので、無理やりやってみよう!
– ブラウザの要素を自由に組み合わせられるのが「 Web 」 RTC
– Canvas, WebAudio, WebSocket
• なぜか音声コーデックの歴史をたどる旅に
26
Thank you!
27