1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Voicevox Core から PulseAudio へ音声を流す Python スクリプトを作ってみた

1
Last updated at Posted at 2026-04-07

はじめに

みなさまご存知の Text-to-Speech(TTS)ソフト VOICEVOX を使って、Ubuntu 24.04 on WSL2 で喋らせてみました。ホストの Windows 11 が Ubuntu 24.04 に PulseAudioサーバー を提供しているので、音声を合成したら、そちらへ流します。

コードの設計

VOICEVOXの使い方について、過去のブログ記事を漁ってみると、Linux 上で Docker で API サーバーを立てるとか、Windows にインストールして API でつなぐ方法を見つけました。ちょっと大変そうです。しかし、調べているうちに VOICEVOX Core には Python Binding もあることを発見。今回はこれを利用させてもらことにしました。

VOICEVOX Core レポジトリには、Pythonを使ったサンプルスクリプト talk.py があります。最初は、この talk.py をシェルスクリプトで包んで、一旦 wav データをファイルに書いてから、PulseAudio へ paplay で出そうと思ったのですが、サンプルなので Wav ファイルを出力して終わり。スピード調整などの機能も無さそう。

PulseAudio にも Python Binding あるようです。

ならばと VOICEVOX と PulseAudio を Python でガッチャンコくっつけて、生成した音声を直接流すスクリプトを書いてみることにしました。:apple::pen_ballpoint:

そういう訳で、Claude Code にお願いして誕生 したのが、こちらになります。

voicevox_paplay スクリプト

使い方

スクリプトの説明のため、先に使い方から説明します。後述のインストールと環境確認が済んだら実行できます。

1. 話者スタイルの確認

まずは、利用可能な 話者・スタイル ID の確認です。

$ voicevox_paplay --list-speakers
0.vvm
├── 四国めたん
│   ├── あまあま  (style-id: 0) ◀
│   ├── ノーマル  (style-id: 2)
│   ├── セクシー  (style-id: 4)
│   └── ツンツン  (style-id: 6)
├── ずんだもん
│   ├── あまあま  (style-id: 1)
│   ├── ノーマル  (style-id: 3)
│   ├── セクシー  (style-id: 5)
│   └── ツンツン  (style-id: 7)
├── 春日部つむぎ
│   └── ノーマル  (style-id: 8)
└── 雨晴はう
    └── ノーマル  (style-id: 10)

右側の「◀」は --style-id オプションで指定する「現在選ばれている話者・スタイル」を示しています。今回のように明示的な指定がなったときは、一番小さい番号の style-id になります。

2. 喋らせてみる

スピーカーから音声を出します。

# テキストだけ指定(デフォルト話者)
$ voicevox_paplay "こんにちは"

# 標準入力から流す
$ echo "こんにちは" | voicevox_paplay

# 話者スタイルを指定
$ voicevox_paplay --style-id 3 "こんにちは、ずんだもんだよ!"

# 話者モデルファイルを指定(既定は 0.vvm)
$ voicevox_paplay --vvm 5.vvm --style 22 小声でずんだもんだよ

# スピードを 1.5 倍にする
$ voicevox_paplay --style-id 3 --speed 1.5 "早口で喋ります"

# WAV ファイルに保存(再生なし)
$ voicevox_paplay --style-id 3 --out output.wav "こんにちは"

3. verbose 出力

詳細なログを出力して、いま何が起こっているのか、動作を確認できます。

