27
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

UnityでVOICEVOXをREST-API経由で利用する方法

Last updated at Posted at 2023-02-21

概要

  • UnityでREST-API経由でVOICEVOXを使用する方法の紹介

  • VOICEVOXのREST-APIクライアントクラスの作成

  • 実際にUnityで喋らせるためのテストスクリプトの作成

手順

【1】VOICEVOXの起動

まだ、VOICEVOXをインストールしていない場合、
以下のサイトよりVOICEVOXをインストールしましょう!

VOICEVOXは、無料で利用できる高品質な音声合成ソフトです!

VOICEVOXを起動すると、ローカルにHTTPサーバが立ち上がります。

Docker使える方は、DockerイメージからHTTPサーバーを起動するのでもOK!
https://github.com/VOICEVOX/voicevox_engine#docker-%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8

VOICEVOX起動後に以下のURLにブラウザからアクセスするとAPI仕様書が表示されます。
http://localhost:50021/docs

VOICEVOX_docs.png

Docsがブラウザで表示できていれば、サーバーの立ち上げは成功しているため、REST-APIが利用できます。

【2】VoiceVoxのREST-APIクライアント作成

以下のクラスを「VoiceVoxApiClient.cs」という名称でUnityに追加します。
VOICEVOXとの通信回りの処理はここに記載します。

VoiceVoxApiClient.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

/// <summary>
/// VOICEVOXのREST-APIクライアント
/// </summary>
public class VoiceVoxApiClient
{
    /// <summary> 基本 URL </summary>
    private const string BASE = "localhost:50021";
    /// <summary> 音声クエリ取得 URL </summary>
    private const string AUDIO_QUERY_URL = BASE + "/audio_query";
    /// <summary> 音声合成 URL </summary>
    private const string SYNTHESIS_URL = BASE + "/synthesis";

    /// <summary> 音声クエリ(Byte配列) </summary>
    private byte[] _audioQueryBytes;
    /// <summary> 音声クエリ(Json文字列) </summary>
    private string _audioQuery;
    /// <summary> 音声クリップ </summary>
    private AudioClip _audioClip;

    /// <summary> 音声クエリ(Json文字列) </summary>
    public string AudioQuery { get => _audioQuery; }
    /// <summary> 音声クリップ </summary>
    public AudioClip AudioClip { get => _audioClip; }

    /// <summary>
    /// 指定したテキストを音声合成、AudioClipとして出力
    /// </summary>
    /// <param name="speakerId">話者ID</param>
    /// <param name="text">テキスト</param>
    /// <returns></returns>
    [Obsolete]
    public IEnumerator TextToAudioClip(int speakerId, string text)
    {
        // 音声クエリを生成
        yield return PostAudioQuery(speakerId, text);

        // 音声クエリから音声合成
        yield return PostSynthesis(speakerId, _audioQueryBytes);
    }

    /// <summary>
    /// 音声合成用のクエリ生成
    /// </summary>
    /// <param name="speakerId">話者ID</param>
    /// <param name="text">テキスト</param>
    /// <returns></returns>
    public IEnumerator PostAudioQuery(int speakerId, string text)
    {
        _audioQuery = "";
        _audioQueryBytes = null;
        // URL
        string webUrl = $"{AUDIO_QUERY_URL}?speaker={speakerId}&text={text}";
        // POST通信
        using (UnityWebRequest request = new UnityWebRequest(webUrl, "POST"))
        {
            request.downloadHandler = new DownloadHandlerBuffer();
            // リクエスト(レスポンスがあるまで待機)
            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.ConnectionError)
            {
                // 接続エラー
                Debug.Log("AudioQuery:" + request.error);
            }
            else
            {
                if (request.responseCode == 200)
                {
                    // リクエスト成功
                    _audioQuery = request.downloadHandler.text;
                    _audioQueryBytes = request.downloadHandler.data;
                    Debug.Log("AudioQuery:" + request.downloadHandler.text);
                }
                else
                {
                    // リクエスト失敗
                    Debug.Log("AudioQuery:" + request.responseCode);
                }
            }
        }
    }

    /// <summary>
    /// 音声合成
    /// </summary>
    /// <param name="speakerID">話者ID</param>
    /// <param name="audioQuery">音声クエリ</param>
    /// <returns></returns>
    [Obsolete]
    public IEnumerator PostSynthesis(int speakerID, string audioQuery)
    {
        return PostSynthesis(speakerID, Encoding.UTF8.GetBytes(audioQuery));
    }

    /// <summary>
    /// 音声合成
    /// </summary>
    /// <param name="speakerId">話者ID</param>
    /// <param name="audioQuery">音声クエリ(Byte配列)</param>
    /// <returns></returns>
    [Obsolete]
    private IEnumerator PostSynthesis(int speakerId, byte[] audioQuery)
    {
        _audioClip = null;
        // URL
        string webUrl = $"{SYNTHESIS_URL}?speaker={speakerId}";
        // ヘッダー情報
        Dictionary<string, string> headers = new Dictionary<string, string>();
        headers.Add("Content-Type", "application/json");

        using (WWW www = new WWW(webUrl, audioQuery, headers))
        {
            // レスポンスが返るまで待機
            yield return www;

            if (!string.IsNullOrEmpty(www.error))
            {
                // エラー
                Debug.Log("Synthesis : " + www.error);
            }
            else
            {
                // レスポンス結果をAudioClipで取得
                _audioClip = www.GetAudioClip(false, false, AudioType.WAV);
            }
        }
    }
}

