RaspberryPiの音声合成にリアルタイム性を求めるには?VOICEVOX Engineの活用

以前はVOICEVOX CORE(コアライブラリ)をRaspberryPiへインストールして音声合成を試してみたのですが、合成されるまでにかなりに時間がかかってしまうため、リアルタイムのコミュニケーションに使用するには実用性が低いという結果でした。

uepon.hatenadiary.com

そこで今回はRaspberryPiからLAN内にインストールをしたVOICEVOX Engine(EngineはWebサーバーとしてREST APIを提供)にアクセスして音声合成の結果のみをもらうという形で使用してみたいと思います。一見あまり意味がなさそうに思いますが、同様にしてRaspberryPi Zero WなどからAPIアクセスすれば、かなり非力なデバイスでも音声合成を使用することができるかなと思います。

VOICEVOX Engineのインストール

VOICEVOX EngineGitHubリポジトリは以下となります。

github.com

プラットフォーム用のバイナリ(自分の場合にはWindows版)をダウンロードする方法とDockerコンテナを使用する方法があります。

Windows版は環境毎にダウンロードを行って展開すればインストールは完了します。含まれているrun.exeを起動することでAPIへのアクセスができるようになります。GPUがある場合には積極的にそちらを使用しましょう。

github.com

Dockerコンテナを使用する場合には以下のようにコンテナを起動すればOKです。(GitHubでのコンテナ起動はポートのフォワード設定が外部アクセス向けではないので、IPを指定しないように)自分はVolumeを使用してファイル共有などを行いたかったので-vオプションも追加しています。

CPUのみの使用するコンテナ

$ docker pull voicevox/voicevox_engine:cpu-ubuntu20.04-latest
$ docker run --rm -p 50021:50021 -v /c/DockerShare:/dockershare voicevox/voicevox_engine:cpu-ubuntu20.04-latest

GPUを使用するコンテナ

$ docker pull voicevox/voicevox_engine:nvidia-ubuntu20.04-latest
$ docker run --rm --gpus all -p 50021:50021 -v /c/DockerShare:/dockershare voicevox/voicevox_engine:nvidia-ubuntu20.04-latest

今回はGPUのコンテナを使用します。

初回起動ではreadme.mdでライセンスなどの説明が表示されます。

以下のように表示が行われていればコンテナは起動しています。(停止は【Ctrl+C】で行い、コンテナは終了とともに削除されます)

コンテナが起動しているPCでブラウザを開き、localhost:50021にアクセスすることで、サービスが動作しているのを確認剃ることができます。または、localhost:50021/docsへアクセスすればAPIのドキュメントが表示されるでしょう。

APIドキュメントページ

以降はRaspberryPiで操作を行っていきます。

VOICEVOX EngineへのAPIアクセス

今回は音声の生成まで行ってみます。 使用するAPI/audio_query音声合成のクエリの作成)と/synthesis音声合成する)を使用することにします。

ドキュメントページのURL、http://localhost:50021/docsまたは【コンテナ起動をしているWindowsのIP】:50021/docsにアクセスすることでAPIの使用方法がわかります。

/audio_query音声合成のクエリの作成)

/synthesis音声合成する)

音声合成する文を直接設定することもできますが、ファイルに一旦格納して使用しています。また、VOICEVOX Engineを起動しているWindowsのPCのIPアドレス192.168.0.18という想定になっています。途中@text.txtなどとなっている部分はファイル内容を展開して埋め込んでくれます。

今回、スピーカーには「ずんだもん」を使用しています。

$ echo -n "こんにちは、世界" >text.txt

# クエリ生成
$ curl -s -X POST "192.168.0.18:50021/audio_query?speaker=1" --get --data-urlencode text@text.txt > query.json

# ちなみに読み上げのテキストをCLIに直接いれる場合には以下
$ curl -s -X POST "192.168.0.18:50021/audio_query?speaker=1" --get --data-urlencode "text=こんにちは、世界" > query.json

