UnityからKoeiromapAPI経由で音声を取得して声を再生する【Unity】【Koeiromap】

概要

昨日アーリーテストとして公開された KoeiromapをUnityから指定した文字列のデータをAPI経由で取得して、音声として再生させる実装を簡単に行いました。

-------- 追記 --------------------------------------------

KoeiromapをUnityで使うためのライブラリを公開

ライブラリ公開・更新に伴い記事の内容を更新しました

KoeiromapをUnityから使うためのLibrary 「KoeiromapUnity」を公開しました!

github.com

NAudioを使ってStreamでの変換処理については以下


環境

Demo

Repositoryは以下で公開しています。

github.com

実装方法

指定したテキストからボイスを生成

公式の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が生成されたので、あとは任意のタイミングで鳴らすと指定した音声が再生されます