概要
昨日アーリーテストとして公開された KoeiromapをUnityから指定した文字列のデータをAPI経由で取得して、音声として再生させる実装を簡単に行いました。
-------- 追記 --------------------------------------------
KoeiromapをUnityで使うためのライブラリを公開
ライブラリ公開・更新に伴い記事の内容を更新しました
KoeiromapをUnityから使うためのLibrary 「KoeiromapUnity」を公開しました!
KoeiromapをUnityで使えるライブラリ「KoeiromapUnity」をアップデートしました!
— ようさん (@ayousanz) 2023年3月23日
【Repository】https://t.co/xoGuio4baP
【Demo Page】https://t.co/ygsMIzAiEP
【変更点】
* Stream再生の対応(WebGLでも動くようになりました)
* サンプルシーン及びデモページの追加#Koeiromap #unity3d pic.twitter.com/vc7qrCfpDj
NAudioを使ってStreamでの変換処理については以下
環境
- Unity 2021.3.16f1
- Koeiromap api(2023/3/4時点の仕様)
Demo
音が割れていたので、変換処理を修正してきれいに聞こえるようにした!
— ようさん (@ayousanz) 2023年3月4日
AIVtuberも Koeiromapを使って実現できそう#Koeiromap https://t.co/jH9kVKeBxU pic.twitter.com/MwKNmRp8Aw
Repositoryは以下で公開しています。
実装方法
指定したテキストからボイスを生成
公式のAPIドキュメントに従って指定したテキストの音声データ (base64エンコードされた文字列)をAPI経由で取得します
public static async UniTask<VoiceResponse> Voice(string text) { var voiceParam = new VoiceParam() { text = text, speaker_x = 2.44f, speaker_y = 2.88f, style = "talk" }; var json = JsonUtility.ToJson(voiceParam); var bodyRaw = Encoding.UTF8.GetBytes(json); var request = new UnityWebRequest(URL, "POST"); request.uploadHandler = new UploadHandlerRaw(bodyRaw); request.downloadHandler = new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); await request.SendWebRequest(); return JsonUtility.FromJson<VoiceResponse>(request.downloadHandler.text); } public class VoiceParam { public string text; public float speaker_x; public float speaker_y; public string style; } public class VoiceResponse { public string audio; public string phonemes; public int seed; }
不要な文字列の削除
APIレスポンスは以下のようになっています
data:audio/wav;base64,UklGRjIsBgBXQVZFZm1...
そのため、音声データに変換する際に不要な先頭部分を取り除く処理を以下で行っています。
public static string VoiceBase64Data(VoiceResponse voiceResponse) { var audio = voiceResponse.audio; return audio[(audio.IndexOf(",", StringComparison.Ordinal) + 1)..]; }
base64からAudioClipを生成
取得して整理したbase64になっている音声データをUnityで再生するために、AudioClip型に変換します
private static async UniTask<AudioClip> ConvertBase64ToAudioClip(string base64EncodedMp3String) { var audioBytes = Convert.FromBase64String(base64EncodedMp3String); var tempPath = Application.persistentDataPath + "tmpMP3Base64.wav"; await File.WriteAllBytesAsync(tempPath, audioBytes); var request = UnityWebRequestMultimedia.GetAudioClip(tempPath, AudioType.WAV); var asyncOperation = request.SendWebRequest(); await asyncOperation; if (request.result.Equals(UnityWebRequest.Result.ConnectionError)) { Debug.LogError(request.error); return null; } var content = DownloadHandlerAudioClip.GetContent(request); request.Dispose(); return content; }
こちらでAudioClipが生成されたので、あとは任意のタイミングで鳴らすと指定した音声が再生されます