VOICEVOX API (エンジン)にHTTPリクエストをするための手引書

## はじめに

VOICEVOXを使った音声合成を、エディターを使わずにHTTPリクエストを用いて行うための手引書です。  
以下の章立てで解説をしていきます。

1. VOICEVOXのHTTPサーバー機能について
2. サーバーに投げるクエリの内容とその投げ方
3. wavファイルの保存の仕方
4. (おまけ) VOICEVOXエンジンAPIドキュメントの読み方とAPIの使い方
5. (おまけ)エディターを起動せずにエンジンを起動する方法
6. (おまけ)HTTPリクエストを使わずに音声を合成するVOICEVOX COREの紹介
7. 音声合成のPythonサンプルコード

## 1. VOICEVOXのHTTPサーバー機能について

VOICEVOXにはGUIを使う他にも音声を合成する方法があり、その1つがHTTPリクエストを使用する方法です。  
VOICEVOXは大まかに分割するとエディターとエンジンとコアという3つのモジュールが組み合わさってできています。エディターはVOICEVOXアプリケーションのGUI部分、エンジンはHTTPサーバー(音声合成のリクエストなどを受け取る)部分、コアは実際に音声を合成する部分となっています。通常のVOICEVOXアプリケーションを利用の際はエディターに入力することでエディターがエンジンにHTTPリクエストを送り、エンジンがコアを使って音声を合成するという流れになっています。

<center><img width="800" alt="VOICEVOX-Image" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721129/18ada333-8de0-0307-6156-931e4693adec.png"></center>

つまり、エンジンにHTTPリクエストを送ることができればエディターを使わなくても音声の合成が可能となるわけです。今回はPythonを例に挙げて説明しますが、他言語でも同等の機能を用いれば音声合成をすることが可能です。



## 2. サーバーに投げるクエリについて

続いて実際にVOICEVOXエンジンにどのようなクエリを投げればよいかを説明します。初めに、音声を合成するためのクエリに必要なjsonファイルをVOICEVOXエンジンのドキュメントにあるコード例からお借りして示します。先に言っておきますが、このようなクエリを実際に自作する必要はないので安心してください。

```python:クエリに使うjsonファイルの例
{
  "accent_phrases": [
    {
      "moras": [
        {
          "text": "string",
          "consonant": "string",
          "consonant_length": 0,
          "vowel": "string",
          "vowel_length": 0,
          "pitch": 0
        }
      ],
      "accent": 0,
      "pause_mora": {
        "text": "string",
        "consonant": "string",
        "consonant_length": 0,
        "vowel": "string",
        "vowel_length": 0,
        "pitch": 0
      },
      "is_interrogative": false
    }
  ],
  "speedScale": 0,
  "pitchScale": 0,
  "intonationScale": 0,
  "volumeScale": 0,
  "prePhonemeLength": 0,
  "postPhonemeLength": 0,
  "outputSamplingRate": 0,
  "outputStereo": true,
  "kana": "string"
}
```

このようなjsonファイルを用いてVOICEVOXエンジンにクエリを投げることで音声データを得ることができますが、これを全て自分で作成しようとすると少し面倒です。しかし、VOICEVOXエンジンには、このjsonファイルを用意するための機能が用意されており、そのためのクエリは以下のような簡単なものになっています。

```python:実際に作成するquery
import requests 
url="http://localhost:50021/audio_query"  # 50021はデフォルトポートなので、変更した場合は変える
params={"text": "ここに喋らせたいテキスト", "speaker": 3}  # 3はずんだもんのノーマルスタイル
timeout = 15  # timeoutは環境によって適切なものを設定する
json_synthesis = requests.post(url, params=params, timeout=timeout)
```

:::note warn
requestsライブラリは標準ライブラリではないので、未インストールの場合はpip install requestsを行ってください。
:::

