Amazon Chime SDKをローカル環境上のReactアプリに組み込んでビデオ会議を表示してみた

2020.10.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部の若槻です。

Amazon Chimeは、オンラインミーティングやビデオ会議を行うためのAWSのサービスですが、 AWSが公式提供するAmazon Chime SDKを使うことで「Amazon Chimeの通信基盤を利用した音声、ビデオ、画面共有などの機能」を自社アプリケーションに組み込むことも可能となります。

このAmazon Chime SDKは、Slack社のSlackコールの機能にも採用されています。

今回は、Amazon Chime SDKの基本的な動作の確認として、Amazon Chime SDKをローカル環境上のReactアプリに組み込んでビデオ会議を表示してみました。

アウトプット

下記のような会議への参加の制御、およびWebカメラで撮影している映像の表示を行う最低限の構成のReactアプリを作成してみました。(今回はアプリをローカル環境で実行しているだけなので複数人での会議参加はできない構成となっています。) image

ソースコードはGitHubの下記Repositoryに公開してあります。

やってみた

Amazon Chime SDKをローカル環境上のReactアプリに組み込んでみます。なお、コードは主に次のドキュメントで紹介されているものを参考にしています。

環境

アプリの作成、実行を行った環境のOS、Node,js、npmのバージョンは次の通りです。

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H2
% node -v
v12.14.0
% npm -v
6.13.4

Reactアプリの新規作成

Reactアプリを新規作成します。

% npx create-react-app react-amazon-chime-sdk

Amazon Chime SDKの追加

ReactアプリへのAmazon Chime SDKの組み込みに必要なライブラリを追加します。

% npm install amazon-chime-sdk-component-library-react amazon-chime-sdk-js styled-components styled-system

AWS SDKの追加

aws-sdkを追加します。後述するmy-server.jsを実行して、会議参加に必要な情報を取得するために必要となります。

% npm install aws-sdk

App.jsの更新

src/App.jsの記述を次の内容で更新します。

src/App.js

import { useMeetingManager } from "amazon-chime-sdk-component-library-react";
import React from "react";
import "./index.css";
import { ThemeProvider } from "styled-components";
import {
  MeetingProvider,
  lightTheme,
  VideoTileGrid,
  useLocalVideo,
  Grid,
} from "amazon-chime-sdk-component-library-react";

const MeetingManager = () => {
  const meetingManager = useMeetingManager();

  const joinMeeting = async () => {
    // Fetch the meeting and attendee data from your server
    //const response = await fetch("/my-server");
    //const data = await response.json();

    var data = require('./temp-join-config.json');
    const joinData = {
      meetingInfo: data.Meeting,
      attendeeInfo: data.Attendee,
    };

    // Use the join API to create a meeting session
    await meetingManager.join(joinData);

    // At this point you can let users setup their devices, or start the session immediately
    await meetingManager.start();
  };

  return <button onClick={joinMeeting}>Join</button>;
};

const LocalVideoToggle = () => {
  const { isVideoEnabled, toggleVideo } = useLocalVideo();

  return (
    <button onClick={toggleVideo}>
      {isVideoEnabled ? "Stop your video" : "Start your video"}
    </button>
  );
};

const App = () => {
  return (
    <ThemeProvider theme={lightTheme}>
      <MeetingProvider>
        <MeetingManager />
        <LocalVideoToggle />
        <Grid style={{ height: "30vh" }}>
          <VideoTileGrid
            noRemoteVideoView={<div>No one is sharing his video</div>}
          />
        </Grid>
      </MeetingProvider>
    </ThemeProvider>
  );
};

export default App;

MeetingManagerでは会議および参加者情報を取得するボタンコンポーネントを定義しています。実際の構成では会議および参加者情報はAPIなどを経由してサーバー上から取得することになりますが、今回はローカル上で動作させるために./temp-join-config.jsonファイルから情報を取得するようにしています。

const MeetingManager = () => {
  const meetingManager = useMeetingManager();

  const joinMeeting = async () => {
    // Fetch the meeting and attendee data from your server
    //const response = await fetch("/my-server");
    //const data = await response.json();

    var data = require('./temp-join-config.json');
    const joinData = {
      meetingInfo: data.Meeting,
      attendeeInfo: data.Attendee,
    };

    // Use the join API to create a meeting session
    await meetingManager.join(joinData);

    // At this point you can let users setup their devices, or start the session immediately
    await meetingManager.start();
  };

  return <button onClick={joinMeeting}>Join</button>;
};

