LoginSignup
0
0

More than 1 year has passed since last update.

はじめに

これまで、Amazon Chime SDK, Twillio, Zoom SDK, Janus Gatewayなどを用いてビデオ会議アプリを開発してきました。より幅を広げようと思い、今回初めてTRTC(Tencent Real-Time Communication)を勉強しています。

本稿ではTypescript+ReactでTRTCのビデオ会議アプリを作りはじめるまで(Hello World!的なところまで)に行ったことと、感想をご紹介してきたいと思います。

前提 その1

TRTCを使用したウェブアプリを作成するには、TencentCloudのアカウントを作成する必要があります。こちらにリンクが張られている「アカウント解説手順」に従い、アカウントを作成しておいてください。
フリートライアルでテストで使用する場合は、クレジットカードの登録や免許証の登録はせずに使えるようです。

前提 その2

TRTCのアプリケーションIDとシークレットを生成しておいてください。
下記は生成までの流れですが、この辺のインターフェイスはちょくちょく変わるようなので、現時点(2022/12/23)のものということでご了承ください。

製品のところから、"trtc"と入力すると候補でTencent Real-Time Communicationが表示されるのでこれを選択します。

image.png

無料で始めるをクリックします。
image.png

メニューからApplication Managementを選択するとCreate applicationボタンが表示されるのでそれをクリックします。

image.png

下記のようなワークフローが表示されるので情報を入力していきます。

image.png

新しくアプリを作る場合は、Application TypeはNewでよさそうです。Application Nameは適当なものを入力します。

Download Source Codeでサンプルコードを入手できるようですが、今回はTypescriptで一から作成するつもりなので、そのままNextを押してしまいます。

image.png

すると、下記のようなコンフィギュレーションが表示されます。赤枠のところにこのアプリケーションのSDKAPPIDとSecretKeyが表示されます。これを記憶しておいてください。(管理には十分お気を付けください。)

image.png

ステップ4まで行けば完了です。
image.png

公式のデモリポジトリ

公式のデモリポジトリのフォルダ構成は次のようになっています。

image.png

base-js, base-react-next, quick-demo-js, quick-demo-vue2-js, quick-demo-vew3-tsがサンプルになります。reactのサンプルも既にあります。しかし、ほかのサンプルも同じなのですが、たくさんのTRTCのSDKの機能を実装しているため、これらをそのまま流用していくのは難しそうです。各機能を使用する際に、リファレンスとしてみるのが良いのかなぁ、という感じです。

ということで、今回はこれらのサンプルには触れずに、会議室に入ってビデオ会議を始めるまでのベースライン(Hello World)を、一から組んでいこうと思います。

ドキュメント

公式ドキュメントはこちらにあります。一部中国語の部分もありますが、大半は英語になっているので問題なさそうです。というか、かなり丁寧な説明でわかりやすいです。

準備 その1

SDKをnpmでインストールします。yarnでも行けると思います。

$ npm install trtc-js-sdk --save

準備 その2

実装を進めていくとわかるのですが、というかこれまでの説明でSDKKeyやらSecret Keyの話が出ているので予想はついていると思いますが、TRTCを使用するためにはアプリケーションの認証を行う必要があります(参考)。認証のためのコード生成方法はいくつかあるようですが、テスト用にはリポジトリで公開されているものを使用してよいようですので、今回はこれを使用させていただくこととします。

GenerateTestUserSig.jsから参照されているこのライブラリをダウンロードしておきます。

準備 その3

reactを開発できる環境を整えます。この辺は開発者によって流儀が異なると思いますので、説明は省略します。私の環境を参考にされたい方は、後述するリポジトリをcloneしてnpm installしてください。

実装

それでは、実装を始めていきます。

認証用のライブラリの読み込み

上述した認証用のライブラリを使えるように、アプリのindex.htmlのスクリプトタグで読み込んでおきます。jsフォルダの下に配置している想定です。

<!DOCTYPE html>
<html lang="ja" style="width: 100%; height: 100%; overflow: hidden">
    <head>
        <meta charset="utf-8" />
        <title>TRTC Simple Demo TS</title>
        <script src="./js/lib-generate-test-usersig.min.js"></script> <!-- ★ ここ -->
    </head>
    <body style="width: 100%; height: 100%; margin: 0px">
        <div id="app" style="width: 100%; height: 100%"></div>
    </body>
</html>

認証用のライブラリの型定義(オプション)

認証用ライブラリには型定義がないので定義しておきます。TRTCの本質ではないので、省略可能です。

export interface LibGenerateTestUserSig {
    constructor(SDKAPPID: string, SECRETKEY: string, EXPIRETIME: number)
    genTestUserSig(userId: string)
}

declare global {
    interface Window {
        LibGenerateTestUserSig: new (SDKAPPID: number, SECRETKEY: string, EXPIRETIME: number) => LibGenerateTestUserSig
    }
}

