生成する音声の再生時間を指定できるZeroShot TTS「VoiceStar」を試す
ここで見かけた
プロジェクトで特定の時間枠内に音声を出力する必要がある場合、VoiceStar の持続時間制御可能な合成機能が役立ちます。開発者は目標の長さを設定できるため、音声出力を時間制限のあるユースケース(固定長のプロンプトやナレーションなど)に合わせることができ、追加の音声編集が不要になります。
このプロジェクトには、推論用の CLI および Gradio インターフェース、およびすぐに使用できる事前トレーニング済みモデルが含まれています。音声インターフェースがアプリでますます重要になる中、このレベルの制御が可能なオープンソースモデルは、重要な一歩前進です。
なぜ重要なのか?
これは、音声の再生時間を正確に指定できるオープンなTTSモデルです。これは、吹き替え、広告、アクセシビリティオーバーレイなど、ミリ秒単位の精度が求められるシーンで役立ちます。これは、オープンソースコミュニティから提供されるAI支援の放送品質のタイミング制御です。
論文(alphaXivのまとめ)
実際に生成された音声のデモページ
VoiceStar は、出力の持続時間を正確に制御し、推論中に最大トレーニング時間よりも長い音声を生成できる、自己回帰型音声クローン(ゼロショット)テキスト読み上げモデルです。
VoiceStar は、未知の声をクローンしたり、録音を編集したりするために、その声の数秒間の音声しか必要としません。30 秒間の音声でトレーニングされた VoiceStar は、40 秒間の音声を生成することができます。
YouTubeにもあった
GitHubレポジトリ
ライセンス
コードライセンス:MIT
モデルウェイトライセンス:CC-BY-4.0(使用したEmiliaデータセットがこのライセンスであるため)
READMEに従って、Ubuntu-22.04サーバ(RTX4090)で試す。
レポジトリクローン
git clone https://github.com/jasonppy/VoiceStar && cd VoiceStar
先にPython仮想環境を作る。uvで全部やろうとしたけどパッケージインストールで詰まったので、すごい中途半端なやり方で・・・
uv venv -p 3.10
uv pip install pip
source .venv/bin/activate
g2pはespeak-ngが必要。
sudo apt-get install espeak-ng
パッケージインストール
pip install torch==2.5.1 torchaudio==2.5.1 --index-url https://download.pytorch.org/whl/cu124
pip install numpy tqdm fire
pip install phonemizer==3.2.1
pip install torchmetrics
pip install einops
pip install omegaconf==2.3.0
pip install openai-whisper
pip install gradio
モデルをダウンロード。
wget -O ./pretrained/encodec_6f79c6a8.th https://huggingface.co/pyp1/Encodec_VoiceStar/resolve/main/encodec_4cb2048_giga.th?download=true
wget -O ./pretrained/VoiceStar_840M_30s.pth https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_30s.pth?download=true
wget -O ./pretrained/VoiceStar_840M_40s.pth https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_40s.pth?download=true
では推論。まずCLIから。デモ用のリファレンス音声を使用させてもらう。
python inference_commandline.py \
--reference_speech "./demo/5895_34622_000026_000002.wav" \
--target_text "I cannot believe that the same model can also do text to speech synthesis too! And you know what? this audio is 8 seconds long." \
--target_duration 8
初回はWhisperのモデルがダウンロードされるので少し時間がかかる。
(snip)
[Info] No reference_text provided, transcribing reference_speech with Whisper.
100%|█████████████████████████████████████| 1.51G/1.51G [03:00<00:00, 8.96MiB/s]
(snip)
出力された。
(snip)
[Info] Running TTS inference...
WARNING:phonemizer:words count mismatch on 300.0% of the lines (3/1)
WARNING:phonemizer:words count mismatch on 400.0% of the lines (4/1)
[Success] Generated audio saved to ./generated_tts/generated.wav
生成されたもの
たしかに8秒。
ffprobe ./generated_tts/generated.wav
Input #0, wav, from './generated_tts/generated.wav':
Metadata:
encoder : Lavf58.76.100
Duration: 00:00:08.00, bitrate: 256 kb/s
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, 1 channels, s16, 256 kb/s
5秒にしてみるとどうなるか?
python inference_commandline.py \
--reference_speech "./demo/5895_34622_000026_000002.wav" \
--target_text "I cannot believe that the same model can also do text to speech synthesis too! And you know what? this audio is 8 seconds long." \
--target_duration 5
5秒で生成されているが・・・
ffprobe ./generated_tts/generated.wav
Input #0, wav, from './generated_tts/generated.wav':
Metadata:
encoder : Lavf58.76.100
Duration: 00:00:05.00, bitrate: 256 kb/s
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, 1 channels, s16, 256 kb/s
生成されたものを聞くと途中で切れてしまっている。
ちなみにリファレンス音声は8秒程度だった。
ffprobe demo/5895_34622_000026_000002.wav
Input #0, wav, from 'demo/5895_34622_000026_000002.wav':
Duration: 00:00:07.87, bitrate: 512 kb/s
Stream #0:0: Audio: pcm_f32le ([3][0][0][0] / 0x0003), 16000 Hz, 1 channels, flt, 512 kb/s
逆に伸ばしてみた。
python inference_commandline.py \
--reference_speech "./demo/5895_34622_000026_000002.wav" \
--target_text "I cannot believe that the same model can also do text to speech synthesis too! And you know what? this audio is 8 seconds long." \
--target_duration 12
12秒で生成されている。
ffprobe ./generated_tts/generated.wav
Input #0, wav, from './generated_tts/generated.wav':
Metadata:
encoder : Lavf58.76.100
Duration: 00:00:12.00, bitrate: 256 kb/s
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz, 1 channels, s16, 256 kb/s
こちらはややゆっくりの発話になった。ただ、最後に無音が1秒ぐらいはあるかな。
発話させるテキストの量によるところはありそうだし、リファレンス音声の長さとかも関係あるのかな?大幅に縮めたり伸ばしたりってのには限界はありそうかな?という印象。
inference_gradio.py
でGradioのWebUIも用意されている。ただ、一部だけ修正したほうがいい。248行目辺り。
(snip)
model_root_box = gr.Textbox(
label="Model Root Directory",
value="/data1/scratch/pyp/BoostedVoiceEditor/runs"
)
(snip)
モデルディレクトリのパスなのだけど、ここまでの流れだと./pretrained
にしておくと良い。
(snip)
model_root_box = gr.Textbox(
label="Model Root Directory",
value="./pretrained"
)
(snip)
WebUIを起動
python inference_gradio.py
ブラウザで7860番ポートにアクセスるとこんな感じ。
リファレンス音声をアップロードして文字起こし、発話させたいテキストと発話時間を入力して生成、という感じで。
一応、日本語のリファレンス音声でも試してみたけど、ところどころ発話してるけど・・・って感じでイマイチな印象。英語のリファレンス音声だと問題ない。
VRAMは起動中でこれぐらいなのだけども、
Fri Jun 13 14:42:24 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 560.35.05 Driver Version: 560.35.05 CUDA Version: 12.6 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 4090 Off | 00000000:01:00.0 Off | Off |
| 0% 50C P8 16W / 450W | 8201MiB / 24564MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
推論中に跳ね上がることがあって、24GBでもたまにCUDA out of memoryになることがあった。
Fri Jun 13 14:44:21 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 560.35.05 Driver Version: 560.35.05 CUDA Version: 12.6 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 4090 Off | 00000000:01:00.0 Off | Off |
| 31% 55C P0 160W / 450W | 21485MiB / 24564MiB | 86% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
まとめ
発話した音声のピッチを変えずに音の長さを変更するには、librosaとかpyrubberbandとかsoxを使えばできなくはない。自分も過去に試してみたことはあるけど、機械的に縮めてるわけだから口調に影響する部分はあるんじゃないかなと思うし、結構品質的に微妙だった記憶がある。(自分が試したときはsoxが一番良かった)
まあそのあたりを生成時点である程度制御できるというのはメリットといえばメリットなのかな?制御できる限界はあると思うけども。