$ voicevox_paplay --verbose "テスト音声です"
[   0.001s] --- args ---
[   0.001s]   style-id       = -1
[   0.001s]   speed          = 1.0
[   0.001s]   pitch          = 0.0
[   0.001s]   intonation     = 1.0
[   0.001s]   volume         = 1.0
[   0.001s]   pre_silence    = None
[   0.001s]   post_silence   = None
[   0.001s]   device         = CPU
[   0.001s]   voicevox_dir   = /usr/lib/voicevox-core
[   0.001s]   onnxruntime    = /usr/lib/voicevox-core/onnxruntime/lib/libvoicevox_onnxruntime.so.1.17.3
[   0.001s]   dict_dir       = /usr/lib/voicevox-core/dict/open_jtalk_dic_utf_8-1.11
[   0.001s]   vvm_dir        = /usr/lib/voicevox-core/models/vvms
[   0.001s]   vmms           = ['0.vvm']
[   0.001s]   cache_dir      = None
[   0.001s]   outfile        = None
[   0.001s]   list_speakers  = False
[   0.001s] --- env ---
[   0.001s]   PULSE_SERVER   = unix:/mnt/wslg/PulseServer
[   0.001s]   PULSE_COOKIE   = (unset)
[   0.001s]   XDG_RUNTIME_DIR= /run/user/1000/
[   0.001s]   XDG_CACHE_HOME = (unset)
[   0.001s]   Python         = 3.12.3 (main, Mar  3 2026, 12:15:18) [GCC 13.3.0]
[   0.001s]   cpu_count      = 4
[   0.001s] Onnxruntime.load_once: /usr/lib/voicevox-core/onnxruntime/lib/libvoicevox_onnxruntime.so.1.17.3
[   0.010s]   supported_devices: cpu
[   0.010s] Synthesizer init: device=CPU, dict_dir=/usr/lib/voicevox-core/dict/open_jtalk_dic_utf_8-1.11, cpu_num_threads=4
[   0.010s]   is_gpu_mode=False
[   0.010s] VVM search: dir=/usr/lib/voicevox-core/models/vvms, patterns=['0.vvm'], found=1
[   0.010s]   scanning meta: 0.vvm
[   0.010s] 1 model(s) scanned
[   0.010s] style-id resolved to 0
  0.vvm: style-id: 0: 四国めたん (あまあま) ◀
  0.vvm: style-id: 2: 四国めたん (ノーマル)
  0.vvm: style-id: 4: 四国めたん (セクシー)
  0.vvm: style-id: 6: 四国めたん (ツンツン)
  0.vvm: style-id: 1: ずんだもん (あまあま)
  0.vvm: style-id: 3: ずんだもん (ノーマル)
  0.vvm: style-id: 5: ずんだもん (セクシー)
  0.vvm: style-id: 7: ずんだもん (ツンツン)
  0.vvm: style-id: 8: 春日部つむぎ (ノーマル)
  0.vvm: style-id: 10: 雨晴はう (ノーマル)
[   0.011s] target text:
  テスト音声です
[   0.011s]   lazy loading: 0.vvm
[   0.374s]   loaded: 0.vvm
[   0.374s] create_audio_query: style-id: 0 "四国めたん (あまあま)"
[   0.385s] synthesis: {'style_id': 0, 'speed': 1.0, 'pitch': 0.0, 'intonation': 1.0, 'volume': 1.0, 'pre_silence': None, 'post_silence': None}
[   0.757s]   synthesis done: 65,580 bytes
[   0.759s] PulseAudio playback: 1ch, 24000Hz, 16bit, 32768 frames (1.37s), pcm=65,536 bytes
[   0.759s]   timeout set: 11.4s
[   0.762s]   pa_simple_new done, writing
[   1.079s]   write done, draining
[   2.159s]   drain done
[   2.160s]   timeout cleared (remaining: 10.0s)

4. 音声キャッシュ

お喋りした音声の WAV データを、ファイルに自動保存し、再利用できます。話者やスピードなどが過去のお喋りと同一かをチェックし、同じであれば音声合成を省いて、保存した WAV データを直接再生します。

# 音声キャッシュを削除
$ rm ~/.cache/voicevox_paplay/ -rf

# 初回は、音声を再生後に保存
$ time voicevox_paplay --cache 以前に話した内容を覚えるよ
real    0m3.573s
user    0m2.991s
sys     0m0.180s

# 2回目以降、保存したデータを再生
$ time voicevox_paplay --cache 以前に話した内容を覚えるよ
real    0m2.523s
user    0m0.055s
sys     0m0.013s

音声合成モデル(vvmファイル)のローディング時間と合成時間が無いので、発話までのレスポンスが改善します。

--cache の代わりに --cache-dir を使えば、保存場所を指定できます。

インストール方法

1. VOICEVOX Core のインストール

VOICEVOX Core のダウンローダーで、モデルデータ等を取得します。

curl -sSfL https://github.com/VOICEVOX/voicevox_core/releases/latest/download/download-linux-x64 -o download
chmod +x download
sudo ./download -o /usr/lib/voicevox-core --exclude c-api

インストール先のディレクトリは -o /usr/lib/voicevox-core で指定しています。変更した場合は voicevox_paplay 実行時にも --voicevox-dir でこの場所を教えてあげる必要があります。もしくは、voicevox_paplay スクリプト自体を直接書き換えましょう。

自分の Home Directory に入れる場合は、もちろん sudo 不要です。

