はじめに
ESPnetの記事は以前にも書きました。
今回はESPnet==202511を使ってみました。
使用するモデルは前回と同じなので作成される音声の質は変わっていません。
動作することを確認しただけになります。
PC環境
Windows 11 Python 3.12
python 3.13以降では今のところ環境構築に成功していません。
Python環境構築
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 --index-url https://download.pytorch.org/whl/cu128 pip install git+https://github.com/espnet/espnet.git@v.202511 pip install espnet_model_zoo pip install pyopenjtalk pip install .\flash_attn-2.7.4.post1%2Bcu128torch2.7.0cxx11abiFALSE-cp312-cp312-win_amd64.whl
flash-attentionはこちらからダウンロードしました。
Pythonスクリプト
使用したモデルは前回同様espnet/kan-bayashi_jsut_full_band_vits_prosodyです。
非常に古いものになりますが、今のところこれを上回るモデルに出会っていません。
import argparse import numpy as np import torch from espnet2.bin.tts_inference import Text2Speech parser = argparse.ArgumentParser() parser.add_argument('input_filename', help='input text file name') parser.add_argument('output_filename', help='output wave file name') args = parser.parse_args() input_fname = args.input_filename output_fname = args.output_filename text2speech = Text2Speech.from_pretrained( "espnet/kan-bayashi_jsut_full_band_vits_prosody", device="cuda" ) pause = np.zeros(30000, dtype=np.float32) with open(input_fname, 'r', encoding="utf-8") as f: x = f.read() sentence_list = x.split('<pause>') wav_list = [] # 最初に60000サンプルの無音を追加 initial_pause = np.zeros(60000, dtype=np.float32) wav_list.append(initial_pause) for sentence in sentence_list: sentence = sentence.strip() if sentence: # 空でない場合は音声合成 with torch.no_grad(): result = text2speech(sentence)["wav"] wav_list.append(np.concatenate([result.view(-1).cpu().numpy(), pause])) else: # 空の場合はpauseのみ追加 wav_list.append(pause) final_wav = np.concatenate(wav_list) # Convert float32 to int16 PCM format max_value = np.max(np.abs(final_wav)) final_wav = (final_wav / max_value * 32767).astype(np.int16) # Save as WAV using wave module import wave with wave.open(output_fname, 'wb') as wav_file: wav_file.setnchannels(1) # Mono audio wav_file.setsampwidth(2) # 2 bytes per sample (16-bit) wav_file.setframerate(text2speech.fs) # Sample rate wav_file.writeframes(final_wav.tobytes())
用意するテキストファイル
このようなテキストファイルを用意しました。
首都はキャンベラ。<pause> 世界一のサンゴ礁、グレートバリアリーフが有名。
テキスト中にpauseを挿入するとそこで間をあける(無音をはさむ)ようになっています。
使い方
上記Pythonスクリプトを「main.py」としています。
python tts.py <テキストファイル名> <出力するファイル名>
補足
以下のようなエラーが出る時がありました。
FileNotFoundError: [Errno 2] No such file or directory: 'E:\\tts-cu128\\env\\Lib\\site-packages\\espnet_model_zoo\\models--espnet--kan-bayashi_jsut_full_band_vits_prosody\\snapshots\\6f358a9e1726e099f71a7ac09513682b9ccce48e\\exp\\tts_train_full_band_vits_raw_phn_jaconv_pyopenjtalk_prosody\\images\\discriminator_backward_time.png'
パスが長すぎるようです。(制限 260文字?)
以下でパスの制限を解除できるようです。
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\FileSystem" ` -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
uvで環境構築
簡単に環境構築できるようにpyproject.tomlを載せておきます。
(はまりポイント)projectの名前をespnet以外にしないとうまくいきません。
Torch 2.7.0+cu128
[project] name = "espnet-uv" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12,<3.13" dependencies = [ "espnet @ https://github.com/espnet/espnet/archive/refs/tags/v.202511.zip", "espnet-model-zoo==0.1.7", "flash-attn", "pyopenjtalk==0.4.1", "torch==2.7.0+cu128", "torchaudio==2.7.0+cu128", "torchvision==0.22.0+cu128", ] [[tool.uv.index]] name = "torch-cuda" url = "https://download.pytorch.org/whl/cu128" explicit = true [tool.uv.sources] torch = [{ index = "torch-cuda" }] torchvision = [{ index = "torch-cuda" }] torchaudio = [{ index = "torch-cuda" }] flash-attn = { path = "flash_attn-2.7.4.post1+cu128torch2.7.0cxx11abiFALSE-cp312-cp312-win_amd64.whl" }
"espnet @ git+https://github.com/espnet/espnet.git@v.202511"
こう書くより次のように書く方が少し早くなる気がします。
"espnet @ https://github.com/espnet/espnet/archive/refs/tags/v.202511.zip"
Torch 2.9.1+cu126
flash-attnはこちらの方法でビルドしました。
[project] name = "espnet-uv" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12,<3.13" dependencies = [ "espnet @ https://github.com/espnet/espnet/archive/refs/tags/v.202511.zip", "espnet-model-zoo==0.1.7", "flash-attn", "pyopenjtalk==0.4.1", "torch==2.9.1+cu126", "torchaudio==2.9.1+cu126", "torchvision==0.24.1+cu126", ] [[tool.uv.index]] name = "torch-cuda" url = "https://download.pytorch.org/whl/cu126" explicit = true [tool.uv.sources] torch = [{ index = "torch-cuda" }] torchvision = [{ index = "torch-cuda" }] torchaudio = [{ index = "torch-cuda" }] flash-attn = { path = "flash_attn-2.8.3+cu126torch2.9.1cxx11abiTRUE-cp312-cp312-win_amd64.whl" }