# 音声合成ファイルの生成
$ curl -s -H "Content-Type: application/json" -X POST -d @query.json "192.168.0.18:50021/synthesis?speaker=1" > audio.wav

クエリの生成では直接ファイル出力していますが、以下のようなクエリが作成されていました。このクエリを更に使用して音声合成を行っています。

{
  "accent_phrases": [
    {
      "moras": [
        {
          "text": "",
          "consonant": "k",
          "consonant_length": 0.10002632439136505,
          "vowel": "o",
          "vowel_length": 0.15740256011486053,
          "pitch": 5.7707061767578125
        },
        {
          "text": "",
          "consonant": null,
          "consonant_length": null,
          "vowel": "N",
          "vowel_length": 0.08265873789787292,
          "pitch": 5.928380966186523
        },
        {
          "text": "",
          "consonant": "n",
          "consonant_length": 0.03657080978155136,
          "vowel": "i",
          "vowel_length": 0.11737360805273056,
          "pitch": 6.031623840332031
        },
        {
          "text": "",
          "consonant": "ch",
          "consonant_length": 0.08903316408395767,
          "vowel": "i",
          "vowel_length": 0.08451663702726364,
          "pitch": 6.013186931610107
        },
        {
          "text": "",
          "consonant": "w",
          "consonant_length": 0.07740496098995209,
          "vowel": "a",
          "vowel_length": 0.18215857446193695,
          "pitch": 5.985758304595947
        }
      ],
      "accent": 5,
      "pause_mora": {
        "text": "",
        "consonant": null,
        "consonant_length": null,
        "vowel": "pau",
        "vowel_length": 0.3451445698738098,
        "pitch": 0
      },
      "is_interrogative": false
    },
    {
      "moras": [
        {
          "text": "",
          "consonant": "s",
          "consonant_length": 0.12513203918933868,
          "vowel": "e",
          "vowel_length": 0.12418756633996964,
          "pitch": 6.064120292663574
        },
        {
          "text": "",
          "consonant": "k",
          "consonant_length": 0.10047850757837296,
          "vowel": "a",
          "vowel_length": 0.1664535254240036,
          "pitch": 6.237164497375488
        },
        {
          "text": "",
          "consonant": null,
          "consonant_length": null,
          "vowel": "i",
          "vowel_length": 0.1945553869009018,
          "pitch": 6.0630011558532715
        }
      ],
      "accent": 1,
      "pause_mora": null,
      "is_interrogative": false
    }
  ],
  "speedScale": 1,
  "pitchScale": 0,
  "intonationScale": 1,
  "volumeScale": 1,
  "prePhonemeLength": 0.1,
  "postPhonemeLength": 0.1,
  "outputSamplingRate": 24000,
  "outputStereo": false,
  "kana": "コンニチワ'、セ'カイ"
}

そして作成された音声は以下の様になります。

生成された合成音声の出力まで行うのであれば以下の様に連続して実行することで実現できます。音声出力はaplayコマンドで行います。

$ curl -s -X POST "192.168.0.18:50021/audio_query?speaker=1" --get --data-urlencode "text=こんにちは、世界" > query.json \
&& curl -s -H "Content-Type: application/json" -X POST -d @query.json "192.168.0.18:50021/synthesis?speaker=1" > audio.wav \
&& aplay audio.wav

おわりに

RaspberryPiからWindowsにインストールしたVOICEVOX EngineREST APIにアクセスして、音声合成を行うことができました。

アクセス側のPCのスペックにもよりますが、RaspberryPi単体での音声合成に比べれば圧倒的に高速に音声合成を行うことができます。GPU付きのデスクトップPCで行ったところクエリ生成、音声合成合わせて1秒ぐらいで音声が生成されていました。

この方式を用いれば、かなりリアルタイムに近い音声の反応ができるようになりますし、より小型のデバイスでも音声合成ができるのもかなり魅力的です。

/* -----codeの行番号----- */