はじめに

SkyWay を Vue.js で動作させた際のメモ。

公式ドキュメントは以下。

TL;DR

  • SkyWay を Vue.js で動作させるサンプルプロジェクトを作成
  • 基本的には公式ページ通りに進めれば OK
  • Tips やハマりポイントも簡単にまとめた
この記事が参考になった方
ここここからチャージや購入してくれると嬉しいです(ブログ主へのプレゼントではなく、ご自身へのチャージ)
欲しいもの / Wish list

目次

  1. はじめに
  2. TL;DR
  3. 環境・条件
  4. 詳細
    1. セットアップ
    2. サンプル実装(チュートリアル)
    3. Tips など
      1. Peer ID
      2. 通信モデル
      3. 接続時の挙動について
      4. 音声/映像 の On/Off について
      5. 受信のみモードでの接続
      6. 1:1 で通話とテキストメッセージを併用
      7. Room でテキストメッセージを併用
      8. v-bind で 動画/音声 を再生
  5. まとめ
  6. その他・メモ
  7. 参考文献

環境・条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.5
BuildVersion: 19F101

$ node -v
v12.7.0

$ npm -v
6.14.5

$ npm v -g @vue/cli
@vue/cli@4.4.6 | MIT | deps: 34 | versions: 123

$ npm v skyway-js
skyway-js@3.0.2 | Apache-2.0 | deps: 11 | versions: 36

詳細

リポジトリ: 17number/vue-skyway-example

セットアップ

vue create でプロジェクト作成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ vue create vue-skyway-example
Vue CLI v4.4.6
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, CSS Pre-processors
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-sass)
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
...
🎉 Successfully created project vue-skyway-example.
👉 Get started with the following commands:

$ cd vue-skyway-example
$ npm run serve

npm iSkyWay JS SDK をインストール

1
2
$ cd vue-skyway-example/
$ npm i skyway-js

サンプル実装(チュートリアル)

詳細は割愛するが、基本的に以下を参考に実装すれば良い。

Vue.js で実装する際のポイントは主に以下あたり。(ほとんど SkyWay に限った話ではない)

  • クリックなどのイベントを v-on(@) で処理
  • 各変数を data として持たせる
  • ビデオ再生は v-bindsrcObject.prop に設定(※)


最初 :srcObject=stream にしててかなりハマった。vue.jsで複数のvideoタグを扱う - Qiita に書かれている通り、:srcObject.prop=stream にしないとダメ

Tips など

Peer ID

参考: Peer ID

  • Peerインスタンス作成時に 16桁のランダム文字列として取得
  • 原則シグナリングサーバが生成
  • ユーザー独自の値も指定可能

対向の Peer ID は mediaConnection.remoteId, dataConnection.remoteId などから取得可能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
peer.on('call', mediaConnection => {
// mediaConnection.remoteId
});

peer.on('connection', dataConnection => {
// dataConnection.remoteId
});

room.on('peerJoin', peerId => {
// peerId
});

room.on('stream', stream => {
// stream.peerId
});

通信モデル

電話モデル(1:1)ルームモデル(n人) の2種類がある。

電話モデル(1:1)

参考: 電話モデル

メディア通信

ビデオ会議、音声通話など。

  • 相手の Peer ID を取得
  • 発信: peer.call(<peer id>)
  • 着信: call.answer()
データ通信

メッセージ送信、ゲーム操作など。

  • 相手の Peer ID を取得
  • 発信: peer.connect(<peer id>)

※勝手に接続が確立するため着信側での処理は不要

ルームモデル(n人)

参考: ルームモデル

ルーム利用の流れ。

  • ルームを作成(or ルーム名を取得)
  • 参加: peer.joinRoom(<room name>)
  • 受信: Room.stream イベントが発火
  • 退出: Room.close()

MeshRoom, SFURoom(Selective Forwarding Unit) の2種類がある。詳細はここを参照

  • Mesh: P2P のフルメッシュ (自分以外の全員と接続)
  • SFU: 中央に存在する SFU サーバに接続

接続時の挙動について

片方(A)が 映像On/音声On、もう片方(B)が 映像On/音声Off(もしくは 映像Off/音声On) の stream を保持している状態だと、calljoinRoom の 処理者/処理順 によって結果が変わってくる。

  • A から B に接続(call): 問題なし(A側では「Bの映像(or 音声)のみ」、B側では「Aの映像と音声」が再生できる)
  • B から A に接続(call): 問題あり(A側では「Bの映像(or 音声)のみ」、B側でも「Aの映像(or 音声)のみ」となる)

joinRoom についても参加順によって類似の事象となった。

MediaStreamTrack.enabled でも 映像/音声 の On/Off はできるので、そちらを使う方が安定性が高そう。詳細は後述。

※iOS SDK, Android SDK でも同じ挙動になるか、モバイルアプリにおける MediaStreamTrack.enabled 相当の API 有無については要確認

音声/映像 の On/Off について

接続中に 音声/映像 の On/Off を切り替える手段は、(Web としては)以下の2つ。

  1. replaceStream を使う
  2. MediaStreamTrack.enabled を変更する

replaceStream は送信データそのものの差し替えで、MediaStreamTrack.enabled は送信データや受信データ内での出力 On/Off。

MediaStreamTrack.enabled を送信側で変更すると、送信側・受信側ともに 黒画面/無音 になる。
MediaStreamTrack.enabled を受信側で変更すると、受信側のみ 黒画面/無音 になる。

replaceStream は動作に癖があり、何度か実施すると(おそらく前の状態に左右されるのか)映像を On にしたら音声が Off になるなど、意図しない状態になることがあった。(※Web 固有の問題、もしくは自分の何らかの考慮漏れの可能性かも)

stream としては 映像On/音声On のデータを送るようにしておき、DataConnectionMeshRoom, SFURoom を使ったメッセージで、MediaStreamTrack.enabled による On/Off を併用するのが無難かと思われる。

※前述の通り、Web 固有かサンプルの誤りかもしれないため、replaceStream で問題なく処理できるなら通信量的にもその方が良い。

※参考: MediaStreamをミュートする

受信のみモードでの接続

1:1

peer.call 時に stream を渡さなければ受信のみモード

Room

peer.joinRoomroomOptionsvideoReceiveEnabled, audioReceiveEnabled を設定する。

もしくは 1:1 と同様に stream を渡さなければ OK

1:1 で通話とテキストメッセージを併用

peer.callpeer.connect を併用する。

peer.call の戻り値は MediaConnection
peer.connect の戻り値は DataConnection

Room でテキストメッセージを併用

MeshRoom.sendSFURoom.send でメッセージ送信可能。

データ送信時に接続している端末のみが受信可能なので、後から入ってきた端末に過去のメッセージ履歴を表示させたい場合には、別の場所にデータを保持しておくなどの仕組みが必要

v-bind で 動画/音声 を再生

参考: vue.jsで複数のvideoタグを扱う - Qiita

:srcObject=stream だと上手く動作しないため、:srcObject.prop=stream にする。

まとめ

  • SkyWay を Vue.js で動作させるサンプルプロジェクトを作成
  • 基本的には公式ページ通りに進めれば OK
  • Tips やハマりポイントも簡単にまとめた

その他・メモ

SkyWay のサンプル実装は他にもあるので、参考にできると思われる。(今回、自分は主に公式ドキュメントしか見てないので、どの程度参考になるかはわからない)

参考文献

関連記事

この記事が参考になった方
ここここからチャージや購入してくれると嬉しいです(ブログ主へのプレゼントではなく、ご自身へのチャージ)
欲しいもの / Wish list