C#でTencent TRTC SDK使ってみた！

Qiita初投稿＆初アドベントカレンダーとなります！

そして初めてのTencent Cloud!

今回はC#でTencent CloudのTencent Real-Time Communication（TRTC）を使ってみた感想を書いていきたいと思います。

# Tencent Cloudとは
 Tencentと聞いて私が一番最初に思い浮かんだのは[League of Legends](https://www.leagueoflegends.com/ja-jp/)(LoL)でした。
LoLと言えば、世界で一番プレイされているゲームです。こちらの記事によるとLoLのプレイヤー人口は世界で１億人いるそうです。

それだけ多くの人が安定してプレイできる環境を実現する技術が使える！というのがTencent Cloudの魅力ですね。

## 提供サービス
提供されているサービスは他のクラウドサービスと同様に、[Virtual Machine](https://www.tencentcloud.com/jp/products/cvm)系や[Storage](https://www.tencentcloud.com/jp/products/cos)系などがありますが、
特徴的なサービスはビデオやストリーミング、ゲーム系のサービスになると思います。

今回試しに使ってみるTRTCもビデオサービスに区分されます。ビデオサービスにはTRTC以外にも
[Video on Demand](https://www.tencentcloud.com/jp/products/vod)と言ったワンストップ配信サービスや昨今とても人気であるショート動画用のサービスとして[User Generated Short Video SDK](https://www.tencentcloud.com/jp/products/ugsv)なども提供されています。

こういったオーディオビデオ系のサービスを実際に作るとなると基盤の構築も難しく、安定した提供を実現するというのは簡単なことではないと思います。
AWSやGCP、Azureにも近しいサービスが提供されていますが、Tencent Cloudは他のクラウドサービスよりもビデオサービスに力が入っていると感じました。


以下ビデオサービス一覧です。
<dl>
  <dt>Tencent Real-Time Communication</dt>
  <dd>Demoを1分以内に実行し、30分で音声通話、ビデオ通話、インタラクティブストリーミングソリューションを構築できます</dd>
  <dt>Cloud Streaming Services</dt>
  <dd>超高速、安定、プロフェッショナルなクラウド型ライブストリーミングオペレーションサービス</dd>
  <dt>Video on Demand</dt>
  <dd>ワンストップメディアトランスコーディング配信プラットフォーム</dd>
  <dt>Media Processing Service</dt>
  <dd>専門的なビデオトランスコーディングやウォーターマークなどのVideo Cloudサービス</dd>
  <dt>User Generated Short Video SDK</dt>
  <dd>ユーザーがモバイル向けのショート動画アプリケーションを手軽に作成する際に役立ちます</dd>
  <dt>StreamLive</dt>
  <dd>安定した高品質の放送グレードのライブブロードキャストサービス</dd>
  <dt>StreamPackage</dt>
  <dd>安定した、安全で効率的なメディアパッケージサービス</dd>
  <dt>StreamLink</dt>
  <dd>グローバルユーザー向けの高速で信頼性の高いリアルタイムビデオ伝送サービス</dd>
  <dt>Media Processing Service</dt>
  <dd>専門的なビデオトランスコーディングやウォーターマークなどのVideo Cloudサービス</dd>
  <dt>Tencent Effect SDK</dt>
  <dd>美顔、フィルター、ステッカーなど、高度なビデオ処理プラン</dd>
</dl>

# TRTC利用方法
Tencent Cloud 登録方法は[こちら](https://marketing-material-1301344332.cos.ap-seoul.myqcloud.com/TencentCloud%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E7%99%BB%E9%8C%B2%E6%89%8B%E9%A0%86.pdf)に記載の通りです。

実際に登録＆アプリケーションの生成をした時のスクリーンショットを載せておきますので参考になれば！
## 利用登録
Tencent Cloud は以下になります。

https://www.tencentcloud.com/jp/

![2022-12-03_16h44_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/5e5f51f6-5b9d-9a82-da40-efe97d2d3d58.png)

![2022-12-03_16h58_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/7783dd1e-677c-8372-7a79-9d2daf52f055.png)

![2022-12-03_17h08_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/ac500318-f06f-b17e-a09f-f67d081a73f9.png)

![2022-12-03_17h14_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/d307e623-0d15-03fd-5b05-1e68d95d541a.png)

![2022-12-03_17h16_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/ffa16619-351c-cb2f-4664-c73c0ff8da6a.png)

以上で利用登録完了です！

## TRTC利用
TRTCの利用手順については以下に公式ドキュメントがあります。参考にしてください。

https://www.tencentcloud.com/jp/document/product/647/39386


まずはコンソールにアクセスします。
![2022-12-11_16h39_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/ec488323-fd2a-44b4-3626-cd81512d6ec5.png)


次に今回利用するTRTCを探します。
![2022-12-11_16h41_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/d56079d9-7377-3ae9-916a-23ea5abb0bd5.png)

こちらがTRTCの構成画面になります。画像はインスタンスって書いてますが、アプリケーションを生成します。
![2022-12-11_16h43_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/f752f00c-6d16-c641-fd5a-261c4a9001b4.png)

後は必要に応じて名前や設定を指定していきます。
![2022-12-11_16h44_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/7fd34aef-9e54-12e3-5e00-75db75f9dec5.png)

![2022-12-11_16h45_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/45f3d64e-74a0-a05a-1e71-5a634631ba9a.png)

![2022-12-11_16h48_15=2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/c6171176-a087-f2e2-80f7-a68f8e701e16.png)

**ここまで淡々と進めていましたが、私はこの画面で凍り付きました。。**
![2022-12-11_16h48_15_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/f358eec0-7d6b-43c5-b507-b603ffa5ec78.png)
**そう、何故なら私の今回のタイトルで予告しているC#用のSDKが用意されていないではないですか！**
![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/643ebf98-7aad-0ce0-b5b2-0027c1ae1f92.jpeg)
やばい..!　C#でTRTC SDK使ってみた！が出来なくなるどうしよう。。
Electronに予定変更するか。。と思いつつもとりあえずTRTCの作成を完了させました。
C#のSDKについては後述します。

![2022-12-11_16h49_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/110c4d7e-775f-d571-c19d-cf3c6d9121cb.png)

# TRTC SDKを使って簡単なアプリケーションを作成
とりあえず簡単なビデオ会議アプリケーションを作ってみます。
とは言いつつも先ほどの選択にはC#でTRTC SDKを試すことが出来ない感じがしました。。

本当にC#用のSDKを探してみたところ.....

なんとありました！！
以下のTRTCクイックスタート製品ドキュメントを見ると、C#のクイックスタートが載っているではないですか！！
で、どこにあるのかと言うとWindows用のSDKにあるようです。
少し考えればわかることなんですが、あの選択肢のところには(C++)って書いてあったから。。。

何はともあれC#で使ってみたができそうです！

https://main.qcloudimg.com/raw/document/intl/product/pdf/647_35082_jp.pdf


## 開発環境
* Microsoft Windows [Version 10.0.19045.2364]
* Visual Studio 2022 Community
* .Net 6

## SDKのダウンロード

以下のページからSDKをとってきましょう。

https://www.tencentcloud.com/jp/document/product/647/34615

必要な部分のみピックアップしますが、ファイル構成は以下のようになっています。
>TXLiteAVSDK_TRTC_Win_latest/
　├ CSharpDemo/
　├ DuilibDemo/
　├ MMFCDemo/
  　├ QRDemo/
  　├ WPFDemo/
  　└ SDK/
     　　　├ CPlusPlus/
　 　　　　└ CSharp/
         　　　　　　　├ Win32/
　       　　　　　　└ Win64/


必要になるのはCSharp以下のWin32又はWin64になります。

## コード
今回は、WPFでアプリケーションを作成していきます。
また、１から作るも大変なのでサンプルから色々拝借して作っていこうと思います。
以下のファイルをサンプルから拝借します。
* TXLiteAVVideoView.cs
* GenerateTestUserSig.cs
* DataManager.cs

それぞれ、Viewにレンダリングをする処理、セキュリティ保護署名を生成する処理、デバイス情報などを操作する処理を行います。

また、Tencent Cloud で作成したTRTCアプリケーションにアクセスできるように、
GenerateTestUserSig.csにSDkAppIDとSecretKeyを入力しておきます。
```cs:GenerateTestUserSig.cs(一部抜粋)

          class GenerateTestUserSig
    {
        /// <summary>
        /// Tencent Cloud SDKAppIdは、ご自身のアカウントのSDKAppIdに置き換える必要があります。
        /// 
        /// Tencent Cloud Communications [console](https://console.cloud.tencent.com/avc)にアクセスして、アプリケーションを作成すると、SDKAppId
        /// </summary>
        /// <remarks>
        /// Tencent Cloudが顧客を区別するために使用する一意の識別子です。
        /// </remarks>
        public const int SDKAPPID = 0;

        /// <summary>
        /// 署名用の暗号鍵の計算
        /// 
        /// Step1.Tencent Cloud Live Audio and Video[Console](https://console.cloud.tencent.com/rav)にアクセスし、まだアプリケーションがない場合は作成してください。
        /// Step2.アプリケーション設定」をクリックして基本設定画面を表示し、「勘定系システム連携」の項目を探します。
        /// Step3. "View Key "ボタンをクリックすると、UserSigの計算に使われた暗号鍵が表示されますので、それを以下の変数にコピーしてください。
        /// </summary>
        public const string SECRETKEY = @"";
```
:::note warn
本来であれば、SDkAppIDとSecretKeyの直打ちは適切ではありません。
今回はSDKを使うことが目的なためこのような処置をしています。
:::

### 入室処理
入室画面は簡易的にこのようなレイアウトにしました。
というより、サンプルとほとんど同じにしました。
ただ、それだけだと寂しいのでMaterial Designを使ってちょっと良い感じにしています。
![スクリーンショット 2022-12-16 222324.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/f42bf501-9269-d354-fccb-5f79fe2d00a3.png)

入室処理は入力されたUserIDよりUserSigを生成し、問題なく生成が完了すれば会議部屋へ移行します。

```cs:LoginWindow.xaml.cs(一部抜粋)

            string userId = this.userTextBox.Text;
            string roomId = this.roomTextBox.Text;
            if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(roomId))
            {
                ShowMessage("部屋番号やユーザー番号を空にすることはできません！");
                return;
            }

            DataManager.GetInstance().userId = userId;
            DataManager.GetInstance().roomId = uint.Parse(roomId);

            //  userId に対応する userSig を得る．            
            string userSig = GenerateTestUserSig.GetInstance().GenTestUserSig(userId);
            if (string.IsNullOrEmpty(userSig))
            {
                ShowMessage("userSigの取得に失敗しました。アカウント情報が記入されているか確認してください！");
                return;
            }

            MainWindow mainWindow = new MainWindow();
            mainWindow.Show();
            mainWindow.EnterRoom();
            this.Close();
```

### ビデオ通話処理
通話画面にはLabelとWrapPanelしかコントロールを配置していません。
WrapPanelをAddCustomVideoViewに渡すことで通話画面とコントロールにバインドしてくれます。

![スクリーンショット 2022-12-16 222400.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/acf9b1dc-80cb-8359-20a5-0208ccce62ff.png)

ManageLiteAV.dllを参照し、ITRTCCloudCallbackを継承します。
このインターフェースにはTRTCコールバック用になるため、必要なコールバックに必要な処理を書いていきます。
会議部屋に入室したときに、コールされるEnterRoomメソッドに下記の処理を加えます。
これらの処理は会議部屋へ入室通知やパラメータの設定を行います。
プロパティの中にはビューティー関連もあるため、フィルターなどの設定も行えるのかもしれません。

```cs:MainWindow.xaml.cd(一部抜粋)
 public void EnterRoom()
        {
            // 入室時に必要な関連パラメータを設定する
            TRTCParams trtcParams = new TRTCParams();
            trtcParams.sdkAppId = GenerateTestUserSig.SDKAPPID;
            trtcParams.roomId = DataManager.GetInstance().roomId;
            trtcParams.userId = DataManager.GetInstance().userId;
            trtcParams.userSig = GenerateTestUserSig.GetInstance().GenTestUserSig(DataManager.GetInstance().userId);
           
            // プロジェクトで音声のみのバイパスライブストリーミングが必要な場合、パラメータを設定する。
            // このパラメータを設定すると、音声がサーバーに到達し、自動的にバイパスが開始されます。
            // このパラメータがない場合、バイパスは最初のビデオフレームを受信する前に受信したオーディオパケットを破棄します。
            if (DataManager.GetInstance().pureAudioStyle)
            {
                trtcParams.businessInfo = "{\"Str_uc_params\":{\"pure_audio_push_mod\": 1}}";
            }
            else
            {
                trtcParams.businessInfo = "";

            // ユーザーによる入退室
            mTRTCCloud.enterRoom(ref trtcParams, DataManager.GetInstance().appScene);

            // デフォルトのパラメータ構成を設定する
            TRTCVideoEncParam encParams = DataManager.GetInstance().videoEncParams;   // ビデオエンコードパラメーター設定
            TRTCNetworkQosParam qosParams = DataManager.GetInstance().qosParams;      // ネットワークフロー制御関連のパラメータ設定
            mTRTCCloud.setVideoEncoderParam(ref encParams);
            mTRTCCloud.setNetworkQosParam(ref qosParams);
            mTRTCCloud.setLocalViewFillMode(DataManager.GetInstance().videoFillMode);
            mTRTCCloud.setLocalViewMirror(DataManager.GetInstance().isLocalVideoMirror);
            mTRTCCloud.setLocalViewRotation(DataManager.GetInstance().videoRotation);
            mTRTCCloud.setVideoEncoderMirror(DataManager.GetInstance().isRemoteVideoMirror);

            // セットビューティー
            if (DataManager.GetInstance().isOpenBeauty){
                mTRTCCloud.setBeautyStyle(DataManager.GetInstance().beautyStyle, DataManager.GetInstance().beauty,
                    DataManager.GetInstance().white, DataManager.GetInstance().ruddiness);
            }

            //サイズフローを設定する
            if (DataManager.GetInstance().pushSmallVideo)
            {
                TRTCVideoEncParam param = new TRTCVideoEncParam
                {
                    videoFps = 15,
                    videoBitrate = 100,
                    videoResolution = TRTCVideoResolution.TRTCVideoResolution_320_240
                };
                mTRTCCloud.enableSmallVideoStream(true, ref param);
            }
            if (DataManager.GetInstance().playSmallVideo)
            {
                mTRTCCloud.setPriorRemoteVideoStreamType(TRTCVideoStreamType.TRTCVideoStreamTypeSmall);
            }
            // 部屋情報
            mUserId = trtcParams.userId;
            mRoomId = trtcParams.roomId;
            this.infoLabel.Content = "部屋番号：" + mRoomId;

            // ネイティブ・メインストリームのカスタムレンダリング ビューは動的にバインドされ、SDKのレンダリングコールバックをリッスンします。
            mTRTCCloud.startLocalPreview(IntPtr.Zero);
            AddCustomVideoView(this.videoContainer, mUserId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, true);

            mTRTCCloud.startLocalAudio();
        }

```

### 詰まったポイント
今回、TRTC SDKを利用していく中で詰まったのはManageLiteAV.dllへの参照です。
DLLへの参照が通らず、何度もコンパイルではじかれました。。

解決方法はTRTCクイックスタート製品ドキュメントに記載されています。
結構な時間詰まっていたので、公式のドキュメントは一番最初に確認すべきだと感じました。。
下記のように、プロジェクトファイルに追記してください。
```cs:.csproj
//それぞれのプラットフォームの下に引用を追加します
<Reference Include="ManageLiteAV" Condition="'$(Platform)' == 'x64'">
<HintPath>SDK\CSharp\Win64\lib\ManageLiteAV.dll</HintPath>
</Reference>
<Reference Include="ManageLiteAV" Condition="'$(Platform)' == 'AnyCPU'">
<HintPath>SDK\CSharp\Win64\lib\ManageLiteAV.dll</HintPath>
</Reference>
<Reference Include="ManageLiteAV" Condition="'$(Platform)' == 'x86'">
<HintPath>SDK\CSharp\Win32\lib\ManageLiteAV.dll</HintPath>
</Reference>
```

# 使ってみた感想
TRTC SDK とサンプルプログラムがあれば簡単にWeb会議アプリケーションを作ることができました。
WPF用にもしっかりUIが用意されている点の非常に良いですね！
.Net MAUIにも使うことが出来れば複数のプラットフォームに一斉展開できるので夢が広がります。

また、ドキュメントやコメントが中国語というのも新鮮でした！
他のビデオサービス（User Generated Short Video SDKやStreamLive等）も是非使ってみたいと思います。

# 後日談
一通りTRTC SDKを使った後にTRTC SDKアプリケーションを停止→削除しようとしたら、
なぜかうまく“停止”が出来ませんでした。

ブラウザを変えても、端末を変えても、日にちを変えても停止が出来ない始末。
そのままにしておくは怖いので、Ticketを発行して助けを求めました。
![2022-12-24_09h59_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521565/460259d6-f2b1-c2aa-1d3a-50fbe891e57b.png)
すぐに対応してもらえるか不安でしたが、思いのほか直ぐに対応してもらえ無事に停止してもらうことが出来ました。
また、日本語での対応もあり、サポートも手厚いように感じます。







# 成果物

https://github.com/soeatu/TencentCloud_TRTC

# おわりに
最後まで目を通していただきありがとうございます！