piper-plusのPython SDKを使って日本語TTSの推論をしてみる

初めに

今回は、自分が開発しているTTSライブラリ「piper-plus」のPython SDKを使って、日本語の音声合成(Text-to-Speech)を試してみます。

piper-plusはVITSアーキテクチャをベースにした多言語対応の高速TTSシステムで、日本語・英語・中国語・韓国語など8言語に対応しています。Python、npm、C#、Rust、Go、C++、WASMなど多くのプラットフォーム向けSDKを提供していますが、この記事ではPython SDKでの基本的な使い方を紹介します。

github.com

開発環境

  • OS: Windows 11
  • GPU: NVIDIA RTX 4090
  • Python: 3.12
  • パッケージマネージャー: uv
  • CUDA: 12.x
  • piper-plus: 1.10.0

環境構築

プロジェクトの作成

まず、uvでプロジェクトを作成します。

uv init piper-plus-python-demo
cd piper-plus-python-demo

インストール

CPU推論の場合は以下のコマンドでインストールします。

uv add piper-plus

GPU(CUDA)を使って推論したい場合は、inference-gpu extraを指定します。

uv add "piper-plus[inference-gpu]"

日本語モデルのダウンロード

piper-plusにはモデルのダウンロード機能が組み込まれています。利用可能なモデルの一覧は以下のコマンドで確認できます。

uv run python -m piper --list-models ja
Available voice models:

  Japanese (日本語) [ja_JP]:
    ja_JP-css10-6lang-medium                [piper-plus]  1 speaker   medium
    ja_JP-tsukuyomi-chan-medium             [piper-plus]  1 speaker   medium

Use --download-model <name> to download a model.

今回はつくよみちゃんコーパスで学習されたモデルをダウンロードします。

uv run python -m piper --download-model tsukuyomi

ダウンロードが完了すると、以下の2ファイルが配置されます。

  • tsukuyomi-chan-6lang-fp16.onnx — ONNXフォーマットのモデル本体(FP16)
  • config.json — 音素マッピングや音声設定などの構成ファイル

ファイルはカレントディレクトリに配置されます。

基本的な推論

Pythonコードからの推論

PiperVoice クラスを使ってテキストからWAVファイルを生成します。

import wave
from piper import PiperVoice

# モデルの読み込み
voice = PiperVoice.load("tsukuyomi-chan-6lang-fp16.onnx", config_path="config.json", use_cuda=False)

# テキストからWAVファイルを生成
with wave.open("output.wav", "wb") as wav_file:
    voice.synthesize("こんにちは、今日はいい天気ですね。", wav_file)

synthesize() メソッドには以下のパラメータを指定できます。

パラメータ デフォルト 説明
length_scale 1.0 発話速度。小さいほど速くなる
noise_scale 0.667 音声のランダム性。大きいほど表現が多様になる
noise_w 0.8 音素の長さのばらつき
volume 1.0 音量
speaker_id 0 話者ID(マルチスピーカーモデルの場合)
language_id 0 言語ID(ja=0, en=1, zh=2, ko=3, es=4, fr=5, pt=6, sv=7)

パラメータを指定する例です。

with wave.open("output_slow.wav", "wb") as wav_file:
    voice.synthesize(
        "ゆっくり話してみます。",
        wav_file,
        length_scale=1.3,   # ゆっくり
        noise_scale=0.5,    # 安定した音声
        noise_w=0.6,
        volume=0.8
    )

GPU推論

GPU推論を有効にする場合は use_cuda=True を指定します。

voice = PiperVoice.load("tsukuyomi-chan-6lang-fp16.onnx", config_path="config.json", use_cuda=True)

CLIからの推論

Pythonコードを書かずに、コマンドラインから直接推論することもできます。テキストは位置引数として渡します。

uv run python -m piper -m tsukuyomi-chan-6lang-fp16.onnx -f output.wav "こんにちは、音声合成のテストです。"

GPU推論を使う場合は --cuda フラグを追加します。

uv run python -m piper -m tsukuyomi-chan-6lang-fp16.onnx -f output.wav --cuda "こんにちは"

生成した音声をすぐに再生したい場合は --auto-play フラグが便利です。

uv run python -m piper -m tsukuyomi-chan-6lang-fp16.onnx --auto-play "再生テスト"

ストリーミング合成

長いテキストを文ごとに分割してリアルタイムに音声生成する場合は、synthesize_stream_raw() を使います。

import wave
import io
from piper import PiperVoice

voice = PiperVoice.load("tsukuyomi-chan-6lang-fp16.onnx", config_path="config.json")

text = "これはストリーミング合成のテストです。文ごとにチャンクが生成されます。リアルタイムに再生できます。"

# 文ごとにraw PCMデータがyieldされる
with wave.open("stream_output.wav", "wb") as wav_file:
    wav_file.setnchannels(1)
    wav_file.setsampwidth(2)
    wav_file.setframerate(voice.config.sample_rate)

    for audio_chunk in voice.synthesize_stream_raw(text):
        wav_file.writeframes(audio_chunk)

synthesize_stream_raw() は文の区切りごとにraw PCMバイト列をyieldするため、再生ライブラリと組み合わせればリアルタイム再生が可能です。

カスタム辞書と直接フォネム入力

特定の単語の読みを制御したい場合は、[[ ]] 記法でフォネムを直接指定できます。

# 「piper」を「パイパー」と読ませる
text = "[[p a i p a a]]のテストです。"

with wave.open("phoneme_output.wav", "wb") as wav_file:
    voice.synthesize(text, wav_file)

固有名詞や専門用語の読みを正確に制御したい場合に便利です。

所感

piper-plusのPython SDKはインストールからモデルダウンロード、推論まで数行のコードで完結します。GPU推論を使えばリアルタイム以上の速度で音声合成が可能です。次回はnpmパッケージを使ってブラウザ上でTTSを動かしてみます。