JavaScript | Web API:グラフィック・メディア - WebRTC の概要

JavaScript JavaScript
スポンサーリンク

WebRTC は「ブラウザ同士を直接つないで、映像・音・データをやり取りする仕組み」

まず一言でいうと、WebRTC は

「ブラウザ同士を“ほぼ直接”つないで、
カメラ映像・マイク音声・任意のデータをリアルタイムで送るための仕組み」

です。

Zoom や Google Meet みたいなビデオ通話
ブラウザだけで動くオンライン会議
P2P(ピアツーピア)ファイル共有
リアルタイム対戦ゲームの通信

こういう「リアルタイム性が命」の機能を、
ブラウザだけで実現するための土台が WebRTC です。

ただし、いきなり全部を理解しようとすると確実に詰まります。
初心者のうちは、まず

「何をやりたい技術なのか」
「ざっくりどんな流れで動くのか」

この二つを押さえるところから始めるのが正解です。


WebRTC で“何ができるのか”をイメージで掴む

一番分かりやすいのは「ビデオ通話」

WebRTC の典型的な使い方は、ビデオ通話です。

自分のカメラ・マイクを相手に送る
相手のカメラ・マイクを自分の画面に映す

これをブラウザ同士でやります。

ここで重要なのは、「サーバーを通して映像を中継する」のではなく、
できるだけ「ブラウザ同士を直接つなぐ」ことを目指している点です。

もちろん、完全にサーバーゼロでは動きませんが、
映像・音声そのものは P2P で流れる、というのが WebRTC の特徴です。

映像・音だけじゃなく「データ」も送れる

WebRTC には DataChannel という機能があり、
任意のデータ(文字列やバイナリ)を
ブラウザ同士で直接やり取りできます。

チャットメッセージ
ゲームのプレイヤー位置情報
ファイルの断片

などを、サーバーを経由せずに
P2P で送ることができます。

「リアルタイムで、少人数で、サーバー負荷を減らしたい」
という場面では、かなり強力な選択肢になります。


WebRTC の“登場人物”を整理する

1. ピア(peer)=通信するブラウザ

WebRTC では、通信の当事者を「ピア(peer)」と呼びます。
あなたのブラウザもピア、相手のブラウザもピアです。

ピア同士が「お互いにどうやってつながるか」を
相談し合うところから、WebRTC は始まります。

この「相談」のために、RTCPeerConnection というオブジェクトを使います。

const pc = new RTCPeerConnection();
JavaScript

これが「このブラウザの WebRTC 接続を管理する本体」です。

2. MediaStream(カメラ・マイクのストリーム)

ビデオ通話をしたいなら、
まずは自分のカメラ・マイクのストリームを手に入れます。

const localStream = await navigator.mediaDevices.getUserMedia({
  video: true,
  audio: true
});
JavaScript

この localStream を、ピア接続に「載せる」ことで、
相手に映像・音声を送れるようになります。

localStream.getTracks().forEach(track => {
  pc.addTrack(track, localStream);
});
JavaScript

ここでの感覚は、

「カメラ・マイクからの流れ(MediaStream)を、
WebRTC のパイプ(RTCPeerConnection)に流し込む」

というイメージです。

3. シグナリング(signaling)サーバー

ここが初心者が一番混乱しやすいところです。

WebRTC は「ブラウザ同士を直接つなぐ」技術ですが、
「最初の連絡先交換」だけは、
何らかのサーバーを経由する必要があります。

お互いの接続情報(SDP)
候補となる通信経路(ICE candidate)

などを交換するための仕組みを
「シグナリング」と呼びます。

このシグナリング自体は WebRTC の仕様には含まれていません。
WebSocket や REST API など、好きな方法で実装します。

ここがポイントです。

WebRTC 本体は「どうやって相手と話すか」は決めてくれるが、
「相手の連絡先をどう交換するか」は自分で決める必要がある。

この分離を理解しておくと、
「なんでサーバーが必要なの?」という疑問がスッと消えます。


ざっくり「1 対 1 ビデオ通話」の流れを追ってみる

コードは簡略化して、流れだけを追います。

1. お互いが RTCPeerConnection を作る

自分側:

const pc = new RTCPeerConnection();
JavaScript

相手側も同じように new RTCPeerConnection() します。

2. 自分のカメラ・マイクを取得して、接続に載せる

