https://d226lax1qjow5r.cloudfront.net/blog/blogposts/custom-video-streams-opentok-api-dr/Publishing-Custom-Video-Streams-with-the-OpenTok-API.png

OpenTok API によるカスタム Video ストリームの公開

最終更新日 May 11, 2021

所要時間:2 分

子供の頃、ホリデーシーズンにはいつも雪の近くにいたいと思っていたが、残念ながらサンフランシスコの近くに住んでいるので、雪が降ることはない。雪が降っているように感じさせるために、OpenTok APIを使ってビデオチャットアプリを作ってみよう。 OpenTok APIを使ってビデオチャットアプリを作ってみましょう!

前提条件

始める前に TokBoxアカウントとAPIプロジェクトのAPI KeyとSecretがあることを確認してください。

アプリの構造

ディレクトリを作成し、好きな名前を付ける:

mkdir publisher-with-snowflakes cd publisher-with-snowflakes

次のコマンドを使って、ディレクトリ内にいくつかのファイルを作成する:

touch index.html index.js

プロジェクト構造はこのようになるはずだ:

publisher-with-snowflakes
├── index.js
├── index.html

プロジェクトを作成したので、OpenTok のコードを index.jsファイルに追加しましょう。

const apiKey = '';
const sessionId = '';
const token = '';

const session = OT.initSession(apiKey, sessionId);
const publisher = OT.initPublisher('publisher');

session.on({
 streamCreated: event => {
   session.subscribe(event.stream);
 },
 sessionConnected: event => {
   session.publish(publisher);
 },
});

session.connect(token, (error) => {
 if (error) {
   console.log(`There was an error connecting to the session ${error.message}`);
 }
});

上のコードでは、初期化した セッションパブリッシャーオブジェクトを初期化しています。 OT.initSessionメソッドと OT.initPublisherメソッドを使用します。次に、セッション・オブジェクトのイベント・リスナーを streamCreatedそして sessionConnectedここで、ストリームが作成されたときにそのストリームを購読し、セッションに接続されたときにストリームを発行します。セッション・イベント・リスナーを設定した後、セッションに接続しようとします。 OpenTok トークン.

さっそく index.jsファイルを index.htmlに追加しましょう。 を追加しましょう。.

<html>
  <head>
    <script src="https://static.opentok.com/v2/js/opentok.min.js"></script>
    <script src="index.js"></script>
  </head>
    <body>
    <div id="publisher"></div>
  </body>
</html>

パブリッシャーの作成方法とセッションで公開する方法がわかったので、カスタム動画ソースを作成する必要があります。 キャンバス APIsnowflake-greenscreen.mp4Video ファイルを使用します。

カスタム・ビデオ・ソース

const closeToGreen = (r, g, b) => {
 // 86, 246, 61
 if (g > (b * 1.4) && g > (r * 1.4)) {
   return true;
 }
 return false;
};

const getCanvasStream = () => {
 let canvas;
 let videoElement;
 let filterVideo;
 let ctx;
 let stopped = false;
 let filterCtx;
 let filterCanvas;
 let cameraCtx;
 let cameraCanvas;

 const drawFrame = () => {
   cameraCtx.drawImage(videoElement, 0, 0, cameraCanvas.width, cameraCanvas.height);
   filterCtx.drawImage(filterVideo, 0, 0, filterCanvas.width, filterCanvas.height);

   const cameraData = cameraCtx.getImageData(0, 0, cameraCanvas.width, cameraCanvas.height);
   const filterData = filterCtx.getImageData(0, 0, filterCanvas.width, filterCanvas.height);
   const res = new Uint8ClampedArray(cameraData.data.length);
   for (let i = 0; i < cameraData.data.length; i += 4) {
     let imgData = cameraData;
     if (!closeToGreen(filterData.data[i], filterData.data[i+1], filterData.data[i+2])) {
       imgData = filterData;
     }
     res[i] = imgData.data[i];
     res[i + 1] = imgData.data[i + 1];
     res[i + 2] = imgData.data[i + 2];
     res[i + 3] = imgData.data[i + 3];
   }
   ctx.putImageData(new ImageData(res, cameraData.width, cameraData.height), 0, 0);
   if (!stopped) {
     requestAnimationFrame(drawFrame);
   } else {
     ctx = null;
   }
 };

 canvas = document.createElement('canvas');
 ctx = canvas.getContext('2d');
 canvas.width = 640;
 canvas.height = 480;

 // Get the Camera video
 OT.getUserMedia({
   audioSource: null
 }).then((stream) => {
   videoElement = document.createElement('video');
   videoElement.srcObject = stream;
   videoElement.play();
   cameraCanvas = document.createElement('canvas');
   cameraCanvas.width = videoElement.width = 640;
   cameraCanvas.height = videoElement.height = 480;
   cameraCtx = cameraCanvas.getContext('2d');

   requestAnimationFrame(drawFrame);
 });

 // Get the filter video
 filterVideo = document.createElement('video');
 filterVideo.setAttribute('loop', true);
 filterCanvas = document.createElement('canvas');
 filterVideo.src = 'snowflake-greenscreen.mp4';
 filterCanvas.width = filterVideo.width = 640;
 filterCanvas.height = filterVideo.height = 480;
 filterVideo.play();
 filterCtx = filterCanvas.getContext('2d');

 return {
   canvas,
   stop: () => {
     stopped = true;
   }
 };
};

上記のコードでは OT.getUserMediaのラッパーである navigator.mediaDevices.getUserMediaのラッパーである MediaStreamオブジェクトを取得します。そして、Video MediaStreamTrackオブジェクトから MediaStreamオブジェクトを使用して canvas に画像を描画します。ビデオを貼り付けた後 MediaStreamTrack雪片フィルターを適用して、キャンバスの画像を修正します。

カメラストリームをキャプチャし、スノーフレークフィルターを追加する仕組みを作ったので、パブリッシャーに videoSourceプロパティを設定しましょう。

const canvasStream = getCanvasStream();
const publisher = OT.initPublisher('publisher', {
  videoSource: canvasStream.canvas.captureStream(30).getVideoTracks()[0],
});

上のコードでは captureStreamオブジェクトの canvasオブジェクトのメソッドを使って MediaStreamオブジェクトを取得し getVideoTracks()[0]を呼び出してVideo MediaStreamTrackオブジェクトを取得している。

セッション内でカスタムビデオの公開を開始するには apiKey, sessionIdtokenの値を追加します!

アプリをロードすると、動く雪の結晶フィルターが付いたカメラのビデオが表示されるはずです:

Video stream with snowflakesVideo stream with snowflakes

既知の制限

  • カスタムストリーミングAPIは、Chrome 51+、Firefox 49+、Safari 11+で動作します。IEやEdgeブラウザでは動作しません。

  • 新しいタブを開いたときなど、ブラウザウィンドウのフォーカスが外れると、Videoは一時停止したり遅くなったりします。

このサンプル・アプリケーションのすべてのコードは こちら.CanvasでOpenTokを使用する他のサンプルは OpenTok-Web-Samplesレポをご覧ください。

シェア:

https://a.storyblok.com/f/270183/384x384/63f654d765/manik.png
Manik Sachdevaヴォネージの卒業生

シニア・ソフトウェア・エンジニア。開発者と協力してAPIを作るのが好き。APIやSDKを構築していないときは、カンファレンスやミートアップで講演している。