人間のあるべき姿の探索

思索・人形・エンジニアリング

人形の視界の為の映像リアルタイム転送

人形になるぞ!

godiva-frappuccino.hatenablog.com

 ということで、人形の視界となる映像をWebカメラで取得し、HMDに視界を流し込む仕組みを開発中です。人形の作業の中で、実現可能性の観点で一番苦労しているのが、実はここになります。個人的に電装周りの知識や機構学の知識が足りないので苦労している点はあるのですが、映像の転送については技術的に限界があります。

 まず、データの通信は基本的に少量を高速に送るか、大容量でも低速にもしくは遅延を許可して送ることが多いです。例えば、極端な例ですが格闘ゲームは極限まで遅延を減らしたいところで、わざわざ映像を同期するようなことはせず、お互いのコマンドを送って相手の画面でその描画をします。描画や計算よりも通信の方がボトルネックになるわけですね。ちなみに格闘ゲームなどは投機的実行として先にこう動くと仮定して動かしておいて、後から命令が異なる場合に補正するような仕組みを導入するゲームもあるようです。高速でも一秒で地球を7周半程度なので、ブラジルと日本で遅延10msなどは現実的ではないんですよね。そして、映像を送るYouTubeの場合は1秒とかラグを許容する場合が多いです。リアルタイム通信のZoomなどのWeb会議システムはUDPベースの制御が軽い通信方法をしていますが、それでもローカルネットワークを超える場合は400ms程度の遅延が入ります。これだけずれると会話がしづらいのですね。

 ということで、今回やろうとしているのは低遅延で映像を送ることになります。できることと言えば、ローカルネットワークで可能な限り有線接続をする、そしてUDPベースで信頼性を犠牲にしてとにかく高速に映像を送るというのが解決法です。しかし、有線接続についてもVRChatのようなツールでは専用ケーブルを刺すとその線で通信してくれるのですが、自前のアプリケーションでTCP/UDP通信をする際にその線を使用する方法がわからず…といった感じで情報がつかめず苦戦しているのが現状です。後で遠隔操作を見越してWebRTCに手を出そうとしたのですが、一番使い慣れているクラウドサービスのAzureで使用できるAzure Communication Servicesでは長らくHMDの開発言語であるUnityサポートがなく、無理やり使用する場合もHoloRensでWPFとマルチプロセス実行が必要だったり、とにかくHMDでは難しいというのが現状です。

 今回はシンプルにUDPで小さめの映像を転送するようにしました。送り側はPythonで書いていて、JPG圧縮した後にUDPHMDに映像を投げています。UDPだと映像のサイズに制限がかかるのですが、JPG圧縮すると映像の内容によってバイト数がかなり変わるので、一番サイズが大きい状態で超えないような画面サイズにする必要がありました。JPGの圧縮アルゴリズムを忘れちゃいました。RGB-YCbCr変換をして情報を少し減らしたのちに離散コサイン変換をして量子化、最後にランレングス・ハフマン圧縮をするらしいです。情報をへらすうえでは最初のRGB-CbCr変換でちょっと情報を落とすのとランレングス・ハフマン圧縮で大きく落とすのがコアになっていそうですが、確かにカメラをふさいで画面を真っ暗にするとランレングス・ハフマン圧縮でめちゃくちゃ圧縮されるのか本棚を映している時と比べて半分くらいのバイト数になります。

kuriken12.hatenadiary.org

受け取り側はUnityなので、Update関数が回っている状態で映像が入ってきたらreceiveBytes変数に入った映像をテクスチャに貼り付けていきます。