MENU

AITuber開発日誌 6 声・頭脳・身体をひとつなぎに!

↓最後まで進めるとこれができます!

前回までの開発で「脳・声・体」それぞれを連携させて動かすことができました!次はそれぞれのパーツを繋がる作業になるのかな。 LMに報告してみます!

つくる人

できた!!!!!さあ、次は何かな~!!

前回、AIとの連携の興奮冷めやらず。!!多用して聞いてしまいました。

AITuber 開用LMの回答

素晴らしいです!!

自分でコードの誤りに気づき、修正できるのは立派なエンジニアの証拠です!🎉 「脳・声・体」のすべてのパーツがこれで揃いました。

さあ、いよいよ最終合体(インテグレーション)「あなたの言葉を聞き、考え、喋りながら動く」 完全なAITuberシステム(main.py)を構築します。

以下のステップで完成します。

1. 声のモジュール化

前回「声」のテストはしましたが、使いやすくするための「クラス化(部品化)」がまだでした。 Cursorの Composer (Ctrl + I) を開き、以下の指示でファイルを作成してくだい。
Composerへの指示(以下のプロンプトをコピペ):

modules/expression/voicevox.py に、VOICEVOXを操作する VoicevoxClient クラスを作成してください。
【要件】
1. requests ライブラリを使用する(非同期ではなく同期でOK)。
2. config/settings.py から VOICEVOX_URL と VOICEVOX_SPEAKER_ID を読み込む。
3. speak(text) メソッドを実装する:
   - 音声合成を行い、wavデータを取得する。
   - simpleaudio ライブラリを使ってその場で再生する。
   - 再生が完了するまで待機する (play_obj.wait_done())。
2. 本体(main.py)の実装

いよいよ全ての指揮を執る「本体」を作ります。 ルートディレクトリに main.py を作成し、以下のコードを貼り付けてください。
このコードは、「入力を受け取る → AIが考える → 声を出す&口を動かす」 という無限ループを行います。

コピペするコード

import asyncio
import random
from config.settings import settings
from modules.cognition.llm_client import LLMClient
from modules.expression.vtube_studio import VTubeStudioClient
from modules.expression.voicevox import VoicevoxClient

# キャラクター設定
SYSTEM_PROMPT = """
あなたは「AITuber」のアイです。
元気で明るい、少しおっちょこちょいな性格です。
短くテンポよく返事をしてください。
"""

async def main():
    print("🚀 AITuberシステムを起動します...")

    # 1. 各モジュールの初期化
    brain = LLMClient(system_prompt=SYSTEM_PROMPT)
    voice = VoicevoxClient()
    body = VTubeStudioClient()

    # 2. VTube Studioに接続
    if not await body.connect():
        print("❌ VTube Studioへの接続に失敗しました。")
        return

    # 会話履歴
    history = []

    print("✅ 準備完了!何か話しかけてね('exit'で終了)")

    try:
        while True:
            # --- ユーザー入力 ---
            user_input = input("\nあなた: ")
            if user_input.lower() in ["exit", "quit", "終了"]:
                break

            # --- 思考 (Brain) ---
            print("🤖 (思考中...)")
            response_text = await brain.generate_response(user_input, history)
            print(f"アイ: {response_text}")

            # 履歴更新
            history.append({"role": "user", "content": user_input})
            history.append({"role": "assistant", "content": response_text})

            # --- 並列処理: 声を出しながら口を動かす ---
            # ※本来は音声波形に合わせて口を動かしますが、
            #   簡易的に「喋っている間、ランダムに口をパクパクさせる」タスクを走らせます
            
            # 口パクのタスクを作成
            async def lip_sync_simulation():
                while True:
                    await body.set_parameter("MouthOpen", random.uniform(0.0, 1.0))
                    await asyncio.sleep(0.1)
            
            # 音声再生と口パクを同時に開始
            lip_task = asyncio.create_task(lip_sync_simulation())
            
            # 声を再生(再生が終わるまでここで待機します)
            # ※VoicevoxClientは同期処理で作ったため、簡易的に executor で実行
            await asyncio.to_thread(voice.speak, response_text)
            
            # 喋り終わったら口パク停止
            lip_task.cancel()
            await body.set_parameter("MouthOpen", 0.0) # 口を閉じる

    except KeyboardInterrupt:
        print("\nシステムを終了します")
    finally:
        await body.close()

