Post

RubyからVOICEVOXを使って合成音声を生成する

合成音声を生成したい

Discord向けの読み上げBotを作るときに、RubyからVOICEVOXという音声合成ツールを操作したくなったので、メモがてら記します。

やる

環境

  • OS: Debian 11.8
  • Ruby: 3.2.2
  • その他: Dockerコンテナ下

開発環境であるcode-serverのコンテナ内で動作確認をしています。

VOICEVOXをCLIで動かす

依存関係解決

curl, p7zipやlibsndfileが必要なためインストールします。

1
sudo apt install -y curl p7zip libsndfile1

インストール

VOICEVOXをインストールしているけど、GUIは使わないのでVOICEVOX ENGINEだけでもいいかも。

それこそ、Dockerコンテナ建てれるなら、Dockerイメージ使っちゃうのもあり。

以下のコマンドを実行すると、カレントディレクトリに「squashfs-root」というフォルダーが生成される。 その中の、「run」を実行するとHTTPサーバーが建ち、VOICEVOXを使えるっぽい。

1
2
curl -s https://voicevox.hiroshiba.jp/static/fc70af03e46d5bd83329e61236a9cd3d/linuxInstallCpu.sh | bash
~/.VOICEVOX.AppImage --appimage-extract

参考: 合成音声 - Kohda Wiki

実行

1
./squashfs-root/run

を実行することでVOICEVOX ENGINEが起動します。

50021番ポートで待ち受けしているようで、ここにHTTPリクエストを投げてあげることで音声が合成できるようです。

VOICEVOX ENGINE の方にcURLを使用したサンプルコードがありますので、試してみるのも良いでしょう。

Rubyで音声合成

  1. 「http://127.0.0.1:50021/audio_query」のURLクエリにspaekerとtextを指定し、POSTすると合成音声に必要なJSONが返ります。
    • speaker: 数値で指定。ずんだもんなら1、四国めたんなら2など
    • text: 喋らせる文書。URLエンコードをする必要がある。
  2. 「http://127.0.0.1:50021/synthesis」のURLクエリにspeaker、リクエストボディには先ほどのJSONを指定し、POSTするとWAVが返ります。

voicevox.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# frozen_string_literal: true

require 'net/http'
require 'uri'

# VoiceVoxとやり取りするためのクラス
class VoiceVox
  def initialize
    @host = 'http://127.0.0.1:50021'
  end

  # textとspeakerから音声を生成
  def speak(text, speaker = 1)
    query = voice_query(text, speaker)
    generate_voice(query, speaker)
  end

  private

  # VoiceVoxのクエリを作成
  def voice_query(text, speaker)
    response = post_req('/audio_query', { speaker: speaker, text: text })
    response.body
  end

  # クエリから音声を生成
  def generate_voice(query, speaker)
    response = post_req('/synthesis', { speaker: speaker }, query)
    response.body
  end

  # Post送信用関数
  def post_req(endpoint, query, data = '')
    uri = URI.join(@host, endpoint)
    uri.query = URI.encode_www_form(query)
    header = { 'Content-Type' => 'application/json' }
    Net::HTTP.post(uri, data, header)
  end
end

main.rb

1
2
3
4
5
6
7
8
9
10
# frozen_string_literal: true
require_relative 'voicevox.rb'

vb = VoiceVox.new
sound = vb.speak('本日は晴天なり。', 1)

# 保存
File.open('test.wav', 'w') do |file|
  file.write(sound)
end

という2つのファイルを作成し、main.rbを実行することで、test.wavが生成されます。

audio_querysynthesisの両方ともにPOSTリクエストをしなければならず、audio_queryはURLクエリ、synthesisはURLクエリ及びリクエストボディを指定する必要があります。

なお、Content-Typeはどちらもapplication/jsonを受け付けるため、audio_queryには空のリクエストボディを指定しています。

詳細なドキュメントはvoicevox_engine API Documentにまとめられていますので、こちらを参照ください。

おわり

Linuxでも動かせる数少ない音声合成ツールなのでとてもありがたいです・・・。(ボイロは窓だけやしね)

今回使用したのはCPU版とのことで、nVidia GPU対応版を使用するともっと高速に生成することができるらしいです。

音声合成についても、もう少し調整できる部分やユーザー辞書などの機能があるらしく今作ってるBotがその域に達したら触ってみようかなと思います。

追伸

書いてから気づいたけどvoicevox.rbという非公式ラッパーあったわ。

これならHTTPリクエスト使わずともいけるかも(まあええか

コンテンツは CC BY-NC-SA 4.0 の下で利用できます。