デジタルな日々

ユニティちゃんをしゃべらせるその仕組み(音声合成まで)


 

今回はユニティちゃんを口をパクパクさせてしゃべらせてみたいと思います。

 

ユニティちゃんをしゃべらせる方法はいくつかありますが…

 

簡単に行うには

  • ユニティちゃんのブレンドシェイプアニメーションで口パク
  • (Macの場合)内臓の合成音声を使う

ですることができます。

 

 

これらについてはまたあとでまとめますが、今回は別の方法を使います。

 

色々調べてみたらこんなアセットを作っている方がいらっしゃいました。

ユニティちゃんが声に合わせて口パクしてくれるリップシンクアセットを作ってみた – 凹みTips

メモ:Unity5.0にて自動のAPI変更部分のアップデートをさせたら動いた

メモ:「StreamingAssets」フォルダはAssets直下に、ほかは移動させても大丈夫

 

しゃべるユニティちゃん

 

す、すごい…!

生成した合成音声にリップシンクするだけでなく、音声データやリアルタイムでマイクからリップシンクできるようです。

 

一体このリップシンクがどのように動いているのか、

スクリプトを少し読みといてみよう

 

 

今後音声合成をメインで使いたいので、音声合成からリップシンクまでの流れを追ってみる。

 

・利用方法

ユニティちゃんリップシンク(MMD)使い方

 

Unity Chan Lip Sync(Script)」のインスペクターの「Play Voice Sound > Word」に、好きな言葉を入れて「Talk」ボタンを押すことで自動で音声合成が行われリップシンクされる。

 

 

・スクリプトの動き

インスペクター(エディタ拡張)は「MMD4Mecanim-LipSync-Plugin > Editor > LipSyncCoreEditor」とに書かれている。

ちなみに「Editor」フォルダ内の他のエディターもこの「LipSyncCoreEditor」を継承している。

 

※ エディターとは…インスペクター上の設定欄などを自由に拡張することができる機能、詳しくはこちら → その1 Isnpectorが変わる!

※ エディタでは「target」変数があらかじめ用意されており、これにクラスを入れることでそのクラスがあるスクリプトに関連付けることができる。(Unity – マニュアル: カスタムエディタ > カスタムエディタの作成)

 

 

ここでは「target」変数に「LipSyncCore」クラスを指定している

 

 

ので、

 

「LipSyncCore」クラスを継承している「UnityChanLipSync」にもこのようなインスペクタが表示される。

 

 

(なるほどね、

どこから関連付けてるのか全然わからなかったわ、

使う側のスクリプトから指定してるのかと思ったら、逆にエディタースクリプトから指定してるのね)

 

 

さてこの「LipSyncCoreEditor.cs」をもっと見てみると、

音声合成の部分(この部分)

音声合成の部分

は次のように書かれている。

 

 

 

 

GUIボタンなどはonGUIなどの描画する関数内で「if ( GUI.Button )」とすることで、

ボタンが押された時にする処理を設定できる。

 

ここでは

 

の部分がそこに当たるので、

「ボタンが押され」て、

「アプリケーション実行中」ならば

lipSync.Talk( word )」が実行される。

 

lipSync」は「LipSyncCore」なので、この中の「Talk」が実行される

 

じゃあ「LipSyncCore」を見てみよう

 

大事そうなのは明らかに「OpenJTalk.CreateWavFromWord(word, (err, wavPath) => { …} 」ですね

第二引数メソッド(無名関数)が渡されてるのを覚えておこう!!

 

OpenJTalk」はスクリプトの上の方を読むと「OpenJTalkHandler」であることがわかる

 

 

ここでようやくOpenJTalkを起動してアクセスしているのがわかる。

(C#の「process」で外部アプリケーションにアクセスできる Process クラス (System.Diagnostics)

これにより、処理が終わると「OnWavCreated」が呼び出されるようになる

 

 

ここでついにコールバック、つまり先ほどの第二引数のメソッド(無名関数)が使われる。

ちなみに第一引数はエラーメッセージで、第二引数は音声ファイルのパスになっている。

というわけで再び「LipSyncCore」に戻ってこのメソッドを見る

 

 

エラーコードがあれば表示し、

音声ファイルのパスを取得して「isNewWavCreated」をtrureにする。

 

それによって「LypSyncCore」のUpdateが動き出しす!

(このなんか推理小説でどんどん推理が進んでる感いいですね)

 

コルーチンで「LoasAudioClipFromPath」が実行されている

コルーチンとは一旦処理を止めて、次のフレームで処理を再開できるもの。好きな時間処理を止めておくとかもできる。

Unity – マニュアル: コルーチン

 

というわけで「LoadAudioClipFromPath」に飛ぶ

 

 

引数のパスを使って、オーディオクリップを取得できれば再生する

終わったら、Disposeでメモリ解放(?)する

 

 

 

 

 

これで文字列を再生することができました。

 

あれ?じゃあリップシンクはどこでやってるの??

 

その辺はまた次回調べてみたいと思います

 

 

 

Play()を「audio source.Play()」と勘違いしてた…

これは独自に作った「Play」メソッドですね

 

Playメソッドはいくつかあるのだけれど、

オーバーロードでAnimationClipを引数に持つこれが呼び出される。

 

 

 

 

最後のaudio_.Play()で音声が再生されていますね

ここでリップシンクのために音声の分析などを行っているようなのですが…

そこはまた次回(ユニティちゃんをリップシンクさせるその仕組み

 

 

コメントを残す