6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

WebRTC チュートリアル(SkyWay)

Last updated at Posted at 2021-06-01

概要

WebRTC初学者向けに、SkyWayのチュートリアルを参考にチュートリアルを作ってみました。
SkyWayのチュートリアルに細かい解説もありますので、ぜひ一読ください。

環境

環境はapacheの環境さえあれば問題ないのですが、再現しやすいように今回はDockerを利用しています。
また、見た目を整えるためにBootstrapも利用しています。

  • maxOS BigSur 11.2.3
  • Docker version 20.10.6
  • docker-compose version 1.29.1
  • skyway 4.4.1
  • Bootstrap 4.3.1

構成

最終的には以下のような構成になります。
SkyWayやBootstrapはCDNを利用していますので、プロジェクト自体はシンプルです。

.
├── docker-compose.yml
└── web
    ├── assets
    │   └── js
    │       └── index.js
    └── index.html

成果物

左側に自分の映像、右側に相手の映像が映るようになります。
(画像では、余計なものが映っているので塗りつぶしています。)

スクリーンショット 2021-06-01 9.49.33.png

HTML

index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
              integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
              crossorigin="anonymous">
        <title>WebRTCサンプル</title>
    </head>
    <body>
        <div class="container">
            <div class="row">
                <h1>WebRTCサンプル</h1>
            </div>
            <div class="row">
                <div class="col-6">
                    <div class="form-group">
                        <p class="col-form-label">自分のPeerID: <span id="my-id"></span></p>
                    </div>
                    <video id="my-video" width="100%" autoplay muted playsinline></video>
                </div>

                <div class="col-6">
                    <div class="form-group row">
                        <label class="col-3 col-form-label" for="their-id">相手のPeerID: </label>
                        <div class="col-7">
                            <input id="their-id" class="form-control">
                        </div>
                        <div class="col-2">
                            <button type="button" class="btn btn-primary" id="make-call">発信</button>
                        </div>
                    </div>

                    <video id="their-video" width="100%" autoplay muted playsinline></video>
                </div>
            </div>
        </div>

        <!-- Optional JavaScript -->
        <script src="https://cdn.webrtc.ecl.ntt.com/skyway-4.4.1.js"></script>
        <script src="assets/js/index.js"></script>
        <!-- jQuery first, then Popper.js, then Bootstrap JS -->
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
                integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
                crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
                integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
                crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
                integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
                crossorigin="anonymous"></script>
    </body>
</html>

JS

index.js
let localStream;

// カメラ映像取得
navigator.mediaDevices.getUserMedia({video: true, audio: true})
    .then(stream => {
        // 成功時にvideo要素にカメラ映像をセットし、再生
        const videoElm = document.getElementById('my-video');
        videoElm.srcObject = stream;
        videoElm.play();
        // 着信時に相手にカメラ映像を返せるように、グローバル変数に保存しておく
        localStream = stream;
    })
    .catch(error => {
        // 失敗時にはエラーログを出力
        console.error('mediaDevice.getUserMedia() error:', error);
    });

//Peer作成
const peer = new Peer({
    key: 'APIキー',
    debug: 3
});

// 自分のPeerID取得
peer.on('open', () => {
    document.getElementById('my-id').textContent = peer.id;
});

// 発信処理
document.getElementById('make-call').onclick = () => {
    const theirID = document.getElementById('their-id').value;
    const mediaConnection = peer.call(theirID, localStream);
    setEventListener(mediaConnection);
};

// イベントリスナを設置する関数
const setEventListener = mediaConnection => {
    mediaConnection.on('stream', stream => {
        // video要素にカメラ映像をセットして再生
        const videoElm = document.getElementById('their-video');
        videoElm.srcObject = stream;
        videoElm.play();
    });
}

//着信処理
peer.on('call', mediaConnection => {
    mediaConnection.answer(localStream);
    setEventListener(mediaConnection);
});

作成手順

1. 準備

1-1. SkyWayアカウントの作成、APIキー取得、利用可能ドメイン追加

SkyWayにてアカウントを作成しましょう。

スクリーンショット 2021-05-31 16.48.35.png
スクリーンショット 2021-05-31 16.44.41.png

アカウントを作成してログインしたら、「アプリケーション一覧」より「新しくアプリケーションを追加する」をクリックします。

スクリーンショット 2021-05-31 16.46.11.png

登録画面では、「アプリケーション説明文」と「利用可能ドメイン名」を以下のように入力します。

スクリーンショット 2021-05-31 16.47.24.png

権限は今回はデフォルトのままで、「アプリケーションを作成する」をクリックしましょう。

スクリーンショット 2021-05-31 16.47.48.png

すると以下のようにAPIキーが発行されますのでコピーしておきましょう。

スクリーンショット 2021-05-31 16.55.53.png

1-2. 環境構築

今回はHTMLやJSが動けばいいので、apache用のコンテナのみを用意します。
まずは、docker-compose.ymlを作ります。

docker-compose.yml
version: "3.9"
services:
  web:
    image: httpd
    volumes:
      - ./web:/usr/local/apache2/htdocs/
    ports:
      - "80:80"