LocalVideoToggleでは会議参加の開始/停止をトグルできるボタンコンポーネントを定義しています。

const LocalVideoToggle = () => {
  const { isVideoEnabled, toggleVideo } = useLocalVideo();

  return (
    <button onClick={toggleVideo}>
      {isVideoEnabled ? "Stop your video" : "Start your video"}
    </button>
  );
};

Appでは画面表示するコンポーネントたちをまとめています。ThemeProviderMeetingProviderはChime SDKのルートコンポーネントとする必要があります。Gridは会議映像の表示領域を制御し、実際の映像の表示はVideoTileGridにより行われます。

const App = () => {
  return (
    <ThemeProvider theme={lightTheme}>
      <MeetingProvider>
        <MeetingManager />
        <LocalVideoToggle />
        <Grid style={{ height: "30vh" }}>
          <VideoTileGrid
            noRemoteVideoView={<div>No one is sharing his video</div>}
          />
        </Grid>
      </MeetingProvider>
    </ThemeProvider>
  );
};

my-server.jsの作成

./my-server.jsを作成して次の内容を記述します。このスクリプトを実行することによりAmazon Chime SDKでの会議参加に必要な情報を取得することができます。

./my-server.js

const AWS = require("aws-sdk");

const region = "ap-northeast-1";

const chime = new AWS.Chime({
  region: "us-east-1",
  endpoint: "service.chime.aws.amazon.com",
});

const createMeetingUrl = async () => {
  const { Meeting } = await chime
    .createMeeting({
      ClientRequestToken: Date.now().toString(),
      MediaRegion: region,
    })
    .promise();

  const { Attendee } = await chime
    .createAttendee({
      MeetingId: Meeting.MeetingId,
      ExternalUserId: Date.now().toString(),
    })
    .promise();

  console.log(JSON.stringify({
    Meeting: Meeting,
    Attendee: Attendee,
  }, null, 2));
};

createMeetingUrl()

アプリを使ってみる

作成したReactアプリを実際にローカル環境で起動して使ってみます。

まず、次の記事などを参考にAWSのクレデンシャル情報をセットしておきます。

そして、my-server.jsを実行し、取得した会議参加情報をsrc/temp-join-config.jsonに書き込みます。

% node ./my-server.js >> ./src/temp-join-config.json

src/temp-join-config.jsonが作成され、ファイルには次のような会議(Meeting)および参加者(Attendee)の情報が書き込まれます。

./src/temp-join-config.json

{
  "Meeting": {
    "MeetingId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "ExternalMeetingId": null,
    "MediaPlacement": {
      "AudioHostUrl": "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.k.m1.an1.app.chime.aws:3478",
      "AudioFallbackUrl": "wss://haxrp.m1.an1.app.chime.aws:443/calls/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "ScreenDataUrl": "wss://bitpw.m1.an1.app.chime.aws:443/v2/screen/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "ScreenSharingUrl": "wss://bitpw.m1.an1.app.chime.aws:443/v2/screen/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "ScreenViewingUrl": "wss://bitpw.m1.an1.app.chime.aws:443/ws/connect?passcode=null&viewer_uuid=null&X-BitHub-Call-Id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "SignalingUrl": "wss://signal.m1.an1.app.chime.aws/control/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "TurnControlUrl": "https://ccp.cp.ue1.app.chime.aws/v2/turn_sessions"
    },
    "MediaRegion": "ap-northeast-1"
  },
  "Attendee": {
    "ExternalUserId": "000000000000",
    "AttendeeId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
    "JoinToken": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
  }
}

アプリを起動します。

% npm start

ブラウザで起動したアプリで[Join]をクリックします。 image

PCにWebカメラがあれば起動して撮影状態となります。

[Start your video]をクリックします。 image

Webカメラの映像をWebアプリ上にタイル表示できました。 image

※なお、[Start your video]をクリックしても映像が映らない場合は、[Stop your video]をクリックして撮影を停止してから再度[Start your video]をクリックすると映るようになる場合があります。

おわりに

Amazon Chime SDKをローカル環境上のReactアプリに組み込んでビデオ会議を表示してみました。

今回はAmazon Chime SDKの基本的な動作確認でしたので、次回はアプリをAWS上に配置して複数人でWeb会議をできるようにしてみます。

参考

以上