Edited at

【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の値が小さすぎないかを確かめていただければと。