そして、確認用のindex.htmlをドキュメントルートに作ります。
BootstrapのCSSとJSをそれぞれ読み込むようにしています。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
              integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
              crossorigin="anonymous">
        <title>WebRTCサンプル</title>
    </head>
    <body>
        <div class="container">
            <div class="row">
                <h1>WebRTCサンプル</h1>
            </div>
        </div>

        <!-- Optional JavaScript -->
        <!-- jQuery first, then Popper.js, then Bootstrap JS -->
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
                integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
                crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
                integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
                crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
                integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
                crossorigin="anonymous"></script>
    </body>
</html>

dockerを起動してみましょう。
docker-compose.ymlがあるディレクトリにて以下のコマンドを実行してください。

docker-compose up -d

ちなみに、dockerを停止させる場合は同じディレクトリにて以下のコマンドを実行してください。

docker-compose down

http://localhost にアクセスしてみましょう。
「WebRTCサンプル」と表示されていれば環境構築はOKです。

2. カメラ映像、マイク音声の取得

2-1. HTML作成

index.htmlにvideoタグとscriptタグを追加します。

index.html
<div class="container">
    <div class="row">
         <h1>WebRTCサンプル</h1>
    </div>
    <div class="row">
        <div class="col-6">
            <video id="my-video" width="100%" autoplay muted playsinline></video>
       </div>
    </div>
</div>

<!-- Optional JavaScript -->
<script src="assets/js/index.js"></script>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->

ハウリングを防ぐために、video要素にはmuted属性を加えています。

2-2. JS作成

続いては、index.jsassets/jsに作ります。

index.js
let localStream;
// カメラ映像取得
navigator.mediaDevices.getUserMedia({video: true, audio: true})
    .then(stream => {
        // 成功時にvideo要素にカメラ映像をセットし、再生
        const videoElm = document.getElementById('my-video');
        videoElm.srcObject = stream;
        videoElm.play();
        // 着信時に相手にカメラ映像を返せるように、グローバル変数に保存しておく
        localStream = stream;
    }).catch(error => {
    // 失敗時にはエラーログを出力
    console.error('mediaDevice.getUserMedia() error:', error);
});

では、 http://localhost にアクセスしてみましょう。

すると、以下のようにカメラを使用して良いか確認が出ます。

スクリーンショット 2021-05-31 16.06.19.png

許可
あなたの顔が映っていればOKです。(笑)

ブロック
以下のメッセージがコンソールに出力されます。
index.js:7 mediaDevices.getUserMedia() error: DOMException: Permission denied

3. Peerの作成

3-1. SDKのインポートとAPIキーの設定

相手との通信を行うための処理を追加していきます。
また、SkyWayのSDKをCDNでインポートします。

SDKをインポートします。
SkyWayのCDNはindex.jsより前に記述してください。

index.html
<!-- Optional JavaScript -->
<script src="https://cdn.webrtc.ecl.ntt.com/skyway-4.4.1.js"></script>
<script src="assets/js/index.js"></script>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->

SkyWayで作成したアプリケーションのAPIキーを設定してください。

index.js
navigator.mediaDevices.getUserMedia({video: true, audio: true})
    ...
});

//Peer作成
const peer = new Peer({
    key: 'APIキー',
    debug: 3
});

3-2. PeerID取得

相手と接続するためのPeerIDを取得します。

index.htmlに出力用のタグを用意します。

index.html
<div class="col-6">
    <div class="form-group">
        <p class="col-form-label">自分のPeerID: <span id="my-id"></span></p>
    </div>
    <video id="my-video" width="100%" autoplay muted playsinline></video>
</div>
index.js
//Peer作成
const peer = new Peer({
    key: 'APIキー',
    debug: 3
});
//PeerID取得
peer.on('open', () => {
    document.getElementById('my-id').textContent = peer.id;
});

http://localhost にアクセスしてみてください。
画面上に16桁のランダム英数字が表示されれば成功です。

3-3. 発信・着信処理

HTMLに以下の要素を追加します。

  • 相手のPeerIDを記入するテキストエリア
  • 発信ボタン
  • 着信時に相手の映像を表示するvideo要素
index.html
<div class="row">
    <div class="col-6">
        <div class="form-group">
            <p class="col-form-label">自分のPeerID: <span id="my-id"></span></p>
        </div>
        <video id="my-video" width="100%" autoplay muted playsinline></video>
    </div>

    <div class="col-6">
        <div class="form-group row">
            <label class="col-3 col-form-label" for="their-id">相手のPeerID: </label>
            <div class="col-7">
                <input id="their-id" class="form-control">
            </div>
            <div class="col-2">
                <button type="button" class="btn btn-primary" id="make-call">発信</button>
            </div>
        </div>

        <video id="their-video" width="100%" autoplay muted playsinline></video>
    </div>
</div>
index.js
// 発信処理
document.getElementById('make-call').onclick = () => {
    const theirID = document.getElementById('their-id').value;
    const mediaConnection = peer.call(theirID, localStream);
    setEventListener(mediaConnection);
};

// イベントリスナを設置する関数
const setEventListener = mediaConnection => {
    mediaConnection.on('stream', stream => {
        // video要素にカメラ映像をセットして再生
        const videoElm = document.getElementById('their-video');
        videoElm.srcObject = stream;
        videoElm.play();
    });
}

//着信処理
peer.on('call', mediaConnection => {
    mediaConnection.answer(localStream);
    setEventListener(mediaConnection);
});

4. 確認

別タブでページを2つ表示して、他方のPeerIDをテキストエリアにコピー&ペーストし、発信ボタンを押下しましょう。
どちらのページにも映像が2つ表示されれば疎通成功です。
これで完成です。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?