2.9K Views
December 28, 24
スライド概要
こちらのライブラリの解説です
https://github.com/TORISOUP/VoicevoxClientSharp
---
【年末だよ】 Unity お・と・なのLT大会 2024【ポロリもあるかもよ】
https://unity-bu.connpass.com/event/337633/
VOICEVOXでVRMを喋らせる ライブラリの紹介 2024/12/28 Unity お・と・なのLT大会 2024 torisoup
自己紹介 • とりすーぷ • 株式会社バーチャルキャスト所属 • Microsoft MVP継続受賞中 • UnityやC#の設計・テクニックなど実用的なモノを学習するのが好き • むかし、UniRxの本を出しました
今回の内容 • VoicevoxClientSharpの紹介 • 機能紹介 • 実装例 • 開発の裏話
こういうことができるライブラリです https://x.com/toRisouP/status/1872890692164546654 VOICEVOX:玄野武宏
VOICEVOXとは 音声合成ソフトウェア
VOICEVOXとは • 無償利用が可能な音声合成ソフトウェア • https://voicevox.hiroshiba.jp/ • テキストから音声合成を行いwavを生成できる • ずんだもん解説動画の音声素材はVOICEVOX製が多い印象
VOICEVOX.exe
VOICEVOXとは • 本体はOSSとして開発されている • https://github.com/VOICEVOX • 言語はPytonで、Docker上で動作させることも可能 • Windows向けのPCソフトが「VOICEVOX.exe」 • WebAPIサーバー機能あり
VOICEVOX API • VOICEVOXはHTTP経由のAPIを提供している • https://voicevox.github.io/voicevox_engine/api/
OpenAPI Spec • OpenAPI Specも用意されている • VOICEVOX.exeを起動中に下記URLにアクセス • http://localhost:50021/openapi.json • OpenAPIが何か忘れた人は去年の自分のスライドを見て • 『UnityでOpenAPI Generatorを使う』 https://www.docswell.com/s/torisoup/ZRX7ER-2023-12-10-160647
VoicevoxClientSharp VOICEVOXをC#からコントロールするライブラリ
VoicevoxClientSharp • VOICEVOXをC#から制御するライブラリ • https://github.com/TORISOUP/VoicevoxClientSharp • VOICEVOXが提供するAPIをC#から実行するクライアントライブラリ • 実行中のVOICEVOXと通信を行い音声合成などを実行できる • .NET Standard 2.0向け • Unityの場合は 2018.4~
できること • VOICEVOXが提供するAPIの呼び出し • HTTPのAPIと1:1で対応したメソッドの提供 • 処理をラップして簡便に使えるようにした補助クラスの提供 • Unity上での使用の補助 • 別途「VoicevoxClientSharp.Unity」を導入する必要あり • 生成したwavをAudioSource上で再生する • VRMアバターのリップシンクを行う
注意点 • 起動中のVOICEVOXと通信して動作します • VOICEVOXを先に起動しネットワーク的に疎通する状態にしてください • VOICEVOX.exeを起動しても、 docker上で実行しても、 voicevox_engineを直接実行してもなんでもOK • WindowsならローカルでVOICEVOX.exeを起動しておくのが一番楽
使い方(C#) C#プロジェクト全体での共通した使い方
C#プロジェクトへの導入方法 • NuGetからパッケージを導入 • https://www.nuget.org/packages/VoicevoxClientSharp • NuGetコマンド経由でインストールしてください • Unityの場合はNuGetForUnityを使うことを推奨 • https://github.com/GlitchEnzo/NuGetForUnity
2つのクライアントクラス • VoicevoxSynthesizer • とにかく簡単に音声合成したいならこっちを使えばOK • 音声合成回りのAPI呼び出しをラップしたクライアント • VoicevoxApiClient • 上級者向け • HTTP APIと1:1で対応したシンプルなクライアント • VoicevoxSynthesizerで機能が足りないときはこっちを使ってください
VoicevoxSynthesizerを使った 音声合成の実装例
とりあえずこのメソッドを 呼べば音声合成される
結果はこの3つが同梱 • 合成結果のwav • 読み上げのクエリ情報 • 読み上げたテキスト
同じ処理を上級者向けの VoicevoxApiClientで 実装するとこう VOICEVOXのAPIに対する知識が 必要でちょっと難しい
使い方(Unity) VoicevoxClientSharp.Unityを導入した場合の話
Unityプラグインの導入 • VoicevoxClientSharp.Unity • UPMから次のURLを指定 https://github.com/TORISOUP/VoicevoxClientSharp.git? path=VoicevoxClientSharp.Unity/Assets/VoicevoxClientSharp.Unity
VRMを使う場合 • UniVRMも導入してください • https://github.com/vrm-c/UniVRM/releases
(補足)VRMとは • 人型アバターを扱うための規格 • https://vrm.dev/ • UniVRMを使えば人型アバターモデル(.vrm)を動的に読み込んでUnityで 扱えるようになる
VoicevoxClientSharp.Unityの準備 • asmdefの参照設定をする 必須要素 (UniTaskも使います) VRM連携する場合は これらも必要
VoicevoxSpeakPlayerコンポーネント • AudioSourceで合成したwavを再生するコンポーネント
使い方
使い方 VoicevoxSynthesizerの結果を そのままコンポーネントに渡せばOK
VoicevoxSpeakPlayerコンポーネント • AudioSourceを紐づけるだけ! • あとはPlayAsync()を呼べば再生される
VoicevoxVrmLipSyncPlayerコンポーネント • VRMを音声と同期して口パクさせるコンポーネント https://x.com/toRisouP/status/1872890794933404027 VOICEVOX:中国うさぎ
セットアップ • VRMInstance と VoicevoxSpeakPlayer がセットで 必要になります 最終的に VoicevoxSpeakPlayerに 紐づけて使う
使い方 • VoicevoxSpeakPlayer.PlayAsyncを呼び出すだけ • VoicevoxVrmLipSyncPlayerが設定済みの場合はこれだけで 音声再生と同期してVRMがリップシンクする
(補足:動的構築) VRMを動的に読み込んだ時は あとからAddComponentしても OK
実装例 サンプル紹介
AvatarSpeaker • HTTP経由でVRMを発話させるサンプルプロジェクト • https://github.com/TORISOUP/AvatarSpeaker
できること • ローカルからVRMアバターの読み込み • 背景色変更 • HTTP経由での発話
実装解説 • 「Unityで非ゲームアプリをクリーンアーキテクチャを 意識して作ってみた話」 • https://qiita.com/toRisouP/items/e5b312af53c40e1f4a80 • クリーンアーキテクチャを意識してガッツリ設計して作ってあります • 良かったらソースコードを読んでみて
裏話 VoicevoxClientSharp実装にあたっての話
OpenAPI 相変わらずしんどい 去年のLTでのスライドの 結論部分
今回はどうだったか? • 失敗! • .NET Standard 2.0指定で上手く生成できず • Nullable回りのコード生成がうまくできず
今回はどうだったか? • 失敗! • .NET Standard 2.0指定で上手く生成できず • Nullable回りのコード生成がうまくできず C#的にキレイなコードを出力したかったら OpenAPI Spec側に手を入れないと厳しそうな結果に
今回はどうだったか? • 失敗! • .NET Standard 2.0指定で上手く生成できず • Nullable回りのコード生成がうまくできず C#的にキレイなコードを出力したかったら OpenAPI Spec側に手を入れないと厳しそうな結果に OpenAPI Specを手動で書き換えてメンテするくらいなら 手で全部実装した方がトータルでコスパが良さそう
というわけで • APIクライアントを全部手動で実装しました
実装全容
実装全容 使い勝手を考えて抽象化や APIの粒度を分割できたので 手動で実装したメリットはあった
テスト 手動実装するついでに、 VOICEVOXのAPIを実行して 動作確認するテストも用意した 一部VOICEVOX側の都合で 動かないAPI以外は全網羅してるはず
(クッションページ) (話題を変えます)
VRMのリップシンク実装について • どうやってるのか?
VOICEVOXの音声合成のフロー
VOICEVOXの音声合成のフロー ① テキストから「クエリ」を作成する
VOICEVOXの音声合成のフロー ② できたクエリを使って 音声合成を実行する
音声合成のフロー
AudioQuery • 発話に必要な音素データの集合 子音、子音部分の発音の長さ(秒)、 母音、母音部分の発音の長さ(秒) が含まれている
AudioQueryの解析 • AudioQueryからリップシンクに必要な情報は得られる • 「どのタイミングにおいて口がどの形なのか」が知りたい • 子音、母音、それぞれの発音の長さがAudioQueryからわかる 指定時刻においてどの音素を再生中か?を 算出することができる
AudioQueryでリップシンク • 音声の再生時間に合わせてリップシンクの計算を行う • ただし時間の分解能に注意 • 現時刻の音素に合わせてVRMのExpressionを設定する • 母音に合わせてExpressionのAa/Ih/Ou/Ee/Ohに反映する • 子音の影響も考慮する(m/b/p/f/v/wは口を一瞬閉じる動作を入れる) • 直前のExpressionの要素を残して滑らかに遷移させる
時間分解能 • UnityではTime.deltaTime以上の分解能が出せない • フレームで処理を行う都合上、0.01666...[s]単位 (60fps時) でしか 時間の計算ができない • 雑に時間の計算をすると誤差が蓄積する可能性がある
誤差
誤差 実際の音素の長さは 整数フレーム倍ではない
誤差 Unityはフレーム単位でしか 時間の計測ができない
誤差 ってした時、本当は約4.57フレーム分awaitしてほしい。 けど実際は5フレーム分待機するしかない。 そのときの差分が誤差になる。
誤差 読み上げテキストが長いほど 誤差は蓄積し最終的に 数フレームずれることになる
誤差が溜まらない待ち方 待ち時間 = 計算上の読み上げ終了予定時刻 - Unity上で実際にかかった現在の時刻 誤差が溜まると次の待ち時間が短くなって帳尻が合う
長文を読ませてもズレなくなった • 例文 「高校ミュージカル最高峰の球技がここに 全国高校jaiball選手権公 演がお盆の時期から始まります。舞台はここjaiballの聖地大阪のバ トル公民館。ハードスタイルを武器に勝ち上がって参りましたのは赤 コーナー西松屋山東高校南高北校、全国公演初参加。対する青コー ナーは大分及熊本九州国際経済産業工業学院高校学園、去年の準優勝 チームです。さぁまもなく戦いのまぶたが切って落とされました。」 元ネタ: ジャイボール https://www.youtube.com/watch?v=m8ErgDgVpZw
https://x.com/toRisouP/status/1872890868761567380 VOICEVOX:春日部つむぎ
よくできた • それっぽくリップシンクしてくれるようになった • 読み上げの終わり際がまだちょっと違和感が残るので調整したいかも • 長文を読ませてもズレなくできた • 30秒程度の文章を読ませてもズレは体感できない
まとめ
まとめ • 「VoicevoxClientSharp」を作った • VOICEVOXをC#から実行できるクライアントライブラリ • .NET Standard 2.0向け • VRMと連携する仕組みも用意したのでぜひ使ってみてね
スライド中で使用したもの • VOICEVOX • https://voicevox.hiroshiba.jp/ • シードさん • https://wiki.virtualcast.jp/wiki/vrm/seedsanvrm • https://github.com/vrm-c/vrm-specification/tree/master/samples • オリジナル3Dモデル『マロン』 • https://booth.pm/ja/items/1105063 • オリジナル3Dモデル『あのん』 • https://booth.pm/ja/items/3564947 • 【43アバター対応】りあちゃん制服【PB対応】 • https://booth.pm/ja/items/3687426 • シンプルベレー • https://booth.pm/ja/items/2394682