const localStream = await navigator.mediaDevices.getUserMedia({
  video: true,
  audio: true
});

localStream.getTracks().forEach(track => {
  pc.addTrack(track, localStream);
});
JavaScript

相手も同じことをします(自分のカメラ・マイクを載せる)。

3. 自分側が「オファー(offer)」を作る

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

// offer をシグナリングサーバー経由で相手に送る
sendToServer({ type: "offer", sdp: offer.sdp });
JavaScript

ここで offer
「自分はこういう条件で通信したいです」という提案書です。

4. 相手側が「オファーを受けて、アンサー(answer)を返す」

相手側:

pc.setRemoteDescription(offerFromRemote);

const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);

// answer をシグナリングサーバー経由で送り返す
sendToServer({ type: "answer", sdp: answer.sdp });
JavaScript

自分側は、その answer を受け取って
setRemoteDescription します。

この「offer ↔ answer」のやり取りで、
お互いの接続条件が合意されます。

5. ICE candidate(通信経路の候補)を交換する

実際にどの IP・ポートで通信するかは、
ネットワーク環境によって変わります。

その候補を「ICE candidate」として
お互いに送り合います。

pc.addEventListener("icecandidate", (event) => {
  if (event.candidate) {
    sendToServer({ type: "candidate", candidate: event.candidate });
  }
});
JavaScript

相手から届いた candidate は、
pc.addIceCandidate(...) で登録します。

このやり取りがうまくいくと、
ブラウザ同士が「じゃあこの経路でつなごう」と決めてくれます。

6. 相手の映像・音声を受け取って表示する

相手からの MediaStream は、
track イベントで受け取れます。

pc.addEventListener("track", (event) => {
  const [remoteStream] = event.streams;
  remoteVideo.srcObject = remoteStream;
});
JavaScript

これで、

自分のカメラ → 相手の画面
相手のカメラ → 自分の画面

という双方向のビデオ通話が成立します。

ここまでの流れを、まずは「ざっくり」でいいので
頭の中で追えるようになると、WebRTC の全体像がかなりクリアになります。


DataChannel で「任意のデータ」を送るイメージ

テキストチャットを WebRTC でやる

ビデオ通話だけでなく、
DataChannel を使うとテキストチャットもできます。

自分側:

const pc = new RTCPeerConnection();
const channel = pc.createDataChannel("chat");

channel.addEventListener("open", () => {
  console.log("DataChannel オープン");
});

channel.addEventListener("message", (event) => {
  console.log("受信:", event.data);
});

// ここから先は、さっきの offer/answer/ICE の流れと同じ
JavaScript

相手側:

const pc = new RTCPeerConnection();

pc.addEventListener("datachannel", (event) => {
  const channel = event.channel;

  channel.addEventListener("open", () => {
    console.log("DataChannel オープン");
  });

  channel.addEventListener("message", (event) => {
    console.log("受信:", event.data);
  });
});
JavaScript

接続が確立したあとなら、

channel.send("こんにちは!");
JavaScript

のようにして、
サーバーを経由せずにブラウザ同士でメッセージを送れます。

ゲームの同期や、P2P ファイル転送なども
この DataChannel をベースに作られています。


初心者として「WebRTC の概要」で本当に掴んでほしいこと

WebRTC は、細かいところまで追うと一気に難しくなります。
でも、概要として押さえるべき本質はシンプルです。

ブラウザ同士を“ほぼ直接”つないで、映像・音・データをリアルタイムにやり取りする技術であること。
カメラ・マイクの MediaStream を RTCPeerConnection に載せて、相手に届けるイメージであること。
「どうつなぐか」を決めるために、offer / answer / ICE candidate を“シグナリング”で交換する必要があること。
DataChannel を使うと、チャットやゲームなどの任意データも P2P で送れること。

最初の一歩としておすすめなのは、

一旦「ビデオ通話を自作しよう」とは思わず、
「RTCPeerConnection と DataChannel だけで、
ローカル(同じブラウザ内)で接続してメッセージを送る」
という超ミニマムな例から触ってみることです。

そこから少しずつ、

MediaStream を載せてみる
シグナリングを WebSocket で実装してみる

と階段を登っていけば、
WebRTC は「魔法の黒箱」ではなく、
「リアルタイムな体験を作るための、筋の通った通信の仕組み」
として、ちゃんと理解できるようになっていきます。

タイトルとURLをコピーしました