DMMグループの一番深くておもしろいトコロ。
テクノロジー

フロントエンドで制御するLive2Dキャラクター~個性的にキャラクターを動かす工夫~

DMMグループの一番深くておもしろいトコロ。

  • 井内将俊フロントエンドエンジニア

    23新卒、LC開発部 VCグロースグループ所属、趣味:絵を描くこと

はじめに

DMMグループAdvent Calendar 2023 の12日目を担当する井内 (@pengin_engineer) です。
私は今年の4月に23新卒としてDMMグループへ入社し、現在はライブコミュニケーション開発部で Webフロントエンド開発をしています。
本記事では業務で携わっているライブコミュニケーションサービスの、Live2D制御にまつわる話をしようと思います。

Live2D制御とフロントエンド

多くの人が「Live2Dの制御」と聞くと、Unityを思い浮かべるかもしれません。しかし、「Live2D®」ではWebGLを用いた「Live2D Cubism SDK for Web」も提供しています。このSDKはTypeScriptで書かれており、フロントエンドエンジニアにとって学習しやすく、制御も効率的です。開発中のバーチャル配信サービスはブラウザベースで動作することを想定しており、Web環境に特化したこのSDKを使用することで、開発が効率的に進められます。
Live2Dの公式YouTubeチャンネルでは、Web SDKの導入方法を解説したワークショップ動画が公開されており、簡単にWeb上でLive2Dを操作ができるようになります。

キャラクターを制御する3つの概念

我々が開発するライブコミュニケーションサービスでは、以下の画像のようなキャラクターをLive2D技術を用いて配信者がコントロールし、視聴者に映像を届けます。

Live2Dキャラクターの全身イラスト

その際、Live2Dキャラクターは

  • FaceTracking
  • Expression制御
  • Motion制御

の3つの手法を用いて制御され、これらを組み合わせて使うことによって豊かな表現を実現しています。

FaceTracking

FaceTrackingでは、トラッキングシステムにより取得した配信者の顔パーツの座標を元に、Live2Dを制御するパラメータ値を計算します。
例えば、顔の角度を制御する場合、

  • ロール(Roll)
  • ピッチ(Pitch)
  • ヨー(Yaw)

という3つの回転軸の角度をそれぞれ計算し、Live2Dパラメータ値とします。

ロール制御

ロール制御を行う際には、頭の頂点と顎の点を結ぶベクトルを作成します。このベクトルと垂直方向のベクトルとの間で形成される角度を計測し、キャラクターの頭部の左右の傾き、すなわちロール角を推定します。

ロール制御の概要図

ピッチ制御

ピッチ制御を行うには、まず頭の頂点から鼻の先端、そして鼻の先端から顎までの2点間の距離を測定します。これらの2つの距離の比から、キャラクターの頭部の前後の傾き、つまりピッチ角を推定します。

ピッチ制御の概要図

ヨー制御

最後にヨー制御を行う際には、まず顔の左端から顔の中心、そして顔の中心から右端までの距離を計測します。これら2つの距離の比率から、キャラクターの顔の左右への回転、すなわちヨー角を推定します。

ヨー制御の概要図

このように、FaceTrackingよって取得した顔パーツの座標を用いてLive2Dパラメータを計算し、リアルタイムにLive2Dキャラクターを動かすことがきます。

Expression制御

Expressionとは、現在のLive2Dパラメータ値に対して表情用のパラメータ値を設定する制御です。Expressionを用いることで、以下のようにキャラクターの表情を簡単に変更できます。

笑顔の表情・困った表情

このExpressionは.exp3.jsonというファイルによって定義されます。.exp3.jsonファイルは、Live2Dモデルの表情(エクスプレッション)を制御するための設定ファイルであり、どのパラメーターへ、どんな値を、どのように設定するのかを定義します。
以下は.exp3.jsonのサンプルデータです。このサンプルでは、EyeROpen、EyeLOpen、MouthOpenという3つのパラメーターに対し、0という値を、Overwrite(上書き)しています。

{
    "Type": "Live2D Expression",
    "Parameters": [
        {
            "Id": "EyeROpen",
            "Value": 0,
            "Blend": "Overwrite"
        },
        {
            "Id": "EyeLOpen",
            "Value": 0,
            "Blend": "Overwrite"
        },
        {
            "Id": "MouthOpen",
            "Value": 0,
            "Blend": "Overwrite"
        }
    ]
}

このサンプルファイルをLive2Dモデルへ適応した場合、左右の目と口の値が0になる、つまり閉じるように上書きされることが予想されます。BlendにはOverwriteの他にも

  • Add(現在のパラメータ値へ値を加算する)
  • Multiply(現在のパラメータ値へ値を乗算する)