このコードを実行することで、実際に合成音声に必要なjsonファイル (先ほど例に挙げたようなもの) がjson_synthesisに格納されます。こちらの方が扱いやすく簡単なため、実際に音声合成を行う際はこちらの簡単なクエリをVOICEVOXエンジンに投げることで音声合成用のjsonファイルを手に入れます。speakerの値は[ここ](https://github.com/VOICEVOX/voicevox_fat_resource/blob/main/core/model/README.md#%E9%9F%B3%E5%A3%B0%E3%83%A2%E3%83%87%E3%83%ABvvm%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A8%E5%A3%B0%E3%82%AD%E3%83%A3%E3%83%A9%E3%82%AF%E3%82%BF%E3%83%BC%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E5%90%8D%E3%81%A8%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB-id-%E3%81%AE%E5%AF%BE%E5%BF%9C%E8%A1%A8)に書かれてあるのを参照してください。  
そしてここで受け取った音声合成用のjsonファイルを以下のようにそのままVOICEVOXエンジンに投げることで音声データを得ることができます。

```python:音声合成のためのquery
params = {"speaker": 3}  # paramsは先ほどと同じものを流用しても良い
response = requests.post(
            "http://localhost:50021/synthesis",
            params=params,
            json=json_synthesis.json()
        )
```

## 3. wavファイルの保存の仕方

先ほどのクエリを送信した際の応答を格納したresponseから、wavデータを取り出し保存する方法を説明します。  
まずはresponseから生成されたwavデータを取り出します。responseからボディデータ(今回は音声データ)を抜き出す方法は2つ用意されており、1つはresponse.textのようにテキストデータとして抜き出す方法、もう1つはresponse.contentのようにバイナリデータとして抜き出す方法です。これは実際に返されたデータに合わせる必要があり、VOICEVOXエンジンではバイナリデータとして返されるので今回はcontentを使用します。そして、そのバイナリ状態の音声データを保存することでwavファイルにすることができます。保存方法はいくつかありますが、以下に具体例を挙げます。

```python:wavファイルとして保存
from pathlib import Path
wav = response.content
path = "sample.wav"  # 保存場所
out = Path(path)
out.write_bytes(wav)
```

これで、sample.wavという名前で音声が保存されます。

## 4. (おまけ) VOICEVOXエンジンAPIドキュメントの読み方

音声の合成自体は3章までの内容でできますが、辞書登録などの他のAPI機能を使おうと思ったとき、そのための解説を探すのは大変だと思います。そこで、VOICEVOXエンジンを利用する上でのAPIドキュメントの読み方と使い方を解説するので参考にしてください。  
まず、APIドキュメントへのアクセス方法です。APIドキュメントは、VOICEVOXを起動した状態で[http://localhost:50021/docs](http://localhost:50021/docs) にアクセスすると閲覧することができます。WEB検索しても出てきますが個人的にはこちらの方が読みやすいかと思います。アクセスすると以下のようなページが開きます。各機能の簡単な説明がそれぞれ書かれており、クリックすると詳細が展開されます。

<center><img width="800" alt="VOICEVOX-API" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721129/0f5896a2-39c5-b881-ff79-1387af48725c.png"></center>

まずこの画面について説明していきます。それぞれの機能に左側に、POST、GET、PUT、DELETEのいずれかが書かれていると思います。これは、この機能を使うときに使用するHTTPリクエストの種類を表しています。例えば、一番上の/audio_queryのクエリを作成するためにはPOSTリクエストをすればいいということが分かります。2章に戻って音声合成のクエリを作成する部分のコードを見るとrequests.postとなっていることが分かると思います。Pythonのrequestsライブラリを使う場合は、このように簡単にリクエストの種類を使い分けることができます。例えばputを使いたければrequests.putに変更するだけでパラメータの指定方法などは同じです。

続いて、URLの指定方法について説明します。URLについては簡単で、POSTやGETのすぐ右に書かれているスラッシュから始まる文字列をhttp\://localhost:50021の後ろにつなげるだけです。例えば、/audio_queryであれば、http\://localhost:50021/audio_queryとなります。

では、パラメータ指定の方法についても解説します。一番上の/audio_queryを展開してみると、ParametersとResponsesというのがあると思います。Parametersがparamsに指定するもので、Responsesが応答です。赤字でrequiredと付いているものが必ず必要なパラメータです。/audio_queryであれば、textとspeakerというパラメータの指定が必ず必要であることが分かります。それぞれのパラメータの真下に書かれているstringやintegerはそのパラメータに渡すデータの種類です。stringであればテキストデータを、integerであれば整数データを渡します。そのため、/audio_queryのパラメータは以下のようになります。

```python:audio_queryのparams
params={"text": "喋らせたいテキスト", "speaker": 3}
```

基本的には他のクエリも同様に作成します。そしてこの形式でクエリを投げると、成功すればCode 200と書かれている部分のデータが返ってきます。失敗すればCode 422と書かれている部分のデータが返ってきます。今回であれば、どちらの場合でもjsonデータが返ってくることが分かります。この流れは、基本的には他のVOICEVOX APIも同じようになっています。ただし、一部違っているものもあります。例えば、2章でも使った/synthesisを見てみると、Request bodyというものがあります。これはparamsとは別で指定してあげる必要があるものです。このようなbodyデータはdataやjsonとして指定するのですが、細かい説明は省きます。VOICEVOXでは投げるデータは全てjsonデータなので2章の「音声合成のためのquery」コードにあるようにjsonで指定すればいいです。つまり、2章の流れをもう一度説明すると、/audio_queryにtextとspeakerというparamsを指定してクエリを投げるとjsonが返ってくる、そして/synthesisにspeakerというparamsと先ほど得たjsonを格納した変数をjsonに指定してクエリを投げるとwavデータが返ってくるということです。このwavがどういうデータかというのは下記画像の赤下線部分のSchemaをクリックして内容を見るとstring binaryとなっており、バイナリテキストであることが分かります。

<center><img width="800" alt="Schema" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721129/18d15f33-5014-36fe-8488-676a4f26698e.png"></center>

これでAPIドキュメントの読み方とおおよそのAPIの使い方が分かったかと思います。

## 5. (おまけ)エディターを起動せずにエンジンを起動する方法

ここまでVOICEVOXエンジンを使って音声を合成する方法を説明してきましたが、現状ではVOICEVOXアプリケーションを起動した状態でしか実行できません。しかし、エディターは不要でプログラム上で完結したいと考える人もいると思います。その場合はエンジンとコアのみを利用することもでき、そのためにはDockerというものを利用する必要があります。Dockerの詳しい使い方はそれだけで記事が書けるぐらいの情報量なので省きますが、[VOICEVOXエンジンのGitHubリポジトリ](https://github.com/VOICEVOX/voicevox_engine)にDockerイメージとその実行コマンドがあるのでそれを利用してください。

## 6. (おまけ)HTTPリクエストを使わずにVOICEVOX COREを使って音声を合成する方法

この章はあくまで参考程度の情報ではあるのですが、HTTPリクエストではなくコアに直接アクセスして音声を合成する方法を紹介します。VOICEVOX コアは音声合成を実行するコアの部分であり、実行するためにはOpenJtalk辞書を自分でダウンロードし、読み込んでSynthesizerを初期化するなど、エンジンがやっていたことを自分でやらなければならず使用難易度が高いです。ですが完全に組み込んでしまえるのでHTTPサーバー分のリソースを削減できるというメリットはあります。ここに[VOICEVOX コア ユーザーガイドへのリンク](https://github.com/VOICEVOX/voicevox_core/blob/main/docs/usage.md)を貼っておくので興味のある人は読んでみてください。

## 7. サンプルコード

音声合成のためのサンプルコードです。VOICEVOXアプリケーションまたはVOICEVOXエンジンが起動している状態で実行すると、ずんだもんのノーマルスタイルで「これはサンプルボイスです」という音声が生成されsample.wavとしてカレントディレクトリ内に保存されます。

```python:サンプルコード
import requests
from pathlib import Path

url = "http://localhost:50021/audio_query"
params = {"text": "これはサンプルボイスです", "speaker": 3}  # ずんだもん ノーマルスタイル
timeout = 15
query_synthesis = requests.post(url, params=params, timeout=timeout)

# params = {"speaker": 3}
response = requests.post(
            "http://localhost:50021/synthesis",
            params=params,
            json=query_synthesis.json(),
        )
wav = response.content

path = "sample.wav"  # 保存場所
out = Path(path)
out.write_bytes(wav)
```

:::note warn
(2章でも貼りましたが再掲)
requestsライブラリは標準ライブラリではないので、未インストールの場合はpip install requestsを行ってください。
:::