if __name__ == "__main__":
    asyncio.run(main())
3. 最終起動!

main.py は、あなたのPC内で待機している「VOICEVOX」と「VTube Studio」という別のアプリに、Pythonから命令(通信)を送ることで動作します。

そのため、これらが起動していないと、Pythonは「命令を送る相手がいない(接続エラー)」と判断して止まってしまいます。

実行前に、以下の「起動チェックリスト」を確認してください。

チェックリスト
  • VOICEVOX
  • VTube Studio
    • アプリが起動していること。
    • 動かしたいキャラクターが表示されていること。
    • 【重要】設定で「APIサーバーの起動(Start API)」がONになっていること
      (ポート番号 8001※これがOFFだと、Pythonからの接続を拒否してしまいます。
  • インターネット接続
    • ネットにつながっていること。
VOICEVOX(補足)

◆ キャラクター(ずんだもんなど、IDに対応するキャラ)が選択されている必要はありませんが、エンジン(アプリ自体)が動いている必要があります。

◆ VOICEVOXは起動するだけで、裏側で「命令受付窓口(サーバー)」を開いてくれます。

VTube Studio(補足)

「APIサーバーの起動(Start API)」がON

◆ これがOFFだと、Pythonからの接続を拒否してしまいます。

インターネット接続(補足)

◆ OpenAI(脳)と通信するために必要です。

以下のコマンドで実行してください。

python main.py

これが動けば…

1. あなたがターミナルで話しかける。

2. アイちゃん(AI)が返事を考える。

3. VTube Studioのキャラクターが、喋りながら(声が出て)口をパクパク動かす!

まさにAITuberの誕生です。 動きましたか?感動の瞬間を教えてください!

つくる人

最終起動!って”!”ついてるよww
空気読んでくれてるねー!さあ!開発だ!

目次

声のモジュール化

前回「声」のテストはしましたが、使いやすくするための「クラス化(部品化)」がまだでした。 Cursorの Composer (Ctrl + I) を開き、以下の指示でファイルを作成してくだい。
Composerへの指示(以下のプロンプトをコピペ):

modules/expression/voicevox.py に、VOICEVOXを操作する VoicevoxClient クラスを作成してください。
【要件】
1. requests ライブラリを使用する(非同期ではなく同期でOK)。
2. config/settings.py から VOICEVOX_URL と VOICEVOX_SPEAKER_ID を読み込む。
3. speak(text) メソッドを実装する:
   - 音声合成を行い、wavデータを取得する。
   - simpleaudio ライブラリを使ってその場で再生する。
   - 再生が完了するまで待機する (play_obj.wait_done())。
コンポーザーにコピペ!
つくる人

実装完了! ありがとうCursor
さて、どうかな

なんかエラーのようなものが表示されていますが、テストするまでそのままにしておきます。

つくる人

エラーは保留!次へ!

本体(main.py)の実装

いよいよ全ての指揮を執る「本体」を作ります。 ルートディレクトリに main.py を作成し、以下のコードを貼り付けてください。
このコードは、「入力を受け取る → AIが考える → 声を出す&口を動かす」 という無限ループを行います。

コピペするコード
import asyncio
import random
from config.settings import settings
from modules.cognition.llm_client import LLMClient
from modules.expression.vtube_studio import VTubeStudioClient
from modules.expression.voicevox import VoicevoxClient

# キャラクター設定
SYSTEM_PROMPT = """
あなたは「AITuber」のアイです。
元気で明るい、少しおっちょこちょいな性格です。
短くテンポよく返事をしてください。
"""

async def main():
    print("🚀 AITuberシステムを起動します...")

    # 1. 各モジュールの初期化
    brain = LLMClient(system_prompt=SYSTEM_PROMPT)
    voice = VoicevoxClient()
    body = VTubeStudioClient()

    # 2. VTube Studioに接続
    if not await body.connect():
        print("❌ VTube Studioへの接続に失敗しました。")
        return

    # 会話履歴
    history = []

    print("✅ 準備完了!何か話しかけてね('exit'で終了)")

    try:
        while True:
            # --- ユーザー入力 ---
            user_input = input("\nあなた: ")
            if user_input.lower() in ["exit", "quit", "終了"]:
                break

            # --- 思考 (Brain) ---
            print("🤖 (思考中...)")
            response_text = await brain.generate_response(user_input, history)
            print(f"アイ: {response_text}")

            # 履歴更新
            history.append({"role": "user", "content": user_input})
            history.append({"role": "assistant", "content": response_text})

            # --- 並列処理: 声を出しながら口を動かす ---
            # ※本来は音声波形に合わせて口を動かしますが、
            #   簡易的に「喋っている間、ランダムに口をパクパクさせる」タスクを走らせます
            
            # 口パクのタスクを作成
            async def lip_sync_simulation():
                while True:
                    await body.set_parameter("MouthOpen", random.uniform(0.0, 1.0))
                    await asyncio.sleep(0.1)
            
            # 音声再生と口パクを同時に開始
            lip_task = asyncio.create_task(lip_sync_simulation())
            
            # 声を再生(再生が終わるまでここで待機します)
            # ※VoicevoxClientは同期処理で作ったため、簡易的に executor で実行
            await asyncio.to_thread(voice.speak, response_text)
            
            # 喋り終わったら口パク停止
            lip_task.cancel()
            await body.set_parameter("MouthOpen", 0.0) # 口を閉じる

    except KeyboardInterrupt:
        print("\nシステムを終了します")
    finally:
        await body.close()

if __name__ == "__main__":
    asyncio.run(main())
つくる人

ん? main.pyファイルはすでにあるぞ?

つくる人

すでにコードが書いてあるけどどうする?
教えてLM!

AITuber 開用LMの回答

はい、全置換して大丈夫です!

現在書かれているそのコードは、プロジェクトの「骨組み(スカッフォールディング)」を作成した際に自動生成された高度な構成用のテンプレートだと思われます。

そのコードでは、処理の中身を core/orchestration.py という別のファイルに任せていますが、私たちはまだその中身(オーケストレーションのロジック)を実装していません。そのため、今のまま実行しても何も起きないか、エラーになる可能性が高いです。

今回は、動きを分かりやすく確認するために、ロジックをすべて main.py に記述したコード(先ほど提示したもの)で上書きしてください。

手順

  1. main.py を開く
  2. 中身を全て削除し、以下のコードに全置換する
    (※先ほどのコードと同じですが、念のため再掲します
コード
import asyncio
import random
# 設定ファイルの読み込み
from config.settings import settings
# 作成した各モジュールをインポート
from modules.cognition.llm_client import LLMClient
from modules.expression.vtube_studio import VTubeStudioClient
from modules.expression.voicevox import VoicevoxClient

# キャラクター設定
SYSTEM_PROMPT = """
あなたは「AITuber」のアイです。
元気で明るい、少しおっちょこちょいな性格です。
短くテンポよく返事をしてください。
"""

async def main():
    print("🚀 AITuberシステムを起動します...")

    # 1. 各モジュールの初期化
    # 脳(AI)、声(VOICEVOX)、体(VTube Studio)のインスタンスを作成
    brain = LLMClient(system_prompt=SYSTEM_PROMPT)
    voice = VoicevoxClient()
    body = VTubeStudioClient()

    # 2. VTube Studioに接続
    if not await body.connect():
        print("❌ VTube Studioへの接続に失敗しました。")
        return

    # 会話履歴
    history = []

    print("✅ 準備完了!何か話しかけてね('exit'で終了)")

    try:
        while True:
            # --- ユーザー入力 ---
            user_input = input("\nあなた: ")
            if user_input.lower() in ["exit", "quit", "終了"]:
                break

            # --- 思考 (Brain) ---
            print("🤖 (思考中...)")
            # AIに返答を生成させる
            response_text = await brain.generate_response(user_input, history)
            print(f"アイ: {response_text}")

            # 履歴更新
            history.append({"role": "user", "content": user_input})
            history.append({"role": "assistant", "content": response_text})

            # --- 並列処理: 声を出しながら口を動かす ---
            
            # 口パクのタスクを作成(0.1秒ごとにランダムに開閉)
            async def lip_sync_simulation():
                while True:
                    await body.set_parameter("MouthOpen", random.uniform(0.0, 1.0))
                    await asyncio.sleep(0.1)
            
            # 音声再生と口パクを同時に開始する準備
            lip_task = asyncio.create_task(lip_sync_simulation())
            
            # 声を再生(再生が終わるまでここで待機)
            # voice.speakは同期処理なので、asyncio.to_threadで実行してメインループを止めないようにする
            await asyncio.to_thread(voice.speak, response_text)
            
            # 喋り終わったら口パク停止
            lip_task.cancel()
            await body.set_parameter("MouthOpen", 0.0) # 口を閉じる

    except KeyboardInterrupt:
        print("\nシステムを終了します")
    finally:
        # 終了時に接続を切る
        await body.close()

if __name__ == "__main__":
    asyncio.run(main())

書き換え後の確認ポイント

書き換えたコードでは、以下の3つの自作モジュールをインポートしています。これらのファイル名やクラス名が合っているか(これまでの手順通りなら合っています)を確認してください。

  • modules.cognition.llm_client -> LLMClient
  • modules.expression.vtube_studio -> VTubeStudioClient
  • modules.expression.voicevox -> VoicevoxClient
書き換え完了!
つくる人

よし!次はいよいよ実行だな。
エラーっぽい部分は気になるが。
動かさんことにはわからん! 

最終起動!

main.py は、あなたのPC内で待機している「VOICEVOX」と「VTube Studio」という別のアプリに、Pythonから命令(通信)を送ることで動作します。

そのため、これらが起動していないと、Pythonは「命令を送る相手がいない(接続エラー)」と判断して止まってしまいます。

実行前に、以下の「起動チェックリスト」を確認してください。

チェックリスト
  • VOICEVOX
    • アプリが起動していること。
  • VTube Studio
    • アプリが起動していること。
    • 動かしたいキャラクターが表示されていること。
    • 【重要】設定で「APIサーバーの起動(Start API)」がONになっていること
      (ポート番号 8001※これがOFFだと、Pythonからの接続を拒否してしまいます。
  • インターネット接続
    • ネットにつながっていること。
VOICEVOX(補足)

◆ キャラクター(ずんだもんなど、IDに対応するキャラ)が選択されている必要はありませんが、エンジン(アプリ自体)が動いている必要があります。

◆ VOICEVOXは起動するだけで、裏側で「命令受付窓口(サーバー)」を開いてくれます。

VTube Studio(補足)

「APIサーバーの起動(Start API)」がON

◆ これがOFFだと、Pythonからの接続を拒否してしまいます。

インターネット接続(補足)

◆ OpenAI(脳)と通信するために必要です。

以下のコマンドで実行してください。

python main.py

これが動けば…

1. あなたがターミナルで話しかける。

2. アイちゃん(AI)が返事を考える。

3. VTube Studioのキャラクターが、喋りながら(声が出て)口をパクパク動かす!

まさにAITuberの誕生です。 動きましたか?感動の瞬間を教えてください!

つくる人

やるぞ!

最終チェック

つくる人

チェックリスト
オールグリーン! 起動します!

結果はやはり。。。

つくる人

やっぱりエラーか!!まあ想定内!
解決してこう! よろしくLM

エラーの内容をコピペしてLMに相談します

解消するにはどうすればいい?

Traceback (most recent call last):
  File "D:\02-my-app\00_AIvtube\my-aituber\main.py", line 8, in <module>
    from modules.expression.voicevox import VoicevoxClient
  File "D:\02-my-app\00_AIvtube\my-aituber\modules\expression\voicevox.py", line 11, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'

AITuber 開用LMの回答

requests というライブラリが仮想環境(.venv)の中にインストールされていないことが原因です。

このライブラリは、PythonからVOICEVOX(音声合成エンジン)に「喋って!」という命令(HTTPリクエスト)を送るために必要です。また、先ほどの実装指示には simpleaudio(音声再生用)も含まれていたため、これらも合わせてインストールする必要があります。

コマンドをターミナルで実行して、不足しているライブラリを一括でインストールしてください。
ターミナル((.venv)が表示されている状態)で、以下のコマンドを入力・実行します。

pip install requests simpleaudio

インストールが完了したら、もう一度実行してみてください:

python main.py

これで ModuleNotFoundError が消え、システムが起動するはずです!

つくる人

いざ、インストール!

つくる人

そして完了! さあ、起動だ!

声・身体・頭脳がひとつなぎになった!

大成功です! ユーザーが入力すると、 AIが返事を返してくれて 連動して声や身体が動いてくれます。

つくる人

一回コメントすると、またmain.pyを起動しないといけないから
会話を続けることができない。次はこれやるのかな?

さぁ、次はどんな作業になるでしょうか。楽しみ!

よかったらシェアしてね!
  • URLをコピーしました!
目次