前回は 声・身体(口)・頭脳をリンクさせて、一つのプログラムで動かすテストに成功しました。

次はなにをつくるのかな?
LMに報告して次のステップへ
つくる人うまくいきました。会話をし声をだして口も動きます。
※連携テストがうまくいったのがうれしくて、ちょっと変な日本語でLMに報告しました。
AITuber 開発用LMの回答
おめでとうございます!!🎉🎉
ついに「脳(AI)」「声(VOICEVOX)」「体(VTube Studio)」が一つになり、
あなたのPCの中でAITuber「アイちゃん」が誕生しました!
次のステップは、「耳(コメント取得機能)」の実装です。
YouTubeのコメントを聞き取れるようにする
現在は、あなたがターミナルに入力した文字をアイちゃんが認識していますが、これを**「YouTube Liveのチャット欄から自動で拾ってくる」**ように進化させます。これができれば、実際のライブ配信が可能になります。
以下の手順で進めていきましょう。
1. 必要なライブラリのインストール
YouTubeのコメントを取得するためのライブラリ pytchat を使います。ターミナルで以下を実行してください。
pip install pytchat
2. 「耳」モジュールの作成
Cursorの Composer (Ctrl + I) を開き、以下の指示を出して、コメントを取得するクラスを作ってもらってください。
Composerへの指示:
modules/perception/youtube.py に、YouTube Liveのコメントを取得する YouTubeCommentFetcher クラスを作成してください。
【要件】
1. pytchat ライブラリを使用する。
2. config/settings.py から YOUTUBE_VIDEO_ID を読み込む。
3. fetch_comments() メソッドを実装する:
- 最新のコメントを取得し、リストで返す。
- 各コメントからは「投稿者名」と「メッセージ内容」を抽出する。
- エラーが発生してもプログラムが止まらないように例外処理を入れる。
3. 本体(main.py)への組み込み
「耳」ができたら、main.py の input() (手動入力)の部分を、作成した YouTubeCommentFetcher に置き換えます。
これで、「YouTubeで配信を開始すると、視聴者のコメントを勝手に拾って、勝手に雑談し続ける」 という完全自律型AITuberが完成します!
準備ができたら、まずはライブラリのインストールから始めてみてください。AITuberデビューはもう目の前です!



耳・・・なるほどな。
ちなみにアイちゃんはLMがつけてくれた名前だ。
私ではない。 まぁ。これでもいいかな。 レッツトライ!
必要なライブラリのインストール
YouTubeのコメントを取得するためのライブラリ pytchat を使います。ターミナルで以下を実行してください。
pip install pytchat







この手の作業はもうお手の物だね。
だってコピペするだけだし!! 最高だ!
「耳」モジュールの作成
Cursorの Composer (Ctrl + I) を開き、以下の指示を出して、コメントを取得するクラスを作ってもらってください。
Composerへの指示:
modules/perception/youtube.py に、YouTube Liveのコメントを取得する YouTubeCommentFetcher クラスを作成してください。
【要件】
1. pytchat ライブラリを使用する。
2. config/settings.py から YOUTUBE_VIDEO_ID を読み込む。
3. fetch_comments() メソッドを実装する:
- 最新のコメントを取得し、リストで返す。
- 各コメントからは「投稿者名」と「メッセージ内容」を抽出する。
- エラーが発生してもプログラムが止まらないように例外処理を入れる。





今回の私の仕事。
1.ターミナルにコピペする
2. コンポーザーにコピペする・・・ふむ。


modules/perception/youtube.py に YouTubeCommentFetcher クラスを追加しました。
同ファイルには既存の YouTubeCommentListener もそのまま残しています。



次じゃ!
本体(main.py)への組み込み
「耳」ができたら、main.py の input() (手動入力)の部分を、作成した YouTubeCommentFetcher に置き換えます。
これで、「YouTubeで配信を開始すると、視聴者のコメントを勝手に拾って、勝手に雑談し続ける」
という完全自律型AITuberが完成します!



お? これはちょっと複雑な作業かな?
先ずはmain.pyを開いて CTRL+Fでページ内検索開いてinputを検索してみよう!


書き換えるのは # — ユーザー入力 — と書かれた部分だと思いますが。一応LMに聞いてみます
書き換えるのはここでいい?
# --- ユーザー入力 ---
user_input = input("\nあなた: ")
if user_input.lower() in ["exit", "quit", "終了"]:
break
AITuber 開発用LMの回答
はい、その通りです! その input() の部分が、AITuberの「耳」を入れ替えるための手術箇所になります。
ただし、単純に書き換えるだけでなく、「待ち方」のロジックを変える必要があります。



