Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Node.js x Headless Chrome for WeRTC MCU / Node.js x Chrome headless で、お手軽WebRTC MCU

2,547 views

Published on

Node学園祭2017の資料です。
WebRTC 向けに映像/音声を合成するMCUを、Node.jsとヘッドレスブラウザで実現しする話。ついでのDockerコンテナでも動かしてみました

Published in: Technology
  • Be the first to comment

Node.js x Headless Chrome for WeRTC MCU / Node.js x Chrome headless で、お手軽WebRTC MCU

  1. 1. Node.js x Chrome headless で、 お手軽WebRTC MCU 東京Node学園祭2017 / Nodefest 2017 2017.11.25 インフォコム株式会社 がねこまさし @massie_g 1
  2. 2. 自己紹介 • がねこまさし / @massie_g • インフォコム(株)の技術調査チームに所属 • WebRTC Meetup Tokyo スタッフ • WebRTC Beginners Tokyo スタッフ • WebRTC入門2016を HTML5Experts.jpに執筆 – https://html5experts.jp/series/webrtc2016/ 2
  3. 3. 過去の Node 学園祭での発表 • 東京Node学園祭2016 LT – Node.js with WebRTC DataChannel – https://www.slideshare.net/mganeko/nodejs-with-webrtc-datachannel • 東京Node学園祭2014 – Nodeで操るKurentoメディアサーバー – http://www.slideshare.net/mganeko/nodekurento • 東京Node学園祭2013 – WebRTCを始めよう – http://www.slideshare.net/mganeko/2013-web-rtcnode 3
  4. 4. 今日の話 • WebRTCの通信の形態は、P2P以外にもある – MCUはサーバーで映像/音声を合成する方式 • MCUはブラウザで実現することも可能 • Node.js x ヘッドレスブラウザで、映像や音声 の加工が自由自在 4
  5. 5. 1. WebRTC and MCU 前説〜どうしてMCUなの? 5
  6. 6. What is WebRTC • Web Real-time Communication – 映像(Video) – 音声(Audio) – データ(Data) • オープンスタンダード … だれでも使える – W3C WebRTC Working Group ... API – IETF RTCWEB Working Group … Protocol – コアライブラリは、オープンソース libwebrtc • Webブラウザと、それ以外のWeb接続デバイスのために設計 • 他のWeb技術と、容易に組み合わせ可能 10101110100…
  7. 7. WebRTCが使える環境 7 「WebRTCハンズオン 概要編」より https://qiita.com/massie_g/items/916694413353a3293f73 Mac OS X / iOS の Safari 2017秋のSafari 11 から対応 (H.264のみ) NEW!NEW!
  8. 8. WebRTCの形態 • Peer to Peer … 基本の形態 – ブラウザ同士が直接通信 • SFU (Selective Forwarding Unit) – サーバー側で映像/音声を配布 • MCU (Multipoint Control Unit) – サーバー側で映像/音声を合成、再圧縮 8
  9. 9. P2P • 基本の形態 – ブラウザ同士が直接通信 • Good – メディアサーバー不要 – 構成がシンプル • Bad(クライアント側) – CPU負荷: 極めて高い – ネットワーク負荷:極めて高い Browser A Browser B Browser D Browser C
  10. 10. P2Pの圧縮負荷(CPU)が高い理由 Browser A 元映像 圧縮 送信 送信 送信 これ、 (すべての相手に 同じ圧縮) ではなく
  11. 11. Browser A P2Pの圧縮負荷(CPU)が高い理由 Browser A 元映像 圧縮 送信 圧縮 圧縮 圧縮 送信 送信 送信 送信 送信 こっち:相手に合わせて別々に圧縮
  12. 12. SFU: Selective Forwarding Unit • サーバー側で映像/音声を配布 – サーバーでは圧縮しない • Good – クライアント側のCPU負荷が低い – クライアントの上りネットーク負荷低い – サーバーCPU負荷はあまり高く無い • Bad • クライアント側の下りネットワーク負荷 は高い • P2Pよりは構成が複雑
  13. 13. MCU (Multipoint Control Unit) • サーバー側で映像/音声を合成 • Good – クライアント側のCPU負荷が一番低い – クライアントの上下のネットーク負荷低い – → モバイルに優しい • Bad • サーバー負荷が非常に高い • 映像のレイアウトがサーバーが固定され る Browser A Browser B Browser D Browser C MCU Mix video / audio
  14. 14. モバイルとMCU • サーバー側で映像/音声を合成 • サーバー側で再圧縮(再エン コード) – 回線に合わせた圧縮率 – クライアント側に合わせたコーデッ クが利用可能 PC Chrome PC Firefox Android Chrome iOS Safari MCU VP9 VP9 VP9 VP9 VP8 VP8 H.264 H.264 H.264のみ対応
  15. 15. MCUの例 • オープンソース – Kureto … http://www.kurento.org/ • Twillioに買収後、開発は活発ではない様子 • 参考:Nodeで操るKurentoメディアサーバー – https://www.slideshare.net/mganeko/nodekurento – Licode … http://lynckia.com/licode/ • 商用製品 – Dialogic PowerMedia XMS 15
  16. 16. 2. MCU Core with Browser MCU のコア処理をブラウザで 16
  17. 17. MCUがやる事 • クライアントから映像/音声を受け取る • 映像を合成する • 音声を合成する • クライアントに映像/音声を送り返す 17
  18. 18. MCUがやる事 • クライアントから映像/音声を受け取る • 映像を合成する • 音声を合成する • クライアントに映像/音声を送り返す 18 WebRTC PeerConnection WebRTC PeerConnection Canvas WebAudio 全部、ブラウザで出来そう!
  19. 19. Video: 映像合成処理 19
  20. 20. ブラウザMCUの仕組み:Video 20 RTCPeerConnection A MediaStream <video>タグ RTCPeerConnection D MediaStream <canvas>タグ drawImage() requestAnimationFrame()で 継続的に描画 <video>タグ drawImage()
  21. 21. ブラウザMCUの仕組み: Video 21 RTCPeerConnection A RTCPeerConnection D <canvas>タグ MediaStream captureStream(fps)で取得
  22. 22. ブラウザMCUの仕組み: Video 22 RTCPeerConnection A MediaStream <video>タグ RTCPeerConnection D MediaStream <canvas>タグ MediaStream drawImage() requestAnimationFrame()で 継続的に描画 <video>タグ captureStream(fps)で取得 drawImage()
  23. 23. ブラウザMCUの流れ:Video • RTCPeerConnection からリモートのMediaStreamを取得 – それを <video> タグで表示 • Canvasのコンテキストを getContext('2d')で取得 • window.requestAnimationFrame()で、継続的に描画処理を実行 – drawImage()を使って、各<video>の映像を、Canvasに描画 • Canvasから captureStream(fps)を使って、MediaStreamを取得 – RTCPeerConnectionに addStream()で渡し、通信相手に送り返す 23
  24. 24. DEMO1:ブラウザMCUによる映像合成 • シングルルーム版(手動起動設定) • MCUブラウザ起動 • シグナリングサーバー起動 • メンバーブラウザ起動、接続 • ※隠れた場合のデモも実施 24
  25. 25. ブラウザMCUの注意点:Video • window.requestAnimationFrame() 利用 – ウィンドウ/タブが隠れると呼ばれない… Chrome 62 (OSX) – タブが隠れると呼ばれない… Chrome 62(Windows, Linux) – 最小化したり、他のタブの後ろに回すと描画停止 • 代わりに window.setInterval() を使っても – ウィンドウ/タブが完全に隠れると、著しく間隔が開いてしまう – 50msに指定しても、後ろに回すと1秒以上間隔が開く 25
  26. 26. Audio: 音声合成処理 26
  27. 27. ブラウザMCUの注意点:Audio • Videoは全員に同じのものを送り返せばよい • Audioは、全員に同じものを送り返すと … つらい – 自分の声が「ちょっと遅れて戻ってくる」と、とてもしゃべり にくい – WebRTC開発している皆さんは、きっと経験あるはず 27
  28. 28. ブラウザMCUの仕組み:Audio • Audioは、「マイナスワン」を作る必要あり – 自分以外の参加者の声を合成(合算)した音 • 複数種類の音声生成が必要 – 4人いたら、4通り – N人いたら、N通り 28 ブラウザ A ブラウザ B ブラウザ D ブラウザ C MCU 音声合成は やっかい 映像(Video)より 音声(Audio)の方が 厄介
  29. 29. ブラウザMCUの仕組み:Audio 29 RTCPeerConnection A MediaStream MediaStreamAudioSourceNode AudioContext . createMediaStreamSource() で生成
  30. 30. ブラウザMCUの仕組み:Audio 30 RTCPeerConnection D MediaStream MediaStreamAudioSourceNode MediaStreamAudioSourceNode MediaStreamAudioSourceNode MediaStreamAudioDestinationNode 合成(合算) RTCPeerConnection A AudioContext . createMediaStreamDestination() で生成 RTCPeerConnection B RTCPeerConnection C
  31. 31. ブラウザMCUの仕組み:Audio 31 RTCPeerConnection A MediaStream RTCPeerConnection D MediaStream MediaStreamAudioSourceNode MediaStreamAudioSourceNode MediaStreamAudioSourceNode MediaStreamAudioDestinationNode 合成(合算) ※これを Nパターン RTCPeerConnection A RTCPeerConnection B RTCPeerConnection C
  32. 32. ブラウザMCUの流れ:Audio • RTCPeerConnection からリモートのMediaStreamを取得 • Web AudioのMediaStreamAudioSourceNodeを生成 – MediaStreamをWeb Audioのノードに変換 • MediaStreamAudioDestinationNodeを生成 – 自分以外の音のSourceNodeを接続(音を合成) – sourceNode.connect(destinationNode); • MediaStreamを取り出す – RTCPeerConnectionに addStream()で渡し、送り返す – peer.addStream(destinationNode.stream); • ※以上を、メンバー毎に個別に行う 32
  33. 33. MCUサーバー役の仕組み:Video & Audio 33 RTCPeerConnection A RTCPeerConnection D videoTrack MediaStream (Audio B+C+D) RTCPeerConnection B RTCPeerConnection C MediaStream (Audio A+C+D) MediaStream (Audio A+B+D) MediaStream (Audio A+B+C) videoTrack と、audioTrack を 1つのMediaStreamにまとめて送信 addTrack() addTrack() addTrack() addTrack() MediaStream (Video A+B+C+D)
  34. 34. 3. MCU Server with Node.js + Browser Node.js とヘッドレスブラウザで作る MCUサーバー 34
  35. 35. 全体の構造 • MCU役のブラウザも、WebRTCのP2Pの仕 組みで通信 • P2P確立までに、シグナリングが必要 – 通信相手、内容を合意するための手順 – 「仲人」や「LINEのID交換」のようなもの • シグナリング方法は規定されていない – アプリケーション、サービスごとに異なる → 合成のコア処理と、通信部分は分離 35 Browser A Browser B Browser MCU Signaling Servermessage message message media media
  36. 36. Browser MCU シリーズ • https://github.com/mganeko/browser_mcu • MCUコア部分 … 映像/音声合成部分 – 通信部分は含まない • P2P通信部分 – PeerConnection生成、SDP/ICE candidate の交換 • メッセージ送信 – WebSocket / Socket.io 等 • シグナリングサーバー – Node.js – http/httpsサーバー + WebSocket/socket.ioサーバー 36 Browser MCU Core 映像/音声合成 (js) Browser MCU Server サンプル 実装 browser_mcu_core browser_mcu_server
  37. 37. Browser MCU シリーズ 37 Browser MCU Server(単一room版) MCU用HTML参加者用HTML シグナリングサーバー Node.js + ws + express Headless Chrome Browser MCU Core 映像/音声合成 (js) P2P通信部分 PeerConnection P2P通信部分 PeerConnection 読み込み 起動 参加者側 ブラウザ Chrome/Firefox/ Safari 参加者側 ブラウザ Chrome/Firefox/ Safari
  38. 38. ヘッドレス Chrome • Chrome 59 ~ – chrome --headless --remote-debugging-port=9222 URL – ※2017/11/15現在、remote-debugging-port が必須 – ※ --disable-gpu は Chrome 61から不要に • 非表示(ウィンドウシステム無し)でも動作 – 受け取った映像のvideo表示可能 – Canvas描画可能 – CanvasからMediaStream取得可能 • requestAnimationFrame()で描画イベント発生 38
  39. 39. ヘッドレスChromeの制御 • Node.js 用モジュール … Chrome DevTools Protocol を利用 – chrome-remote-interface • https://github.com/cyrus-and/chrome-remote-interface – puppeteer • https://github.com/GoogleChrome/puppeteer • 今回はシンプルな処理を自前実装 – Node.js のサーバーとはWebSocket/Socket.ioで常時接続状態 • シグナリング用 • サーバーからの制御にも利用可能 … 接続/切断を指示 – ページ遷移しない(ある意味、Single Page App) 39
  40. 40. ヘッドレスChromeの原始的な制御 • Node.js から起動 // 子プロセスとして起動 let proc = childProcess.execFile(path, args); • 停止 // Chromeの自殺はできないので、原始的な手段で proc.kill('SIGKILL'); 40
  41. 41. DEMO2 (マルチRoom版、自動起動) • メンバー接続 → Chrome 起動 – 通信開始 – ps –ef | grep Chrome で確認 • (全メンバー離脱 → Chrome 終了) • (再度メンバー接続 → Chrome起動、通信開始) • Chrome強制終了(kill)→ 映像停止 41
  42. 42. Dockerコンテナでの実行 • ヘッドレスChromeは、Dockerコンテナでも実行可能 • Node.js も含めて、まるごとコンテナに – シングルルーム版 – Browser MCU Pack (Dockerfile) • https://github.com/mganeko/browser_mcu_pack – ベース: node:latest • https://github.com/mganeko/browser_mcu_server をクローン • Chrome stable をインストール • コンテナイメージ: mganeko/browser_mcu_pack – https://hub.docker.com/r/mganeko/browser_mcu_pack/ 42
  43. 43. Browser MCU シリーズ 43 Browser MCU Server (単一room版) MCU用HTML参加者用HTML シグナリングサーバー Node.js + ws + express Browser MCU Pack (docker イメージ) Headless Chrome Browser MCU Core 映像/音声合成 (js) P2P通信部分(js) PeerConnection P2P通信部分(js) PeerConnection 読み込み 起動 参加者側 ブラウザ Chrome/Firefox/ Safari 参加者側 ブラウザ Chrome/Firefox/ Safari
  44. 44. DEMO (シングル、コンテナ版) • コンテナ起動 – docker pull mganeko/browser_mcu_pack – docker run -d -p 3000:3000 --cap-add=SYS_ADMIN mganeko/browser_mcu_pack • メンバー接続 – 通信開始 http://localhost:3000/ – [StartVideo]クリック、[Connect]クリック • コンテナ停止 → 映像停止 – docker stop xxxxxxxxxx 44 省略
  45. 45. 4. Scale out for Multiple rooms 複数Room、多数ユーザで使うための スケールアウトの方法 45
  46. 46. 複数Room対応 • Room(会議室)ごとに、MCU役のブラウザを起動 – Room(会議室)ごとに、映像/音声を合成 46 Browser A Browser B Browser MCU Signaling Server Browser C Browser D Browser MCU Web/Signaling /MCU Server Room1 Room2
  47. 47. MCUの欠点 • サーバー側の負荷が非常に高い – Roomが増えると辛い – Room内のメンバーが増えると辛い • 対応するには、オートスケールアウ ト? 47 vultr で実験 - CPU: 2 vCore - RAM: 4GB 負荷 初期 … CPU 3% - 1room、2人 … CPU 200%、+300MB - 1room、4人 … CPU 200%、+50MB - 2room、4+2人 … CPU 200%、+300MB
  48. 48. オートスケールアウトするとしたら? • Room(会議室)ごとに、MCUサーバーを起動 – VMインスタンス / または コンテナ 48 Browser A Browser B Browser MCU Signaling Server Browser C Browser D Browser MCU Web/Signaling Server Room1 Room2 MCU Server MCU Server 自動起動自動起動 → サーバ費用、 技術的に厳しい..
  49. 49. 割り切り:ユーザ主導スケールアウト • Room(会議室)ごとに、ユーザがMCU役ブラウザを起動 – ブラウザ / または コンテナ 50 Browser A Browser B Browser MCU Signaling Server Browser C Browser D Browser MCU Web/Signaling Server Room1 Room2 Browser MCU Docker 手動起動 手動起動
  50. 50. Browser MCU docker Browser MCU シリーズ on Web 51 Browser MCU Service(複数room対応版) MCU用HTML参加者用HTML シグナリングサーバー Node.js + ws + express サンプル稼働 https://meetin.biz Chrome Browser MCU Core 映像/音声合成 (js) P2P通信部分(js) PeerConnection P2P通信部分(js) PeerConnection 参加者側 ブラウザ Chrome/Firefox/ Safari 参加者側 ブラウザ Chrome/Firefox/ Safari Headless Chrome
  51. 51. DEMO3 (マルチ、コンテナ版) • MCU役ブラウザを起動して接続、[Open Room]をクリック – https://meetin.biz/multi_mcu.html?room=node2017 • または、手動でコンテナ起動 – docker pull mganeko/browser_mcu_docker – docker run -d -p 9222:9222 --cap-add=SYS_ADMIN mganeko/browser_mcu_docker node2017 • メンバー参加(iPadも) – https://meetin.biz/?room=node2017 52
  52. 52. Browser MCU シリーズをどうぞ • Browser MCU シリーズ – https://github.com/mganeko/browser_mcu – コアライブラリ … https://github.com/mganeko/browser_mcu_core • 単一Room版サンプル Browser MCU Server – https://github.com/mganeko/browser_mcu_server • サーバー + ヘッドレスブラウザのコンテナ版 – https://github.com/mganeko/browser_mcu_pack – https://hub.docker.com/r/mganeko/browser_mcu_pack/ • 試験サービス … https://meetin.biz/ – MCU … https://meetin.biz/multi_mcu.html 53
  53. 53. まとめ • WebRTCの通信の形態は、P2P以外にもある – MCUはサーバー負荷が高いことが Bad point – モバイルクライアントの負荷を減らせることが Good point • MCUはブラウザで実現することも可能 • 高負荷の部分と、そうでない部分を切り離して考えると良さそう • Node.js x ヘッドレスブラウザで、Node.jsの世界が広がる – 映像や音声の加工が自在にできる 54
  54. 54. Thank you! 55 https://github.com/mganeko/browser_mcu シリーズ WebRTC Meetup Tokyo WebRTC Begginers Tokyo にもお越しください

×