Unity
Vtuber
OVRLipsync
リップシンク

【VTuber】OVRLipsyncでUnity上のキャラをリップシンクさせる方法

Unity上のキャラをリップシンクさせるには二通りあります。
1つ目はMMD4MecanmLipSyncPlugin、2つ目がOVRLipsyncを使う方法。

しかし、Oculusのほうが精度が高いと感じたため、今回はOVRLipsyncを使ってリップシンクさせる方法をまとめてみました。

こちらの記事を参考にさせていただいております。
http://tips.hecomi.com/entry/2016/02/16/202634

完成イメージ

kizunaai_lipsync3_gif.gif

用意するもの

OVRLipsyncをダウンロードして、空オブジェクトにアタッチする

OVRLipsyncをダウンロードしてインポートします。

そしたら空オブジェクトを作成しましょう。
image.png

空のObjectにOVRLipSyncをアタッチ。
image.png

音声によって口の動きを変形させられるようにする

キズナアイ(3Dモデル)Objectに
OVRLipSyncContext ,
OVRLipSyncContextMorphTarget
をアタッチ。
image.png

OVRLipSyncMorphTarget > Skinned Mesh Rendererに、頭のパーツを当てはめましょう。キャラによって違いますが、キズナアイの場合はU_char_1になります。
image.png
これによって、キズナアイのモーフを操れるようになりました。

もし「どれを当てはめるのか分からない!」という方は頭周辺のパーツを探りBlendShapesが付いているものを当ててみるといいかも。

image.png

次にOVRLipSyncMorphTarget > Viseme To Blend を開き、
Targetの母音部分を対象のモーフのインデックス番号を指定します。
image.png

まず、Visme To Blendは15種類の口形素があります。(詳しくはこちらに載ってますが勉強する必要はありません)
0 sil(無音)
1 PP(p,m,b)
2 FF(f,v)
3 EH(@r)
4 DD(t,d)
5 kk(k,g,x)
6 CH(tS,S,Z)
7 SS(ts,s,z)
8 nn(n,l,r)
9 RR(@r)
10 aa(あ)
11 E(え)  
12 ih(い)  
13 oh(お)
14 ou(う)

例えば、「あ」と、発音したしたときに、Element10に当てはめたモーフのインデックス番号が反映される仕組みです。
モーフのインデックス番号はSkinned Mesh Renderer > BlendShapesから確認できます。
image.png
ここでは1~32がインデックス番号に当たり、その番号に対するモーフ(表情)がそれぞれ対応しています(キャラによって数が違う)
中でも、9 →「あ」、10 → 「い」 11 → 「う」12 → 「え」13 → 「お」となっていることに気づくと思います。

これらが、先程当てはめたモーフ番号になります。
つまり、現状ではこんな感じ。

発音 インデックス番号 口の形
0 sil(無音) 0
1 PP(p,m,b) 0
2 FF(f,v) 0
3 EH(@r) 0
5 kk(k,g,x) 0
6 CH(tS,S,Z) 0
7 SS(ts,s,z) 0
8 nn(n,l,r) 0
9 RR(@r) 0
10 aa(あ) 9
11 E(え) 12
12 ih(い) 10
13 oh(お) 13
14 ou(う) 11

10 aa(あ)と発音したときに、9「あ」の口の形をする
14 ou(お)と発音したときに、14「お」の口の形をする
といった感じです。

他にも、pp であれば「ポ」、FFなら「ファ」の発音になるので、それぞれの発音に対するモーフを当てはめていただけれければと。

次に、OVRLipSyncContextMorphTargetのUpdate()LateUpdate()に変更しておきます。

OVRLipSyncContextMorphTarget.sc
void LateUpdate () {

        if((lipsyncContext != null) && (skinnedMeshRenderer != null))

        {

            // trap inputs and send signals to phoneme engine for testing purposes



            // get the current viseme frame

            OVRLipSync.Frame frame = lipsyncContext.GetCurrentPhonemeFrame();

            if (frame != null)

            {

                SetVisemeToMorphTarget(frame);

            }



            // TEST visemes by capturing key inputs and sending a signal

            CheckForKeys();

        }

    }

マイクで入力させる

キズナアイ(モデル)にOVRLIpSyncMicInputをアタッチします。

そしたら常に音声を認識させられるように、Mic Controlの部分をConstantSpeadkにしておきます。
image.png

もし口の動きが小さくて分かりづらかったら、OVRLipSyncContext > Gainの値をお起きすると口が動きやすくなります。
image.png

これで完成。

まとめ

Viseme To Blend Targetsでマイクから拾ってきた音を認識し、その音声に従ってSkinned Mesh Rendererのモーフが適応されているというイメージかと思います。

もし口が動かない場合は、他のデバイスが音声を拾っていないか、Gainの値が小さすぎないかを確かめていただければと。