お! ちょっと込み入った作業になりそうだね
”main.py”の書き換え作業
AITuber 開発用LMの回答
これまで: input() であなたが文字を打つまで、プログラムはそこで止まって待っていました。
これから: YouTubeのコメントはいつ来るかわからないため、「コメント来てないかな?(確認)→ 来てないなら1秒休む → また確認」 という**ループ処理(ポーリング)**に変更します。
以下の2ステップで実装しましょう。
「耳」モジュールの作成
まず、YouTubeからコメントを取ってくる部品を作ります。Composerに以下のファイルを作成させてください(または手動で作成)。
ファイル名: modules/perception/youtube.py
modules/perception/youtube.py
import pytchat
from config.settings import settings
import logging
# ログを見やすくするための設定
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class YouTubeCommentFetcher:
def __init__(self):
# .env (config/settings.py経由) から動画IDを読み込む
self.video_id = settings.YOUTUBE_VIDEO_ID
self.chat = None
# インスタンス作成時に接続を開始する
self.connect()
def connect(self):
"""YouTubeチャットに接続する"""
if not self.video_id:
print("⚠️ YouTube Video IDが設定されていません。.envを確認してください。")
return
try:
print(f"📡 YouTubeチャットに接続中... (ID: {self.video_id})")
# pytchatを使用して指定された動画IDのチャットに接続
self.chat = pytchat.create(video_id=self.video_id)
print("✅ 接続成功!コメントを監視します。")
except Exception as e:
print(f"❌ 接続エラー: {e}")
def fetch_comments(self):
"""
前回の取得以降に来た新しいコメントを取得してリストで返す
戻り値: [{"user": "名前", "text": "コメント内容"}, ...]
"""
# チャット接続が生きていない場合は空リストを返す
if not self.chat or not self.chat.is_alive():
# ※ここで再接続処理を入れることも可能ですが、簡易化のためスキップします
return []
comments = []
try:
# sync_items() を使うことで、前回の取得分以降の「新しいコメント」だけを取得できます
for c in self.chat.get().sync_items():
# コメントデータから必要な「投稿者名」と「メッセージ」を抽出
comments.append({
"user": c.author.name,
"text": c.message
})
except Exception as e:
print(f"⚠️ コメント取得中にエラーが発生しました: {e}")
return comments
main.py の書き換え
いよいよ質問いただいた箇所を書き換えます。 main.py を開き、以下の変更を行ってください。
全置換用コードmain.py
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
from modules.perception.youtube import YouTubeCommentFetcher # 【追加】耳モジュール
# キャラクター設定
SYSTEM_PROMPT = """
あなたは「AITuber」のアイです。
元気で明るい、少しおっちょこちょいな性格です。
リスナーのコメントに対して、短くテンポよく返事をしてください。
"""
async def main():
print("🚀 AITuberシステムを起動します...")
# 1. 各モジュールの初期化
brain = LLMClient(system_prompt=SYSTEM_PROMPT)
voice = VoicevoxClient()
body = VTubeStudioClient()
youtube = YouTubeCommentFetcher() # 【追加】YouTube接続インスタンス
# 2. VTube Studioに接続
if not await body.connect():
print("❌ VTube Studioへの接続に失敗しました。")
return
# 会話履歴
history = []
print(f"✅ 準備完了!YouTube配信(ID: {settings.YOUTUBE_VIDEO_ID})のコメントを待機中...")
try:
while True:
# --- 【変更点】YouTubeコメントの取得 ---
# 新しいコメントを取得(リスト形式)
comments = youtube.fetch_comments()
# コメントが来ていない場合は、少し待ってから再確認(CPU負荷軽減のため)
if not comments:
await asyncio.sleep(3) # 3秒待機
continue
# コメントが来た場合、一番新しいものをピックアップして反応する
# (※一度に大量に来た場合、すべてに反応すると遅延するため最新のみ採用)
last_comment = comments[-1]
user_name = last_comment["user"]
user_text = last_comment["text"]
print(f"\n💬 {user_name}: {user_text}")
# "終了" コマンドでシステム停止(管理者用)
if user_text == "終了":
print("システムを終了します。")
break
# --- 思考 (Brain) ---
print("🤖 (思考中...)")
# AIへの入力プロンプトを作成(誰からのコメントかを明記)
prompt_text = f"リスナーの「{user_name}」さんが「{user_text}」と言っています。返事をしてあげて。"
response_text = await brain.generate_response(prompt_text, history)
print(f"アイ: {response_text}")
# 履歴更新(AIの記憶用)
history.append({"role": "user", "content": f"{user_name}: {user_text}"})
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())
# 声を再生(再生完了まで待機)
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())
1. input() の行を削除。
2. 代わりに youtube.fetch_comments() を呼ぶ。
3. コメントがない時は await asyncio.sleep(1) で休ませる(これをしないとPCが固まります)。
◆ステップ1
modules/perception/youtube.pyの作成



手動でやるぞ!フォルダの深い階層にあるから
探さんとな!