GitHub の rate limit でエラーになったら、gh auth login で認証しておくと緩和されます。

2. Python Binding のインストール

VOICEVOX Core と PulseAudio の Python パッケージを入れます。バージョンは適宜変更してください。

pip install https://github.com/VOICEVOX/voicevox_core/releases/download/0.16.0/voicevox_core-0.16.0+cpu-cp310-abi3-linux_x86_64.whl
pip install pasimple

3. voicevox_paplay のダウンロード

ダウンロード後、PATH の通った場所に置くか、PATH を編集して通しましょう。

curl -o voicevox_paplay https://raw.githubusercontent.com/h2suzuki/terminal-configs/main/files/voicevox_paplay
chmod +x voicevox_paplay

4. 【環境チェック】 PulseAudio に出力できることを確認

念の為、PulseAudio のオーディオ出力が生きているか、事前に確認しておきます。ここが通らないと、voicevox_paplay 以前の問題ですので。

$ paplay /usr/share/sounds/alsa/Front_Center.wav

スピーカーから、英語で「フロント・センター」と流れたはず。

なお、paplay は PulseAudio に含まれるテスト用コマンドです。Alsa に含まれる aplay の PulseAudio 版といったところ。

5. voicevox_paplay で喋らせてみる

最後に VOICEVOX で音声合成し、PulseAudio に流してみます。

$ voicevox_paplay フロント・センター

スピーカーから、日本語で「フロント・センター」と流れたら、幸せ。 :smirk:

voicevox_paplay の docstring
インストール方法は、本スクリプト先頭の docstring にも記載してあります。

まとめ

  • WSL2 環境では PulseAudio → WSLg 経由で、Windows ホストに簡単に音声出力できます。
  • VOICEVOX Core の Python Binding を使えば、Docker や Windows アプリなしで、音声合成できます。
  • VOICEVOX と PulseAudio を直結するスクリプト voicevox_paplay を作りました。

おまけ

この Python スクリプトは、素の Claude Code に依頼して書きましたが、最初のプロンプトで要件を伝えたところ、すぐ 70点くらいのコードを生成してくれました。そこからは私のレビューと Claude による修正の反復作業が続くのですが、Opus 4.6 だからか、異常終了するようなバグは数件だけでした。毎月のように精度が上がっていき、すごいなと。:astonished:

反復中のコード変更(10件のCommit)について、なぜ反復が必要だったかの原因分析も Claude Code にさせてみました。Claude と一緒に何ターンか推敲して、最終的に抽出された学びが、こちらです。

A. 仕様策定の不備 — ユーザーインターフェースの設計判断が欠落(4 件)
B. 局所的な正しさで完了する — 副次的影響・全体との整合を見ない(6 件) 
C. 体験の質の参照基準がない — 「動く」の先の「良い」を評価していない(横断的)

提案された対策がこちら。

## 対策

### A → 仕様先行

実装前に「ユーザーに見える面」の設計判断を明示的に行う。

- デフォルト値の設計思想(副作用を伴う機能は opt-in か opt-out か)
- 出力の仕様(順序、書式、表示幅の扱い)
- エラー表示の方針(何をどこまで見せるか)
- ログ・verbose に含める情報と含めない情報の境界                                                   

### B → 副次的影響の確認

実装手段を選ぶとき、「目的を達成するか」だけでなく「他に何が起きるか」を確認する。

- この関数/オプションは、目的以外に何を出力・変更するか
- この追加は、既存のコード・出力と重複や矛盾を生まないか
- この値は、本当にリテラルで書くべきか、別の場所から導出すべきか                                     

### C → 参照基準との比較

実装後、同じ領域で広く使われている良質なツールと体験を比較する。
「動く」は検証済みとして、その先の「良いか」を評価する基準を外部に求める。

## CLAUDE.md 向けルール

1. **仕様先行**: ユーザーに見える振る舞い(デフォルト値、出力形式、エラー表示、ログ内容)は実装前に決定する
2. **副次的影響の確認**: 実装手段を選ぶとき、目的の達成だけでなく「他に何が起きるか」を確認する
3. **参照基準との比較**: 実装後、同じ領域の良質なツールとユーザー体験を比較し、「動く」の先の「良い」を評価する                                                                                      

「動く」の先の「良い」を評価していない。とか、なかなか痺れる文言です(笑)
この辺りは Skills とかでカバーできるか色々と試してみようかと思います。

※ この記事も Claude in Chrome を利用して書いています。

1
2
0

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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?