blog.mahoroi.com

webカメラとブラウザでバーチャルモデルになれる「ModelV.」

-

web カメラとブラウザでバーチャルモデルになれる web サイト「ModelV.」を公開したので、ここで宣伝します。

ModelV.

ModelV. | webカメラとブラウザでバーチャルモデルになれるwebアプリ

動作サンプル

特徴

ModelV. では 2 つのタブを使って MMD (pmx) モデルをブラウザ上で動作させることができます。

1 つ目のタブは、web カメラで撮影した映像からフェイストラッキングを行うために使われます。サイト公開時点では、顔の向きと口の開閉動作に対応しています。ここで取得・処理されたデータは 2 つ目のタブに送信されます。

2 つ目のタブでは、1 つ目のタブから送信されたトラッキングデータをもとにバーチャルモデルを描画するために使われます。

使用するブラウザは同じものである必要はありません。たとえばトラッキングは「Chrome」で行い、モデルの描画は「Firefox」で行う、というように別ブラウザであっても動作可能です。

動作端末も PC に限定されるわけではなく、トラッキングはスマホで行って描画は PC で行うということも可能です。異なる端末で動作させることで処理を分散できるのも ModelV. の特徴です。

使用技術

フェイストラッキング

目や鼻の位置を取得するために face-api.js を使いました。同様の機能をもつ他のライブラリに比べて、横を向いた顔の認識精度がいい気がしています。

顔向き推定

顔の向きを取得するために OpenCV.js を使いました。開発当初は自前の顔向き推定コードを書いていたのですが、固有ベクトルを求めるときに動作しない場合が多々あるダメダメコードができあがってしまいました。そのため、自前実装は諦めて素直に OpenCV.js を使うことにしました。おかげで圧倒的な精度の向き推定が可能になりました。

OpenCV.js を使うデメリットとしてはファイル容量が非常に大きいことがあげられます。対応策として、OpenCV の必要な関数だけを抽出し、Brotli 圧縮配信することでファイルサイズを約 680kb に抑えています。これでもまだまだ大きいですが。

モデル描画

モデルの表示には three.js を使っています。公式から MMDLoader が提供されているので、非常に簡単に描画・動作の実現が可能でした。

タブ・ブラウザ間の通信

ModelV. では 2 つのタブ間の通信に WebRTC を使っています。

顔の向き情報や口の開閉情報などを 1 つ目のタブから 2 つ目のタブに送信するときに Data Channel 経由で送信しています。

接続にはシグナリングサーバーは用いず、手動シグナリングによる接続を行っています。SkyWay などを使えばサーバー管理の手間もなく楽に運用できるとは思うのですが、外部依存をなくしたかったので今回は手動シグナリングを採用しました。デメリットとして WebRTC の接続まで到達できない環境がでてきます。そのため WebRTC が繋げられない環境は非対応としています。

Next.js × TypeScript × Vercel

フロント開発フレームワークとして Next.js × TypeScript を使っています。2020 年のデファクトスタンダード環境だからでもあるのですが、今回はやることが多いため、環境周りの整備を Next.js に丸投げできることが採用理由です。

また React のおかげで通信時のデータ処理は送信先の state 更新にのみ集中すればよいため、比較的に簡潔な通信処理実装におさまりました。

デプロイ先には Vercel を使っています。ありがたいことに、個人の GitHub リポジトリであれば転送量が無制限(Fair Use Policy のため実質 100 GB / month)なので、OpenCV.js や face-api.js のモデルデータも転送量を気にすることなく配信できます。

開発モチベーション

最近は、例のあの影響でビデオミーティングをする機会が多くなりました。その過程でバーチャルモデルでミーティングに参加したいと思ったのが制作のはじまりでした。

すでに類似サービスはあるのですが、自分の使い方には合わなかったため ModelV. の制作までに至りました。

今回は顔向き推定や three.js など初めて触れるものが多かったのです。とくに WebRTC は知れば知るほどわからなくなりました。最終的には公開することができてよかったと思っています。

今後の予定

実装できていない機能の導入であったり、動作の安定化やパフォーマンスの向上であったりと、やりたいことはまだまだあります。

コードは GitHub で公開しています。