本体

ビデオ会議のHello Worldとしては、こんな感じかなと思います。

HTML上のボタンにより、joinメソッドとleaveメソッドが呼び出されます。

joinメソッド(★1)は、HTML上のusernameとroom idを取得して、認証用のコードを作成します。これらの情報を使用して会議室に入ります。
認証用のコード生成には、SDKAPPKEY(コード内ではSDKAPPIDと読んでる)とSECRETKEYとEXPIRETIMEが必要となります。const.tsで別途定義していますので、上記の手順で入手した情報を使ってください。EXPIRETIMEは適切な値を設定してください。

leaveメソッド(★2)は会議室から退室して、クライアントを消去します。

import React, {  useRef } from "react";
import { createRoot } from "react-dom/client";
import TRTC, { Client } from "trtc-js-sdk"
import { EXPIRETIME, SDKAPPID, SECRETKEY } from "./const";
import "./index.css"

const App = () => {
    const clientRef = useRef<Client>()
    // ★1 joinメソッド
    const join = async () => {
        const usernameInput = document.getElementById("username") as HTMLInputElement
        const username = usernameInput.value
        const roomIdInput = document.getElementById("room-id") as HTMLInputElement
        const roomId = Number(roomIdInput.value)

        const signer = new window.LibGenerateTestUserSig(SDKAPPID, SECRETKEY, EXPIRETIME)
        const sign = signer.genTestUserSig(username)

        clientRef.current = TRTC.createClient({
            sdkAppId: SDKAPPID,
            userId: username,
            userSig: sign,
            mode: 'rtc'
        });

        clientRef.current.on('stream-added', event => {
            if (!clientRef.current) {
                alert("client is not initialized.")
                return
            }
            const remoteStream = event.stream;
            const container = document.getElementById("remote-video-container") as HTMLDivElement
            const divForRemote = document.createElement("div")
            divForRemote.id = `remote-video-${remoteStream.getId()}`
            container.appendChild(divForRemote)
            clientRef.current.subscribe(remoteStream);
        });
        clientRef.current.on('stream-subscribed', event => {
            const remoteStream = event.stream;
            console.log('Subscribed to remote stream successfully:' + remoteStream.getId());
            remoteStream.play(`remote-video-${remoteStream.getId()}`);
        });

        await clientRef.current.join({ roomId: roomId });
        const localStream = TRTC.createStream({ userId: username, audio: true, video: true });
        await localStream.initialize()
        localStream.play('local-video-container');

        await clientRef.current.publish(localStream);
    }

    // ★2 leaveメソッド
    const leave = async () => {
        if (!clientRef.current) {
            alert("client is not initialized.")
            return
        }
        await clientRef.current.leave();
        clientRef.current.destroy();
    }

    // HTMLコンポーネント部分
    return (
        <div className="root-div">
            <div className="header">
                <div className="header-item-container">
                    <div className="header-label">username</div>
                    <input type="text" id="username"></input>
                </div>
                <div className="header-item-container">
                    <div className="header-label">room id</div>
                    <input type="number" id="room-id"></input>
                </div>
                <div className="header-item-container">
                    <div className="header-button" onClick={join}>enter</div>
                </div>
                <div className="header-item-container">
                    <div className="header-button" onClick={leave}>leave</div>
                </div>
            </div>
            <div className="body">
                <div id="remote-video-container"></div>
                <div id="local-video-container"></div>
            </div>
        </div>
    )
}

const container = document.getElementById("app")!;
const root = createRoot(container);
root.render(
    <App></App>
);

以上が、Hello Worldの実装になります。ここまででざっと100行強程度です(cssは別)。

デモ

このアプリはこんな感じで動きます。ちゃんと動いていますね。

リポジトリ

リポジトリは次のところです。

使い方

リポジトリをクローンする。

$ git clone https://github.com/w-okada/trtc-simple-demo-ts.git  -b hello-world

src/const.tsに情報を設定する。

そして、次のコマンドを実行してください。

$ npm install
$ npm run start

表示されたアドレスにブラウザでアクセスしてください。

感想

以上、Typescript+Reactを用いた、TRTCビデオ会議のHello Worldを作ってみました。

Hello Worldを作るまでのところであれば、他のビデオ会議のSDKと比べても、同等レベルかそれ以上に素直なつくりではないかと思います。めちゃくちゃ簡単に作れました。なんとなく、Janus Gatewayに近い感触かな、と思いました。

マニュアルがとてもわかりやすいので、公式のサンプルリポジトリを解析するより、一から作った方が楽だと思います。

TencentCloudを本格的に使うようになると、個人認証で免許証やパスポート情報を入力する必要があるので、そちらの方が心理的にネックな人も多いような気がします。

追記

コンソールでは使用状況・履歴が簡単に見えて楽しい。

image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0