正確に修正できるように、ページ内のコードを全部コピペして、LMに修正データをつくってもらいます。
youtube.pyにコピペするコード
import pytchat
from config.settings import settings
import logging
# ログを見やすくするための設定
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class YouTubeCommentFetcher:
def __init__(self):
# .env (config/settings.py経由) から動画IDを読み込む
self.video_id = settings.YOUTUBE_VIDEO_ID
self.chat = None
# インスタンス作成時に接続を開始する
self.connect()
def connect(self):
"""YouTubeチャットに接続する"""
if not self.video_id:
print("⚠️ YouTube Video IDが設定されていません。.envを確認してください。")
return
try:
print(f"📡 YouTubeチャットに接続中... (ID: {self.video_id})")
# pytchatを使用して指定された動画IDのチャットに接続
self.chat = pytchat.create(video_id=self.video_id)
print("✅ 接続成功!コメントを監視します。")
except Exception as e:
print(f"❌ 接続エラー: {e}")
def fetch_comments(self):
"""
前回の取得以降に来た新しいコメントを取得してリストで返す
戻り値: [{"user": "名前", "text": "コメント内容"}, ...]
"""
# チャット接続が生きていない場合は空リストを返す
if not self.chat or not self.chat.is_alive():
# ※ここで再接続処理を入れることも可能ですが、簡易化のためスキップします
return []
comments = []
try:
# sync_items() を使うことで、前回の取得分以降の「新しいコメント」だけを取得できます
for c in self.chat.get().sync_items():
# コメントデータから必要な「投稿者名」と「メッセージ」を抽出
comments.append({
"user": c.author.name,
"text": c.message
})
except Exception as e:
print(f"⚠️ コメント取得中にエラーが発生しました: {e}")
return comments


こちらはテスト用に任意のYOUTUBE配信のコメントを取得するコードみたいですね。.envの設定方法はコチラにまとめています。↓


いよいよ質問いただいた箇所を書き換えます。 main.py を開き、以下の変更を行ってください。
こちらも 既存のmany.pyを提示して正確に書き換えてもらうようにたのみました。
全置換用コード
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
from modules.perception.youtube import YouTubeCommentFetcher # 【追加】耳モジュール
# キャラクター設定
SYSTEM_PROMPT = """
あなたは「AITuber」のアイです。
元気で明るい、少しおっちょこちょいな性格です。
リスナーのコメントに対して、短くテンポよく返事をしてください。
"""
async def main():
print("🚀 AITuberシステムを起動します...")
# 1. 各モジュールの初期化
brain = LLMClient(system_prompt=SYSTEM_PROMPT)
voice = VoicevoxClient()
body = VTubeStudioClient()
youtube = YouTubeCommentFetcher() # 【追加】YouTube接続インスタンス
# 2. VTube Studioに接続
if not await body.connect():
print("❌ VTube Studioへの接続に失敗しました。")
return
# 会話履歴
history = []
print(f"✅ 準備完了!YouTube配信(ID: {settings.YOUTUBE_VIDEO_ID})のコメントを待機中...")
try:
while True:
# --- 【変更点】YouTubeコメントの取得 ---
# 新しいコメントを取得(リスト形式)
comments = youtube.fetch_comments()
# コメントが来ていない場合は、少し待ってから再確認(CPU負荷軽減のため)
if not comments:
await asyncio.sleep(3) # 3秒待機
continue
# コメントが来た場合、一番新しいものをピックアップして反応する
# (※一度に大量に来た場合、すべてに反応すると遅延するため最新のみ採用)
last_comment = comments[-1]
user_name = last_comment["user"]
user_text = last_comment["text"]
print(f"\n💬 {user_name}: {user_text}")
# "終了" コマンドでシステム停止(管理者用)
if user_text == "終了":
print("システムを終了します。")
break
# --- 思考 (Brain) ---
print("🤖 (思考中...)")
# AIへの入力プロンプトを作成(誰からのコメントかを明記)
prompt_text = f"リスナーの「{user_name}」さんが「{user_text}」と言っています。返事をしてあげて。"
response_text = await brain.generate_response(prompt_text, history)
print(f"アイ: {response_text}")
# 履歴更新(AIの記憶用)
history.append({"role": "user", "content": f"{user_name}: {user_text}"})
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())
# 声を再生(再生完了まで待機)
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())


いざ!実行!!
✅ 実行前の最終確認
1. .envファイル: YOUTUBE_VIDEO_ID に、現在配信中(またはテスト用)の動画IDが設定されていることを確認してください。
2. アプリの起動: VOICEVOXとVTube Studioが起動していることを確認してください。





オールグリーン(OK)!
ターミナルで実行だ!
耳モジュール実装完了



コメントにリアクションできてる!
すごい!
耳モジュール実装完了です。いよいよAiTuberぽっくなってきました。配信の環境を整えたら、もう行けそうですね。
次はどんな作業かな。たのしみ!