「WWW」クラスは最新版のUnityでは非推奨で、
「UnityWebRequestMultimedia」クラスを使用するのを推奨している。

ただ、「UnityWebRequestMultimedia」クラスはGET通信のみしか対応していなかったため今回は非採用。
https://docs.unity3d.com/ja/2018.4/ScriptReference/Networking.UnityWebRequestMultimedia.GetAudioClip.html

【3】テスト用のスクリプト作成

ひとまず、Unityでテスト実行したいので
アプリ実行時に指定した文章を喋るC#スクリプトを作成しましょう!

以下はアプリ実行時に「春日部つむぎ」さんに「こんにちは!みんなもUnityでVOICEVOXを使おう!」と喋らせるコードです。

VoiceVoxTest.cs

using System.Collections;
using UnityEngine;

public class VoiceVoxTest : MonoBehaviour
{
    [SerializeField]
    private AudioSource _audioSource;

    void Start()
    {
        StartCoroutine(SpeakTest("こんにちは!みんなもUnityでVOICEVOXを使おう!"));
    }

    IEnumerator SpeakTest (string text)
    {
        // VOICEVOXのREST-APIクライアント
        VoiceVoxApiClient client = new VoiceVoxApiClient();

        // テキストからAudioClipを生成(話者は「8:春日部つむぎ」)
        yield return client.TextToAudioClip(8, text);

        if (client.AudioClip != null)
        {
            // AudioClipを取得し、AudioSourceにアタッチ
            _audioSource.clip = client.AudioClip;
            // AudioSourceで再生
            _audioSource.Play();
        }
    }
}

【4】Unityに空のGameObjectを用意

ここからはScriptのアタッチ方法なので、Unityに詳しい方は読まなくても大丈夫です!

空のGameObjectを用意
※ [Hierarchy] で右クリック [Create Empty]から作成できます。

ここでは VoiceVoxTest という名称のGameObjectを用意

GameObject追加_VoiceVoxTest.png

【5】コンポーネントを追加

  1. 用意した VoiceVoxTest(GameObject)VoiceVoxTest(Script) をアタッチ

  2. VoiceVoxTest(GameObject) にAudioSourceをアタッチ(Add Componentから追加できます)

  3. アタッチした VoiceVoxTest(Script) のフィールド [AudioSource] に [2.] で用意したAudioSourceをアタッチ

Inspector_VoiceVoxTest.png

以下に一連の流れをGIFアニメ化しました。

Unity_VoiceVoxアタッチ.gif

【6】実行!

アプリ実行してみて、
「こんにちは!みんなもUnityでVOICEVOXを使おう!」と音声が聞こえれば成功です!

補足

話者IDって何?

話者を決めるIDです。
この話者IDの定義はVOICEVOXのREST-API経由で取得できます。

VOICEVOXを起動して、ブラウザから以下のURLにアクセスすると閲覧できます。

json形式で取得するため、別途ブラウザのプラグインなどを用意するとよいかと思います。
(以下Chromeのプラグイン)

以下から「春日部つむぎ(ノーマル)」の話者IDが「8」であることが分かります。
VoiceVox_Speakers.png

最後に

今回はUnityでVOICEVOXを使用する手順を簡単に紹介しました。

サンプルコードではアプリ起動時に喋る処理にしていますが、UGUIのInputFieldからテキストを取得、ButtonのOnClickイベントでVOICEVOXのAPIを叩くようにすればチャットアプリみたいなのも作れるかと思います。

また、VOICEVOXを使用する場合は必ず利用規約を守り、クレジット表記するようにしましょう!

参考サイト

27
19
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?