この記事の最後まで進めると、コードをコピペするだけで、
テキストと、それを読み上げる音声ファイルを作成してくれるプログラムができます!
作成した音声
さあ、開発の時間だ!
つくる人環境設定は完了したから、次は声のテストになるのかな?
教えてLM!
AITuber 開発用LMの回答
はい、その通りです!環境構築お疲れ様でした。 次は**「PythonからVOICEVOXを操作して、音声ファイルを生成できるか」**を確認する「声のテスト」を行いましょう。
これが成功すれば、AITuberの「口(発声機能)」が完成したことになります。
Cursorの**Composer機能(Ctrl + I)**を使って、以下の手順でコードを実装・実行していきましょう。
Cursorでコードを書いてもらおう!
まず、VOICEVOXアプリを起動しておいてください。 (これが起動していないと、Pythonが接続しようとしてもエラーになります)


Cursorのエディタで Ctrl + I(Macは Cmd + I)を押してComposerを開き、以下のプロンプトを入力して「送信」してください。
Composerへの指示(プロンプト)
modules/expression/voicevox.py に、VOICEVOXを操作するクラス VoiceVoxClient を実装してください。
【要件】
1. 非同期処理 (aiohttp) を使用すること。
2. コンストラクタで base_url (デフォルト: http://localhost:50021) と speaker_id を受け取る。
3. 以下のメソッドを実装する:
- create_audio_query(text): /audio_query エンドポイントを使用
- synthesis(query, speaker): /synthesis エンドポイントを使用
- generate_voice(text): 上記2つを組み合わせて、音声データ(bytes)を返す
4. config/settings.py が未実装なら、pydantic-settingsを使って .env を読み込むクラスも作成してください。
Cursorがコードを生成したら、「Accept(適用)」または「Save All」をクリックしてファイルを保存します。
次に、正しく動くか確認するための小さなテストファイルを作ります。 ルートディレクトリ(main.pyがある場所)に test_voice.py というファイルを新規作成し、以下のコードを貼り付けてください。
コピペするコード
import asyncio
from modules.expression.voicevox import VoiceVoxClient
# 設定ファイルから読み込む形が理想ですが、まずは直接指定でテストします
from config.settings import settings
async def main():
print("🤖 音声合成テストを開始します...")
# クライアントの初期化 (設定ファイルの値を使用)
# もしエラーが出る場合は url="http://127.0.0.1:50021", speaker_id=3 など直接指定してください
client = VoiceVoxClient(
base_url=settings.VOICEVOX_URL,
speaker_id=settings.VOICEVOX_SPEAKER_ID
)
text = "こんにちは。これはAITuberの声のテストです。"
try:
# 音声データの生成
audio_data = await client.generate_voice(text)
# ファイルとして保存
with open("test_voice.wav", "wb") as f:
f.write(audio_data)
print("✅ 成功! 'test_voice.wav' が作成されました。再生して確認してください。")
except Exception as e:
print(f"❌ エラーが発生しました: {e}")
print("ヒント: VOICEVOXアプリは起動していますか?")
if __name__ == "__main__":
asyncio.run(main())


CursorのAI
作業ログ
まずプロジェクト構成と既存コードを確認し、modules/expression/voicevox.py と config/settings.py の有無・内容を見ます。その上で VoiceVoxClient をaiohttpで実装し、未実装なら設定クラスも追加します。


実装内容
modules/expression/voicevox.py に VoiceVoxClient を要件どおり実装しました。
class VoiceVoxClient:VOICEVOXクライアント
VOICEVOX エンジンの HTTP API を非同期で呼び出します。
"""
def __init__(self, base_url: str = "http://localhost:50021", speaker_id: int = 1):
...
self.base_url = base_url.rstrip("/")
self.speaker_id = speaker_id
...
async def create_audio_query(self, text: str, speaker: Optional[int] = None) -> Optional[Dict[str, Any]]:
"""`/audio_query` エンドポイントを呼び出して音声クエリを生成します。"""
...
async def synthesis(self, query: Dict[str, Any], speaker: Optional[int] = None) -> Optional[bytes]:
"""`/synthesis` エンドポイントを呼び出して音声データを生成します。"""
...
async def generate_voice(self, text: str) -> Optional[bytes]:
"""テキストから音声データ(bytes)を生成します。"""
...
仕様との対応
- 非同期処理: 全メソッドで aiohttp.ClientSession を使用した async 実装。
- コンストラクタ: __init__(base_url: str = “http://localhost:50021”, speaker_id: int = 1) に変更。
- メソッド
- create_audio_query(text): /audio_query を POST、クエリ JSON を返却。
- synthesis(query, speaker): /synthesis を POST、音声 bytes を返却。
- generate_voice(text): 上記 2 メソッドを組み合わせて bytes を返却(失敗時は None)。
- config/settings.py について
- すでに pydantic-settings を用いて .env を読む Settings クラス (settings = Settings()) が実装済みのため、新規実装は行っていません。


Cursorの下部にあるターミナルで、以下のコマンドを実行します。
python test_voice.py


成功すると。。。
フォルダ内に test_voice.wav というファイルが生成されます。これを再生して、ずんだもん(設定したキャラ)の声が聞こえれば「声のテスト」は完了です!
実行結果





エラーが出たよ?なんでLM?
エラー原因を特定!&修正!
ターミナルの結果とSTEP3の実装内容をコピペしてLMに聞いてみます。
AITuber 開発用LMの回答
エラーが出た原因は、実行しようとした test_voice.py というファイルが、まだフォルダの中に保存されていないから です。
PowerShellの画面で can't open file ... [Errno 2] No such file or directory と表示されるのは、「そのファイルが見つからないよ」という意味です。
Cursorのエディタ上で、以下の 2つのファイル が正しい場所に作成・保存されているか確認し、なければ作成してください。
解決方法
手順1:音声合成モジュールの作成
あなたが貼り付けてくれた class VoiceVoxClient... のコードは、ここに保存します。
- ファイル名: modules/expression/voicevox.py
- modules フォルダの中の expression フォルダの中に作ります。
以下のコードをコピーして貼り付けてください(import文なども含めた完全版です)。
中身のコード
import aiohttp
import json
from typing import Optional, Dict, Any
class VoiceVoxClient:
"""
VOICEVOXエンジンと通信するクライアントクラス
"""
def __init__(self, base_url: str = "http://127.0.0.1:50021", speaker_id: int = 1):
self.base_url = base_url.rstrip("/")
self.speaker_id = speaker_id
async def create_audio_query(self, text: str, speaker: Optional[int] = None) -> Optional[Dict[str, Any]]:
"""音声合成用のクエリを作成します (/audio_query)"""
speaker_id = speaker if speaker is not None else self.speaker_id
params = {"text": text, "speaker": speaker_id}
async with aiohttp.ClientSession() as session:
try:
async with session.post(f"{self.base_url}/audio_query", params=params) as response:
response.raise_for_status()
return await response.json()
except Exception as e:
print(f"Error creating audio query: {e}")
return None
async def synthesis(self, query: Dict[str, Any], speaker: Optional[int] = None) -> Optional[bytes]:
"""音声を合成してバイナリデータを返します (/synthesis)"""
speaker_id = speaker if speaker is not None else self.speaker_id
params = {"speaker": speaker_id}
async with aiohttp.ClientSession() as session:
try:
headers = {"Content-Type": "application/json"}
async with session.post(
f"{self.base_url}/synthesis",
params=params,
json=query,
headers=headers
) as response:
response.raise_for_status()
return await response.read()
except Exception as e:
print(f"Error synthesizing audio: {e}")
return None
async def generate_voice(self, text: str) -> Optional[bytes]:
"""テキストから音声を生成する一連の流れを実行します"""
query = await self.create_audio_query(text)
if query is None:
return None
return await self.synthesis(query)





既にファイルがあるんだけど
これに追記する形でいいの?
結論から言うと、追記も上書きも不要です。そのままで完璧です!
あなたが持っている modules/expression/voicevox.py のコードは、必要な機能(音声合成、クエリ作成)が全て実装されており、さらにプロジェクト固有の core.logger(ログ出力機能)も組み込まれている完成度の高い状態です。
ここにコードを追記すると、クラスの定義が重複してエラーになったり、逆にバグの原因になったりします。そのファイルの内容は変更せず、そのまま保存してください。



OK!こちらは何もせずに次!
手順2:テスト用実行ファイルの作成
先ほどエラーになった「実行しようとしていたファイル」を、プロジェクトの一番上の階層(ルート)に作成します。
- ファイル名:
test_voice.pymain.pyや.envと同じ場所に作ってください。




中身のコード
import asyncio
import os
from modules.expression.voicevox import VoiceVoxClient
from dotenv import load_dotenv
# .envファイルを読み込む
load_dotenv()
async def main():
print("🤖 音声合成テストを開始します...")
# 環境変数から設定を読み込む(なければデフォルト値)
voicevox_url = os.getenv("VOICEVOX_URL", "http://127.0.0.1:50021")
speaker_id = int(os.getenv("VOICEVOX_SPEAKER_ID", "1"))
# クライアントの初期化
client = VoiceVoxClient(base_url=voicevox_url, speaker_id=speaker_id)
text = "こんにちは。聞こえていますか?これはテストです。"
print(f"生成するテキスト: 「{text}」")
# 音声生成
audio_data = await client.generate_voice(text)
if audio_data:
# ファイルに保存
filename = "test_output.wav"
with open(filename, "wb") as f:
f.write(audio_data)
print(f"✅ 成功! '{filename}' が作成されました。")
else:
print("❌ 失敗しました。VOICEVOXが起動しているか確認してください。")
if __name__ == "__main__":
asyncio.run(main())


手順3:もう一度実行する
2つのファイルを保存(Ctrl + S)したら、もう一度ターミナルで以下のコマンドを実行してください。python test_voice.py
これで「✅ 成功!」と表示されればOKです!



いざ、実行!
手順3までやったらこれがでた





これって、うまくいったの????
教えてLM!
コードをコピペして「上手くいったの?」と聞きました。
AITuber 開発用LMの回答
惜しい!あと少しです。
エラーが出てしまったので、まだ成功していません。
原因は、プログラムの中で使っている「部品(ライブラリ)」である aiohttp が、あなたのパソコンにまだ入っていないからです。
以下の手順で、必要な部品をまとめてインストールしてしまいましょう。
- 1. 必要な部品をインストールする
-
PowerShell(黒い画面)で、以下のコマンドをコピーして貼り付け、Enterキーを押してください。これで今回必要なものが全て入ります。
pip install aiohttp python-dotenvPowerShell(黒い画面)で、以下のコマンドをコピーして貼り付け、Enterキーを押してください。これで今回必要なものが全て入ります。


実行していっぱいコード出ますが、最後にこれがでたらOK - 2. もう一度テストを実行する
-
インストールが終わって文字の動きが止まったら、さきほどと同じコマンドでもう一度テストを実行してください。
python test_voice.py

いってみよー!
実行結果はまたエラー


コードをのみを貼り付けてLMに聞いてみます。
AITuber 開発用LMの回答
まだ成功していません!
エラーメッセージ ModuleNotFoundError: No module named 'loguru' は、「loguru(ログル)」というライブラリが入っていない という意味です。
このプロジェクトでは、ログ(実行履歴)をきれいに表示するために loguru という外部ライブラリを使っているようです。
以下の手順でインストールして、もう一度実行してください。
- 1. 不足しているライブラリをインストール
-
PowerShell(黒い画面)で以下のコマンドを実行してください。
pip install loguruPowerShell(黒い画面)で、以下のコマンドをコピーして貼り付け、Enterキーを押してください。これで今回必要なものが全て入ります。


最後の部分の表示は先ほど一緒! - 2. もう一度テストを実行
-
インストールが終わったら、さきほどと同じコマンドを実行します。
python test_voice.py

こっちも同じだね。いってみよー!
この感動。やヴぁい





これ上手くいったよね!!!
どうするの!? このあとどうすればいいの!?
AITuber 開発用LMの回答
おめでとうございます!大成功です! 🤖🎉
ログを見ると、VOICEVOX(ずんだもん)への接続、音声データの生成、そしてファイル保存まで完璧に動作しています。
test_output.wav を再生して、実際に「こんにちは」という声が聞こえるか確認してみてください。これでAITuberの「声(Voice)」の部分は完成です。



心なしかLMさんも浮かれている様だ
ありがとう。LMさん!
再生だな。ファイルを選んで再生だな!


テスト音声が出来ました!。次は何をするのかな!?楽しみです。