チュートリアル

本章では Sora JavaScript SDK を使って音声と映像を送受信できる簡単なサンプルを作成します。

プロジェクトの作成

開発環境ツールとして Vite を利用します。 無理に Vite を利用する必要は無く、慣れたツールを利用してください。

パッケージマネージャーとしては pnpm を利用していますが、 npm または yarn でも問題ありません。

$ pnpm create vite@latest
✔ Project name: … sora-js-sdk-tutorial
✔ Select a framework: › Vanilla
✔ Select a variant: › TypeScript

Scaffolding project in /private/tmp/sora-js-sdk-tutorial...

Done. Now run:

  cd sora-js-sdk-tutorial
  pnpm install
  pnpm run dev
tree
.
├── index.html
├── package.json
├── public
│   └── vite.svg
├── src
│   ├── counter.ts
│   ├── main.ts
│   ├── style.css
│   ├── typescript.svg
│   └── vite-env.d.ts
└── tsconfig.json

sora-js-sdk の追加

$ pnpm add -D -E sora-js-sdk

vite と typescript を最新にする

$ pnpm up vite@latest typescript@latest

index.html の変更

  • connectButton は接続ボタン

  • disconnectButton は切断ボタン

  • localVideo は自分が取得した映像を出力する

  • remoteVideos は他の映像を表示する

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Vite + TS + Sora JS SDK</title>
</head>

<body>
  <button id="connectButton">Connect</button>
  <button id="disconnectButton" disabled>Disconnect</button>
  <hr />
  <video id="localVideo" autoplay="" playsInline="" controls="" muted=""></video>
  <hr />
  <div id="remoteVideos"></div>

  <script type="module" src="./src/main.ts"></script>
</body>

</html>

.env.local の作成

.env.local ファイルを作成してください。

$ touch .env.local

その後 Sora のシグナリング URL やチャネル ID、必要があればアクセストークンを指定してください。

VITE_SORA_SIGNALING_URL=wss://sora.example.com/signaling
VITE_SORA_CHANNEL_ID=sora-js-sdk
VITE_ACCESS_TOKEN=

main.ts の変更

import Sora from "sora-js-sdk";
import type { ConnectionPublisher } from "sora-js-sdk";

const connectButton =
  document?.querySelector<HTMLButtonElement>("#connectButton")!;
const disconnectButton =
  document?.querySelector<HTMLButtonElement>("#disconnectButton")!;
const localVideo = document?.querySelector<HTMLVideoElement>("#localVideo")!;
const remoteVideos = document?.querySelector<HTMLDivElement>("#remoteVideos")!;

let sendrecv: ConnectionPublisher;

connectButton?.addEventListener("click", async () => {
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: false,
    video: true,
  });
  const debug = true;
  // .env からシグナリング URL を取得する
  const signalingUrl = import.meta.env.VITE_SORA_SIGNALING_URL;
  // .env からチャネル ID を取得する
  const channelId = import.meta.env.VITE_SORA_CHANNEL_ID;
  const metadata = {
    // sora-labo や sora-cloud のアクセストークン
    access_token: import.meta.env.VITE_ACCESS_TOKEN,
  };
  const options = {
    multistream: true,
  };
  const soraConnection = Sora.connection(signalingUrl, debug);
  sendrecv = soraConnection.sendrecv(channelId, metadata, options);
  sendrecv.on("track", (event) => {
    const stream = event.streams[0];
    const remoteVideoId = `remoteVideo-${stream.id}`;
    if (!document.querySelector(`#${remoteVideoId}`)) {
      const video = document.createElement("video");
      video.id = remoteVideoId;
      video.autoplay = true;
      video.playsInline = true;
      video.srcObject = stream;
      remoteVideos?.appendChild(video);
    }
  });
  sendrecv.on("removetrack", (event) => {
    // removetrack は MediaStream で発火する
    const target = event.target as MediaStream;
    const remoteVideo = document.querySelector(`#remoteVideo-${target.id}`);
    if (remoteVideo) {
      // target は mediaStream なので target.id は mediaStream.id と同じ
      remoteVideo.remove();
    }
  });
  await sendrecv.connect(stream);
  localVideo.srcObject = stream;

  connectButton.disabled = true;
  disconnectButton.disabled = false;
});

disconnectButton?.addEventListener("click", async () => {
  // sendrecv があるかどうか確認する
  if (sendrecv) {
    // 切断する
    await sendrecv.disconnect();
    localVideo.srcObject = null;

    while (remoteVideos?.firstChild) {
      remoteVideos.removeChild(remoteVideos.firstChild);
    }
  }

  connectButton.disabled = false;
  disconnectButton.disabled = true;
});

起動

$ pnpm run dev
VITE v5.1.3  ready in 535 ms

➜  Local:   http://localhost:5173/
➜  Network: use --host to expose
➜  press h + enter to show help

http://localhost:5173/ へアクセスして、ブラウザのタブをふたつ以上開いて、 Connect ボタン を押して、双方向で配信ができていれば成功です。

© Copyright 2023, Shiguredo Inc. Created using Sphinx 7.2.6