という設定があります。詳しくはLive2D SDK マニュアル 表情モーションについてを読んでみてください。
このように.exp3.jsonファイルはとてもシンプルな構成となっており、Live2Dに明るくないエンジニアでも、簡単に編集・修正することが可能となっています。

Motion制御

Motionは言葉の通りキャラクターの動き(モーション)を制御します。以下の画像のように、キャラクターが手を振ったり、手を叩いたりするモーションを、.motion3.jsonというファイルで設定します。

MotionによるLive2Dの動き

MotionはExpressionの親のような概念であり、.motion3.jsonファイルを元に.exp3.jsonが作成されます。つまり、.exp3.jsonを利用せず、表情も.motion3.jsonによって動かすことが可能です。motion3.jsonは以下のような形式で書かれています(いくつかの要素は省略しています)。

{
    "Version": 3,
    "Meta": {
        "Duration": 3.5,
        "Fps": 30.0,
        "Loop": true,
        "CurveCount": 2,
        "etc.":
    },
    "Curves": [
        {
            "Target": "Parameter",
            "Id": "HandType",
            "Segments": [0, 0, 0, 5, 1]
        },
        {
            "Target": "Parameter",
            "Id": "ArmType",
            "Segments": [
                0,
                0,
                1,
                0.166,
                0,
                0.333,
                1,
                0.5,
                1,
                1,
                0.833,
                1,
                1.166,
                1,
                1.5,
                1,
                1,
                1.756,
                1,
                2.000,
                0,
                2.266,
                0,
            ]
        }
    ]
}

.exp3.jsonよりも複雑な構成となっており、パッと見ただけでは以下の3点ほどしか分かりません。

  • Metaで初期設定をしている
  • idによってパーツ指定をしてる(サンプルの場合HandType、ArmType)
  • Segmentsで値を更新をしている

ただ、肝心のSegmentsの中身も、どれが時間でどれが値なのかを読み取ることができず、このJSONファイルを見ただけでは意図した通りにモーションを修正することは困難です。何故ここまで読み取りづらいかというと、MotionはExpressionに無い「時間」「モーション方法」という概念がある為です。

Expressionは単に現在の値を別の値に変える機能です。一方で、Motionは現在の値を特定の時間方法で変更し、このプロセスを繰り返します。「モーション方法」には、直線的な遷移をする「リニア」や滑らかな曲線的な遷移をする「ベジェ曲線」が含まれます。リニアでは次の値を1つ設定するだけですが、ベジェ曲線では、その性質上、右ハンドルや左ハンドルのような追加の値が必要です。そのため.motion3.jsonのSegmentsでは、モーションの種類によって必要なパラメータの数が異なります。このように.motion3.jsonは値の意味が分かりにくく複雑であるため、直接編集するのでは無く、Live2D Cubism EditorというLive2Dの専用ソフトを使用することが一般的です。
先ほど「.exp3.jsonを利用せず、表情も.motion3.jsonによって動かすことが可能」と書きましたが、.motion3.jsonの修正はこのように手間がかかります。簡単な表情の変更であれば、シンプルな構成である.exp3.jsonを用いることで、エンジニアでも簡単に編集でき、効率よく開発できます。

3種の制御の組み合わせ・優先順位

このように、Live2Dキャラクターの操作にはFaceTracking、Expression制御、Motion制御の3つの手法が用いられます。これらは同時に実行され得るため、優先順位の設定が重要です。私たちのサービスでは、優先順位をFaceTracking < Expression < Motionの順に設定しています。これは、ExpressionやMotionによる設定がFaceTrackingの設定を上書きすることを意味します。

私たちのサービスでは、個性豊かな複数のLive2Dキャラクターを提供しており、全キャラクターでFaceTracking、Expression、Motionといった制御の仕組みを共通化しています。

個性のある複数のキャラクター

ただし、Motionを個性的にすると、特定のキャラクターには合っても他のキャラクターのイメージにそぐわないことがあります。そのため、笑いながら手を振る、怒りながら手を振る、FaceTrackingをしながら手を振るといった表現が可能になるよう、Expression、Motionによって上書きするパラメータは最小限に留めています。

3種の制御を組み合わせた動き

終わりに

本記事ではリアルタイム配信を想定したLive2D制御の手法を紹介しました。Live2Dの公式マニュアルにも多くの情報が記載されていますが、.exp3.jsonや.motion3.jsonの構成等は載っていない為、実際にSDKのコードを読み解き理解する必要があります。

実装の理解やパフォーマンス改善の為にも、SDKの理解をより深め、ユーザーへ快適なサービスを提供できるよう努めたいと思います。本記事で紹介したExpression制御、Motion制御は、Live2D Cubism SDK for Web を用いれば比較的簡単にWeb上で再現できるので、興味を持たれた方はぜひ触ってみて下さい。

またね!

 

一緒に働く仲間を募集しています!