アドベントカレンダー初挑戦です!
SkyWay Media Pipeline Factoryが凄そうだったので試してみました。
チュートリアルを終えたら速攻で詰まったので、単なる紹介記事です! (開き直り)
基本用語
WebRTC: ブラウザ上でリアルタイム通信する技術 (ex. ビデオ通話)
SkyWay: WebRTCを簡単に使うためのプラットフォーム
(いらないのでは? と思いつつも分野外の人に向けて)
SkyWay Media Pipeline Factoryって何?
SkyWay Media Pipeline Factoryとは、NTTが2019年1月に試験提供した、SkyWayの実験的機能です。
SkyWayでやりとりするデータをクラウドに流して、あれこれ加工できるようになります。
音声をクラウドに流す→録音→AIで解析→ログやメトリクスを保存、なんて感じでWebRTCのデータをパイプライン的に加工。しかも、その設定やデプロイをGUIでできる!
...とめっちゃ夢が広がる機能なんですが、まだ試験段階(α版)ということもあり、何でも揃っているわけではありません。
以下、試した内容や感想などを書きます。
試した動機
- WebRTCを使ったビデオ通話の録音・録画をしたかった
- 会社の人に「こんなんあるよ」と教えてもらって、調べたら面白そうだった
試した内容
アカウント作成
→パイプライン(=クラウド上で動く一連の処理)の作成
→デプロイ
→ビデオ通話のサンプルコード(前に作ったやつ)を修正して、パイプラインにデータを送るようにする
→サンプルコードを動かして、パイプラインにデータが飛んでくることを確認
(→自前で音声合成する必要があり、ここで挫折)
パイプラインの作成~デプロイ
公式のGetting Startedに従いました。
ドキュメントに従ってぽちぽちGUIを触るだけで、簡単にデプロイができました。
(ホスティングにはnetlifyが使われているようです)
既存コードの修正
公式のコーディングガイドに従いました。
変更はごく少量。
具体的にはpeer.on("open")イベントの中にパイプラインと接続する処理を足すだけ。
単にデータを送るだけなら、簡単に既存アプリへ組み込めます。
以下は、ブラウザを2窓立ち上げて、両者間でビデオ通話するコード(の大枠)です。
/*
* callする方、される方の共通処理
*/
// 自デバイスの音声、映像を取得
const localStream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: true
});
// Peer(接続管理用オブジェクト)の作成
const peer = (window.peer = new Peer({
key: "自分のSkyWayアプリのAPIキー"
});
// peerができたらパイプラインと接続する(唯一の変更箇所)
- peer.on("open", (id) => {localPeerId = id});
+ peer.on("open", async (id) => {
+ localPeerId = id;
+
+ // デプロイしたパイプラインのAPIを叩いてpeerId(≒パイプラインへ繋ぐ電話番号)とtokenをもらう
+ const entrypoint = "https://userfront.m-pipe.net/↑のデプロイ画面に表示されるエントリポイントのURL/";
+ const body = JSON.stringify({eventParams: {clientId: id}});
+ const res = await fetch(`${entrypoint}/session`, {
+ method: "POST",
+ headers: {
+ "Accept": "application/json",
+ "Content-Type": "application/json"
+ },
+ body
+ });
+ const {token, peerid} = await res.json();
+
+ // パイプラインへ音声・映像を送信
+ peer.call(peerid, localStream, {metadata: {token}});
+ });
/*
* callする方の処理 (変更の必要なし)
*/
// callボタンを押したら、相手へ自分の音声・映像を送信
callButton.addEventListener("click", () => {
if (!peer.open) {
return;
}
// remotePeerIdには、相手のlocalPeerIdを指定
// (パイプラインから帰ってきたpeerIdではない)
const mediaConnection = peer.call(remotePeerId, localStream);
mediaConnection.on("stream", async stream => {
remoteVideoElement.srcObject = stream;
await remoteVideoElement.play().catch(console.error);
});
});
/*
* callされる方の処理 (変更の必要なし)
*/
// callされたら、answerし、相手へ自分の音声・映像を送信
peer.on("call", mediaConnection => {
mediaConnection.answer(localStream);
mediaConnection.on("stream", async stream => {
remoteVideoElement.srcObject = stream;
await remoteVideoElement.play().catch(console.error);
});
});
ポイントは、既存のWebRTC通信とは別にパイプラインへデータを送る用のコネクションを張ることです。
自分相手がそれぞれPeerを作成(localPeerIdを取得)
→パイプラインと接続(パイプラインからpeerIdが返ってくる)
→peerIdではなく、localPeerIdを指定してcall/answerする
p2pに組み込む方法は公式に明確な記述がなく、けっこう躓きました。
ビデオ通話に組み込まれた方の資料を見てようやく"別なんだ!"ということが分かった。
(改めて公式トップページの画像(本記事の最初に張った画像)を見ると、ちゃんと別コネクションになっている。。。)
パイプラインにデータが飛んでくることを確認
GUI操作でログを確認できます。
試してみた感想
- さくっとデプロイできてログとかとれるの凄い
- 既存アプリへ組み入れる際の影響も少なそう
- 現状だとドキュメントやネット上の情報が少なく、チュートリアル以上のことをやろうとすると速攻で詰まる(かなりの腕力を要求される)
- クラウドを使うのでAWS等の知識も必要(この辺弱いのも挫折した一因)
- 作成中の機能とかもあって、まさにα-trial
- 公式トップでは音声の合成やAI解析などのユースケースを挙げているが、現状その辺は自力で解決する必要がある(例えば音声の合成は自前で組む必要がある)
- 実サービスへ組み込むには、公式とがっぷり四つに組む必要がありそう
- ビデオ通話に組み込んだ事例、マジですごい
最後に
このまま発展して、β-trial、そして正式リリースへと至りますよう!
そして、音声合成とかAI解析とかをサクッと使えるようになりますよう。。。