1. はじめに
この記事は「Qiita Engineer Festa 2022」に参加するための記事です。
初めまして。
株式会社レイという映像機材を扱う会社でエンジニアをしています。
普段はTouchDesignerやUnrealEngineを使って、
映像オペレーションのシステムやXR表現の研究・開発をしています。
今回はZoomAPI/SDKとTouchDesignerを組み合わせた、
Zoomオペレーションシステムをプロトタイピングしました。
2.システム環境
- Windows10
- Geforce RTX 3060
- node: v16.15.1
- npm: 8.11.0
- TouchDesinger: 2022.25370
- UnrealEngine: 4.27.2
3. 映像屋が抱えるZoomオペの課題
私たちが企業の表彰式などの現場でオペレーションをする時、
表彰者の映像を扱うためZoomを利用することが多くあります。
その際表彰者をピン留めして不要な部分をクロップし、
メインオペレーターのスイッチャーなどに出力します。
しかし、この方法だと表彰者の数だけピン留めが必要ですし、
PCごとにZoomの設定を毎回の現場でする必要がありました。
またその分作業員も必要なので、物的・人的コストが掛かります。
(ズラァ...)
この課題を、ZoomAPI/SDKを活用することで解決できないかと考えました。
4. ZoomAPI/SDKの機能選定
初めはRaw Video
が取得できるというVideo SDK
の利用を検討しました。
しかし、Video SDK
は通常のミーティングとの互換性が無いようです。
VideoSDKで実現できる映像音声通話は個別の通信としての扱いになるため通常のZoomミーティングやウェビナーとは互換性がありません。そのため、VideoSDKで生成された通話識別子(Session Name)へは通常のZoomクライアント及びMeetingSDKからは参加接続できないものとなります。
なので、通常のミーティングにも参加できるMeeting SDK
を利用する方針にしました。
5. MeetingSDKを利用した映像の取得
今回はプロトタイピングですので、公式のサンプルをそのまま利用します。
参考にしたのは、こちらの記事とGithubのリポジトリです。
導入方法は上記記事とREADMEのままなので、割愛します。
npm start
すると127.0.0.1:9999
で入室前の画面が立ち上がるので、
事前に立ち上げた部屋の番号とパスワードを入力して、Join
を押します。
(必要に応じて名前の変更と言語を日本語に設定して下さい)
URLはJoin
を押すたびに異なるものが発行されるので、
これを必要な分だけ繰り返せば、1台のPCで複数の人を管理することが出来ます。
別タブで立ち上がったURLを、Pallete/Tools
にあるWeb Browser
に入力します。
(Web Render TOP
だと画面が操作出来ないので、Web Browser
を使います)
これでZoomミーティングの部屋をTouchDesigner内で操作が出来るようになります。
URLは手入力でベタ打ちしても良いのですが、数が多いと面倒なので、
Fetch API
を使ってTouchDesignerに直接渡します。(Fetch API
の理由は後述)
6. FetchAPIによるURLの送受信
発行されたURLは、http通信でTouchDesignerに渡します。
http
やXMLHttpRequest
を試しましたが、CORS
に弾かれてしまいました。
HTTPレスポンスヘッダにAccess-Control-Allow-Origin
を付加すれば
通せるようなのですが、今回の検証段階では上手くいきませんでした。
そこでfetch関数の引数にmode: "no-cors"
を加えたところ、回避出来ました。
以下、サンプルのコードjs/index.js
の103行目~に追記した箇所になります。
var signature = ZoomMtg.generateSDKSignature({
meetingNumber: meetingConfig.mn,
sdkKey: SDK_KEY,
sdkSecret: SDK_SECRET,
role: meetingConfig.role,
success: function (res) {
console.log(res.result);
meetingConfig.signature = res.result;
meetingConfig.sdkKey = SDK_KEY;
var joinUrl = "/meeting.html?" + testTool.serialize(meetingConfig);
console.log(joinUrl);
// 別タブが開く必要が無いので、コメントアウト
// window.open(joinUrl, "_blank");
jsonData = {key: joinUrl};
postUrl = 'http://127.0.0.1:9980';
fetch( postUrl, {
method: 'POST',
mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(jsonData),
})
.then(response => response.json())
.then(data => {
console.log('Success:', jsonData);
})
.catch((error) => {
console.error('Error:', error);
});
},
});
普段JavaScriptは全く書かないので、書き方はMDN Web Docsの通りです。
あくまでローカルネットワーク内でURLを渡すだけなので問題無いと思いますが、
本番環境では、CORS
の仕組みをしっかり理解した上で実装します。(自戒)
POSTしたURLは、TouchDesignerのWeb Server DAT
で受け取ります。
以下、Web Server DAT
に紐づいているコールバックのオペレータに追記した箇所です。
import json
# URLを保持するためのTable DAT
table = op("table1")
def onHTTPRequest(webServerDAT, request, response):
response['statusCode'] = 200 # OK
response['statusReason'] = 'OK'
response['data'] = '<b>TouchDesigner: </b>' + webServerDAT.name
get_data = request['data']
load_data = json.loads(get_data)
value_data = load_data['key']
table.appendRow("http://127.0.0.1:9999" + value_data)
return response
後はTable DAT
に入るURLをWeb Browser
にリファレンスすれば完了です。
7. TouchDesingerでの映像演出
せっかくTouchDesignerを使っているので、
簡単なインタラクティブ演出を加えていきます。
Face Tracking CHOP
を使って顔の上に王冠を乗せ、
賑やかしのパーティクルなんかも加えて派手にします。
素材はいらすとやから拝借。(王冠とおじいちゃん)
全体のプログラム図 ↓↓↓
Face Tracking CHOP
は、内部的にNvidia MaxineのAR SDKを利用しており、
顔のポイントや向きなどを手軽に取得することが出来るオペレータです。
ここで取得したUV
やwidth
の数値を基準に、顔の位置に合うよう調整します。
詳しくは以下チュートリアル動画を参照して下さい。
次にblenderを開き、紙吹雪風のパーティクルを作ります。
こちらも今回は以下チュートリアル動画の通りなので、詳しくは(以下略)。
ここでちょっとしたTIPSです。
Channel Mix TOP
を使うと、黒背景の画像や動画を透過背景に出来ます。
方法はパラメータをalpha1 => 1、alpha4 => 0
にするだけです。
(追記:alpha1 => 1、alpha2 => 0, alpha4 => 0
の方が良い)
この画をSpout Out TOP
でUnrealEngineに渡してテクスチャに使い、
さらに同じくSpoutでUEのカメラ画をTouchDesignerに戻します。
これで、TouchDesigner側で映像のスイッチングをすることが出来ます。
UnrealEngine側のSpoutの出力には、Live-streaming Toolkit
を利用します。
このプラグインはSpoutだけでなくNDIの入出力にも対応しており、便利です。
またTouchDesignerから飛ばすOSCをトリガーに、UEのマテリアルを操作します。
Actor BP
にOSCの受信を定義し、Event Dispatcher
でLevel BP
のイベントを発火。
最終的な画がこちら ↓↓↓
今回はMixamoのBotを置いているだけですが、グリーンバックを用意すれば
UEのバーチャル空間に現実の人を合成することができ、XR表現を強化出来ます。
8. まとめ
今回はZoom Meeting SDKとTouchDesignerを組み合わせることで、
Zoomオペレーションシステムと映像演出をプロトタイピングしました。
これで課題解決。となれば良いのですが、現実はそういきません。
1台のPCに制御を集約するということは、それだけリスクも集中します。
リスク分散の観点から言えば、複数のPCと人を用意した方が良いかもしれません。
しかしドキュメントを見ていると様々な可能性が想像出来ますし、
今後もイベント業界でのZoomの利用シチュエーションは多くあるので、
検証を進めて現場に出せるようなシステムを開発したいと思いました。