Local TTS
デフォルトの音声: Qwen3-TTS 1.7B CustomVoice、話者 aiden、8ビットGGUF(Q8_0)、qwentts.cpp(C++/ggml、MIT)で実行。スタイル指示は以下の通り:
温かく、明確で好奇心旺盛、親しみやすい技術解説動画のナレーターのように。リラックスした、均等なペース。
これは、Kokoro、Chatterbox、PyTorch Qwen3-TTS、VoxCPM2、Phonon に対するブラインドリスニングテストで勝利しました(詳細は references/benchmarks.md を参照)。8 GB RTX 4070 ラップトップGPUでは、モデル読み込みを含めて約4倍のリアルタイム速度で動作します。18分のナレーションは約4.5分で生成されます。
セットアップ(各マシンで1回)
python -I <skill>/scripts/say.py --check を最初に実行してください。OK と表示されれば、このセクションはスキップできます。それ以外の場合はエンジンをセットアップするか、ユーザーにそのように依頼してください。所要時間は10~20分、ディスク容量は約2.5GBです。
- qwentts.cppをビルドする。 事前ビルドされたWindowsバイナリは存在しないため、ソースからビルドします:
Windowsでは、VS 2022(またはそれ以降)ビルドツールをC++ワークロード、CMake、Ninja、CUDA Toolkitとともにインストールし、リポジトリからgit clone --recurse-submodules https://github.com/ServeurpersoCom/qwentts.cpp ~/tools/qwentts.cpp cd ~/tools/qwentts.cpp ./buildcuda.sh # NVIDIA(Linux); AMD/Intelの場合は ./buildvulkan.sh; CPUのみ(例: macOS)の場合は ./buildcpu.shbuildcuda.cmdを実行します。vcvars64.batが別の場所にある場合は、スクリプトの先頭にあるパスを編集してください。1つのGPUのみを対象にするには、cmake行に-DCMAKE_CUDA_ARCHITECTURES=89(RTX 40xx; 86 = RTX 30xx, 120 = RTX 50xx)を追加します。 - 重みをダウンロードする(約2GB) Hugging Face の
Serveurperso/Qwen3-TTS-GGUFから:pip install -U huggingface_hub hf download Serveurperso/Qwen3-TTS-GGUF qwen-talker-1.7b-customvoice-Q8_0.gguf qwen-tokenizer-12hz-Q8_0.gguf --local-dir ~/tools/qwen-gguf - say.py にそれらを指し示す 他のフォルダを使用した場合:
QWEN_TTS_HOME(チェックアウト先)、QWEN_TTS_EXE(バイナリ)、またはQWEN_TTS_MODELS(.ggufフォルダ)を設定します。Windowsではsay.pyが自動的に%CUDA_PATH%\bin\x64をPATHに追加します(CUDA_BINで上書き可能)。 say.py --checkを再度実行し、1行テスト用の音声を生成します。
ハードウェア: 8 GB VRAM で Q8_0(使用中約3GB)には十分です。GPUがない場合、CPUビルドはおおよそ4分の1の速度で動作します。GGML_BACKEND=CPU でGPUビルドを強制的にCPUで実行できます。
生成前の確認
- GPUを他で使用しているものはありますか? ゲームやその他のGPU負荷の高いアプリケーションがあると、生成速度が約4倍遅くなり、そのアプリもカクつきます。長時間のジョブを開始する前に確認してください。ユーザーがそのようなアプリ名を挙げた場合、
TTS_BUSY_APPS=app1,app2を設定すると、say.pyが実行中に警告を表示します。 - 新しいモデルを試す価値はありますか? 以下の「より良いモデルを探し続ける」を参照してください。前回のチェックから約6週間以上経過しており、タスクが本番のナレーション(1行テストではない)の場合は、まずクイックスキャンを実行してください。
- テキストは人間らしく聞こえますか? 音声はAIらしい言い回しを毎回同じ抑揚で読み上げるため、そのパターンは文章以上に目立ちます。数行を超えるナレーションの場合は、
whiteboard-explainerスキル(同じプラグイン、references/)からnatural-narration.mdを読み、そのscripts/aispeak_scan.pyを実行してください。これは script.py またはプレーンテキストファイルを入力として受け取ります。
生成
スクリプトは標準ライブラリのみを使用するため、Python 3.10以降であれば動作します。<skill> はこのスキルのフォルダです。
python -I <skill>/scripts/say.py "First line." "Second line." -o out.wav # 1つのWAV、0.35秒のギャップ
python -I <skill>/scripts/say.py --file lines.txt -o clips/ # 000.wav, 001.wav, ...
オプション:
| フラグ | 機能 |
|---|---|
--speaker | aiden(デフォルト); ryan はもう1つのネイティブ英語音声 |
--instruct | スタイルテキスト、例: "Excited, fast-paced" や "Calm and serious" |
--seed N | 再現可能なテイクを生成 |
--gap S | 結合ファイル内の行間の無音秒数 |
--srt F | 結合WAVに合わせた字幕も書き出します(字幕を参照) |
--quant | Q8_0(デフォルト、最高品質)または Q4_K_M(より小容量、やや平坦; 事前にダウンロードが必要) |
--check | エンジン、モデル、CUDAフォルダの検出結果を報告 |
仕組み:
- すべての行は1つのプロセスで処理されるため、モデルは1回だけ読み込まれます(3~8秒)。行は1回の呼び出しでまとめて渡し、行ごとに1回の呼び出しを行わないでください。
- 出力は24 kHzモノラル16ビットWAVです。
テイクはサンプリングされるため、実行ごとに異なります:
- 気に入ったクリップは保存してください。テキストと設定をキーとして、行ごとにキャッシュします。
- 行の長さが1文字あたり約0.07秒から大きく外れている場合は、その行を再テイクしてください。これは単語が省略または捏造されたことを意味します。
動画ナレーションの場合、さらに:
- 各クリップの無音部分を約50ミリ秒のパディングにトリミングし、独自のギャップでタイムラインに配置します。
- 最終トラックをラウドネスノーマライズ:
ffmpeg -af loudnorm=I=-16:TP=-1.5:LRA=11
字幕(.srt): ナレーション動画ごとに提供する
各行の開始と終了がすでにわかっているため、文字起こしの必要はありません。それらのタイミングから字幕を構築します。
say.pyを使用する場合:--srt narration.srtを追加します(.wavの-oが必要)。字幕は結合されたトラックと正確に一致します。- 独自のパイプラインで使用する場合:
scripts/srt.pyのto_srt([(start_s, end_s, text), ...], display=[...])を、話された各行のビデオ時間の開始/終了とともに呼び出します。またはCLIを使用:python srt.py timings.tsv -o video.srt。 - 音声のスペルを修正する。 ナレーションテキストは多くの場合、音声用に書かれています: 「D I L」、音声的に書き直された名前、「runner dot HTML」、数字を言葉で書いたもの。
display/--display display.tsv(話された形式書き言葉形式)で元にマッピングします。書き言葉形式は画面上に表示されているものから取得し、数字には数字を使用します(例: "$232", "83%")。 - 結果を確認する。 残っているスペース区切りの大文字(
[A-Z] [A-Z])や「 dot 」をgrepで検索します。 - モジュールが適用するルール:
- 字幕あたり最大2行、42文字
- 文、節、単語の順で改行
- 短い文はマージして、高速で流れないようにする
- 時間は長さに比例して分配
- 動画と同じ名前を付ける(
Video Name.mp4の隣にVideo Name.srt)ことで、プレーヤーが自動的に読み込みます。VLCでは、--sub-file=でファイルを強制指定できます。
whiteboard-explainer スキルの template/narration/build_vo.py は完全な実用的パイプラインです: 行ごとのキャッシュ、再テイク、無音トリミング、ポーズ整形、ワードアライメント、キュー表、リップシンクエンベロープ。
注意点
- CUDA DLLがPATHに存在する必要があります(Windows)。 CUDA 13では
...\CUDA\v13.x\bin\x64にあります。そのフォルダがPATHにないと、qwen-tts.exeは出力なしで静かに終了します。say.pyが自動的に追加します。 --stream-by-line -o -はストリーミングWAVヘッダーを書き出す(サイズは0x7fffffff)、行ごとに1つ。RIFF....WAVEfmtで分割し、各44バイトのヘッダーを削除します。サイズフィールドは信頼しないでください。- Aiden は単一文字や特殊トークンを誤読します。 予告なしのWhisper監査で判明:
- "h star" は "a hap" や "our star"、"y t" は "VT"、"y" は "we"、"arXiv" は "ArcSireFolk" と出力されました。
- これらは問題なく動作: 大文字の "H star" / "under H"、"why tee" / "why tilde"、"archive"、"SMILES check"。
- "aitch" は不安定です。名前だけで問題なくても文中で誤読されることがあります: 行全体の中でテストしてください。
- 文頭のKは脱落することがあります("Kwenputer" → "When Pooter"): そのような行は "And" や "So" で始めてください。
- 各クリップをスクリプトを初期プロンプトとして与えずに文字起こしし、スクリプトと比較することで監査します。プロンプトを与えたWhisperは意図された単語を「聞き取り」、エラーを隠します。ツール:
whiteboard-explainer/template/narration/audit_vo.pyとtts_try.py。
- コロンでのポーズ。 Qwenはコロンで0.6~0.8秒、時にはフレーズの途中でポーズします。ナレーションでは、各無音をその前の句読点でキャップし(テンプレートの build_vo.py にある
shape())、コロン断片の行("First: …")を避けてください。 - CPUフォールバック: Kokoro 82M(
kokoro-onnx)は平坦ですがCPU上で高速で、GPUが使用中の下書きに適しています。
より良いモデルを探し続ける
ローカルTTSは急速に改善されており、現在の選択肢もやがて更新されます。これを最終回答ではなく、現在のチャンピオンとして扱ってください。特に大規模なナレーションジョブの前、または以下の最終チェックから約6週間以上経過している場合は、新しいより良いモデルを探してください。
- スキャン。 前回のチェック以降にリリースまたは更新されたオープンウェイトTTSをウェブで検索してください。以下を確認:
- TTS Arena / Artificial Analysis 音声リーダーボード
- Hugging Face トレンドの text-to-speech モデル
- r/LocalLLaMA
- 以下のエンジンのGitHubリリース
- フィルタリング。 以下の条件をすべて満たす場合のみ候補として保持:
- ローカルで無料で使用できる(オープンウェイト、寛容なライセンスまたは個人使用ライセンス)
- ユーザーのGPUメモリとOSで実行できる
- 必要な言語を話す
- 品質でチャンピオンを上回る、または品質が同等で大幅に高速である
- トライアル。 候補で
eval/lines.txtを生成します。scripts/voice_metrics.py(pip install numpy librosa; チャンピオンとベースラインの録音はeval/にあります)でチャンピオンとスコアを比較:- ピッチ標準偏差が約5半音以上、範囲が約17半音以上必要です(自然に聞こえるため)。
- 生成1秒あたりの音声秒数で速度を測定します。
- 聴いて判断。 ユーザーに候補と
eval/champion_*.wavを耳で比較してもらいます(ffplay -nodisp -autoexit file.wav)。評価指標は候補を絞り込むだけで、最終判断は耳が行います。 - 記録。 何も変更がなくても、以下の「最終チェック」の行と
references/benchmarks.mdを更新します。チャンピオンが変わった場合は、eval/champion_*.wavを置き換え、say.pyを更新し、古いモデルを削除する前に確認を取ります。
最終チェック: 2026-11-02(ウェブ調査とローカルのVoxCPM2 Q8およびPhonon 31m/Milesトライアル)。Aiden は耳で判断して両方より好まれました。まだローカルで試していないもの: Phonon 40m、OmniVoice、Breeze TTS 2、Drama 3、Orpheus、Dia、Sesame CSM、Spark-TTS、IndexTTS-2、VibeVoice、Higgs Audio、Kyutai TTS、Fish/OpenAudio。詳細は references/benchmarks.md にあります。