WebRTCを使ったビデオ会議システムについて
最近のリモートワーク需要に関連してビデオ会議のシステムが簡単に作れないか調べてみるとWebRTCという技術が。調べてみた内容から試作までをアップしていきたいと思います。
WebRTCとは?
WebRTC(Web Real Time Communication)はブラウザ間で直接リアルタイム通信を行うためのAPIを提供するオープンソースのプロジェクトです。次のような機能を持っています。
- ブラウザからカメラやマイクにアクセスする
- キャプチャした映像や音声を送受信する
- サーバーの仲介を必要とせずにブラウザ間でのデータ通信が可能
ただし完全なサーバーレスとはならない
フロントエンドはJavaScriptを使って実装できます。
対応ブラウザ
- Google Chrome
- Microsoft Edge
- Mozilla Firefox
- Safari
- Opera
2020年8月現在、Internet Explorer以外の主要ブラウザでサポートされています。ただし、デバイスへのアクセスなどはブラウザによってベンダープレフィックスが必用な場合があります。
上記以外にも、モバイル用のブラウザで対応しているものがあります。
WebRTCの種類
WebRTCには接続方法によって次の3種類があります。
名称 | 通信イメージ | 内容 |
---|---|---|
P2P |
クライアント同士が直接通信を行う。 全員と送受信を行うため、人数が増えるほど、クライアントの通信量と負荷が大きくなる。 サーバーは端末同士を繋げる役割のみに使用する。 |
|
SFU |
クライアントはサーバーとだけ通信を行う。 クライアント側でデコードするため、人数が増えるとクライアントの負荷が大きくなる。 サーバー側の通信負荷が大きい。 | |
MCU |
クライアントはサーバーとだけ通信を行う。 サーバー側で全員の映像と音声を合成して各クライアントに送信する。 サーバー側はリアルタイムで映像の合成などを行うため、負荷が大きい。 合成済みの映像が送信されるので、端末側でレイアウトの変更ができない。 |
機能比較
P2P | SFU | MCU | |
---|---|---|---|
クライアントのスペック | ●●●●● | ●●●● | ● |
クライアントの通信量 | ●●●●● | ●●● | ● |
サーバーのスペック | ● | ●●● | ●●●●● |
サーバーの通信量 | ● | ●●●●● | ●● |
実装難易度 | 低 | 高 | 高 |
もちろん、スペックが高くなるとお値段も高額になります。(^-^;
P2P
WebRTCについて調べると多くがP2P方式になります。提供されているAPIを使ってすぐに試すことができます。
クライアント同士が直接通信を行うのですが、通信相手のIPアドレスを取得するためにサーバーが必要です。
通信相手全員と双方向通信を行うため、3~4人での接続が現実的な利用になります。
SFU (Selective Forwarding Unit)
クライアントはサーバーとだけ通信を行います。
サーバーが各クライアントから受信した情報を他の接続クライアントに送信します。そのためクライアントの送信が1本で済むメリットがあります。
一方で、受信した映像や音声のデコードはクライアント自身が行うことは変わらないため、ある程度の人数までしか双方向通信ができません。
実装の難易度は高いですが、複数のOSSモジュールもあるためそれらを利用することで個人レベルでの実装も可能です。
主な SFU OSS
- mediasoup
- Janus
- Jitsi
MCU (Multipoint Control Unit)
クライアントはサーバーとだけ通信を行います。
サーバーは各クライアントから受信した映像と音声を合成して各クライアントに送信します。そのため、クライアントは送信と受信それぞれ1本で済むメリットがあります。
一方サーバー側は映像の合成などをリアルタイムで行わないといけないため、高スペックが要求され、かつ負荷も大きくなります。サーバーの性能次第で何人でも双方向通信が可能です。
また映像は合成されるので端末側でレイアウトの変更はできません。
実装の難易度は高いですが、こちらもOSSモジュールがあるため利用することで個人レベルでの実装も可能です。
主な MCU OSS
- Kurento
- Licode
- Medooze
ブラウザでカメラ映像を表示する
実際にWebRTCの機能を使って自分のパソコンに搭載したカメラから取得した映像とマイクから取得した音声をブラウザで出力してみましょう。
次のファイルを用意します。
navigator.mediaDevices.getUserMedia()
でカメラやマイクの入力を取得できます。
あとは取得したストリームをvideoタグに設定するだけです。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebRTC Video</title>
<style>
.video-box {
border: 1px solid #000;
height: 240px;
width: 320px;
}
.outlined-button {
background-color: #2196f3;
border-radius: 4px;
border: none;
color: #fff;
font-size: 16px;
font-weight: 600;
line-height: 36px;
margin-left: 4px;
outline: none;
padding: 0 16px;
text-align: center;
}
</style>
</head>
<body>
<div>
<p>自身の映像と音声を出力します。</p>
</div>
<div id="main-container">
<button onclick="startVideo();" class="outlined-button">Start</button>
<button onclick="stopVideo();" class="outlined-button">Stop</button>
<section class="video">
<video id="local-video" autoplay control class="video-box"></video>
</section>
</div>
<script type="text/javascript">
let localVideo = document.getElementById('local-video');
let localStream;
function startVideo() {
navigator.mediaDevices.getUserMedia({ video:true, audio:true })
.then(function(stream) {
localStream = stream;
localVideo.srcObject = stream;
localVideo.onloadedmetadata = function(e) {
localVideo.play();
};
}).catch( function(error) {
console.error('mediaDevice.getUserMedia() error:', error);
return;
});
}
function stopVideo() {
for (let track of localStream.getTracks()) {
track.stop();
}
localStream = null;
// kill local video.
localVideo.pause();
localVideo.srcObject = null;
}
</script>
</body>
</html>
実行
Google Chromeでindex.html
を開きます。次のダイアログが表示された場合は許可してください。
Startボタンを押すと自分の映像が表示されます。音声を出力した場合、ハウリングするので注意してください。
参考
HTML5でWebRTCを使ってみよう!「カメラを使ってみよう」編