召喚出来ました!
VRChat内で自分のアバター以外のなにかとお話出来るようにする流れを作りました
VRChatで遊んでいて、「ログインした時間にはフレンドがいない…」なんてことがあります。
※VRChatとはVRSNS、メタバースサービスです
そんなとき、AITuberに取り組んでいたり、AIキャラコンテンツや開発者さんのSNSをTLで見てた時、ふと「AIキャラクターをVR空間に召喚して、一緒におしゃべりできたら面白そうだな」と思いました。
今回は 自分でやってみたい! というところから、その「VR空間内でAI対話キャラクターを登場させて会話する」仕組みを作ってみたので、制作の流れや試行錯誤のポイントをまとめます。
Twitterに投稿した映像URL
はじめに
やりたかったこと
VR空間内にAI対話キャラクターを出現させる
「イマジナリーフレンド」的な存在
フレンドが不在な時間にAIキャラクターと楽しく会話できるようにする
このアイデアは、以前から取り組んでみたかった「OSC通信」練習も兼ねています
今回の制作では、VRChatそのものへ大掛かりな接続はありません。
VRChat側との連携は以下程度です。
1.APIから取得したテキストをVRChat内の吹き出しとして表示
2.音声入力はPCローカルで実行
3.テキスト生成AIとのやりとりはコンソール上で完結
4.AIの返答音声(VOICEVOX生成)はマイク音声としてVRChat側に出力
5.自分の声も同時に入れられるよう、ミキシングソフトを活用
6.ハムスターアイテム(既存製品)をそのまま活用
UnityやVRChat特有の複雑な設定はあまり多くありませんでした。
※ハムスターアイテムは既存品で、とてもわかりやすい導入マニュアルがありました!
使用環境とツール一覧
無料ツール・サービス
Python 3.12
Voicemeeter Banana(仮想オーディオミキサー)
マイク(手元のマイク)
VOICEVOX
OpenAI API (gpt4o-mini)
Unity
VRChat(Steamで無料!!!)
有料ツール
Boothで購入したハムスターアイテム(今回の本体的存在)1,000円
OSC通信参考資料
システム構成
今回用いたパッケージは大まかに「4+2」の構成となりました。
(o1に上記書いてみてもらいました、多分いい感じ)
pythoファイルは基本4ファイルで構成
+2はこの後の音声絡みで必要なものがあってです。(後述)
音声構成図
ハムスターアイテム・VRChatの都合でAI音声もマイク入力に統一する必要がありました。(後述)
制作の流れ
コンセプト
あくまで自分がログインしたときに付随して現れる、イマジナリーフレンドのような存在を目指しました。
つまり、「自分専用のおしゃべり相手をその場で召喚して話したい!」という発想がベースです。
段階的な取り組み
基本構造はsaldraさんの本を参考に自分でも手を動かしたAITuberの構成です。
その流れから、まずはVRChatにAIの返答を出せるようにしたかったです。
そしてその次に「自分の声」をAIに入力できるようにステップアップ
音声入力への取り組み
YouTubeコメントではなく、「VR空間で自分が声でAIに話しかける」風にするために、音声入力が欲しくなりました。
ここではChatGPT(o1-preview版)に相談して実装方法を模索。音声認識にはいくつか既存のやり方もあるかと思いますが、今回はとにかく「VRでしゃべりたい!」という欲求が先行したため、まずは完成優先でAIに任せる形を取りました。
抜粋コード
# 音声入力によるユーザー入力取得
key_input = get_voice_input()
if key_input is None:
continue # 音声認識失敗時は再度入力要求
print("あなた: " + key_input)
# Voicevoxアダプターを初期化(main.pyの前部で行っている場合は重複削除)
voicevox = VoicevoxAdapter(speaker_id=3)
# OpenAIなどのプロセスを経て、生成した返信をtextとして得たと仮定
reply_content = "AIによる生成テキスト"
# VOICEVOXへテキスト送信し、合成音声データを取得
data, sample_rate = voicevox.get_voice(reply_content)
# 合成音声を再生
play_audio(data, sample_rate)
アバターの口以外から声を出す
こちらのBooth商品を購入しました
これは、Unityの知識があまりなくても、アバター以外のオブジェクトから音声を発する手助けをしてくれるマニュアル付きの素敵なアイテムです。まさに求めていた機能を補うのにピッタリでした。
音声処理上の問題点と解決策
課題1:自分の声とAIの声を分けられない
VRChatでは「マイク入力は1本」で扱います。そのため、自分の声とAIボイス(VOICEVOX出力)を分けて扱うことが難しいです。
課題2:PC内音声がすべて混ざってしまう
もしPC内で再生されるYouTube音声やVRChatの環境音までもが、AIキャラクターの声と混ざってしまったら? 全てがひとつのマイク音声として流れてしまい、非常に不便です。
解決策:仮想オーディオミキサーソフトの導入
上記2つの課題を解消するため、仮想オーディオミキサーソフトを使いました。
参考記事
このソフトを使えば、
自分のマイク音声
VOICEVOXによるAI音声
PC内の他アプリ音声
これらを細かくルーティング・ミックスできます。
マイク・スピーカー番号の確認
PC内でマイクやスピーカー番号を取得するためにコードを実行し、出力された番号にあわせてプログラム内を調整します。ただし、PCを再起動するとデバイス番号が変わることもあるため、そのたびに確認が必要です。
音声入力用コード
# voice_input.py
import speech_recognition as sr
def get_voice_input():
"""
事前に指定したマイクデバイスから音声を入力する。
"""
recognizer = sr.Recognizer()
# 使用するマイクのインデックスを指定
mic_index = 13 # 使用したいマイクのインデックス番号を指定してください
try:
# マイクを指定して音声を取得
with sr.Microphone(device_index=mic_index) as source:
print(f"マイク '{sr.Microphone.list_microphone_names()[mic_index]}' を使用します。")
print("音声入力を開始します。話しかけてください...")
recognizer.adjust_for_ambient_noise(source) # 環境ノイズを調整
audio = recognizer.listen(source)
# 音声をテキストに変換
text = recognizer.recognize_google(audio, language='ja-JP')
print("あなた(音声入力): " + text)
return text
except sr.UnknownValueError:
print("音声を認識できませんでした。もう一度お試しください。")
return None
except sr.RequestError as e:
print(f"音声認識サービスにアクセスできませんでした; {e}")
return None
except IndexError:
print("指定したマイクインデックスが無効です。マイクのリストを確認してください。")
return None
except Exception as e:
print(f"予期しないエラーが発生しました: {e}")
return None
音声出力用コード
# voice_output.py
import numpy as np
import sounddevice as sd
def play_audio(data: np.ndarray, sample_rate: int):
"""
指定されたデバイスを使用して音声を再生する。
"""
# 使用するオーディオデバイスのインデックスを指定
output_device_id = 29 # 使用したいデバイスのインデックス番号(例: 1 = ヘッドホン)
try:
print(f"出力デバイス: '{sd.query_devices()[output_device_id]['name']}' を使用します。")
sd.play(data, sample_rate, device=output_device_id)
sd.wait()
except Exception as e:
print(f"エラーが発生しました: {e}")
マイク番号取得プログラム
# マイク番号取得プログラム
import speech_recognition as sr
# 使用可能なマイクデバイスをリスト表示
print("使用可能なマイクデバイス:")
for index, name in enumerate(sr.Microphone.list_microphone_names()):
print(f"{index}: {name}")
スピーカー番号取得プログラム
# スピーカー番号取得プログラム
import sounddevice as sd
# デバイス一覧を表示
print("使用可能なオーディオデバイス:")
devices = sd.query_devices()
for idx, device in enumerate(devices):
print(f"{idx}: {device['name']}")
また、VRChatで他のフレンドと合流出来て、会話する可能性も考慮して、「自分の声」をVRChatへ常時流せるようにもしておきます。
マイク音声をVRChatアプリケーションに対してカットは絶対しません。
つまり、「AI対話用」と「フレンドとの会話用」のどちらにも入出力できるようにする必要がありました。
将来の改善ポイントメモ
遅延対策
音声認識精度の向上
Real Time API対応
任意の音声モデルやAPI先の差し替え(Dify等)
⇒バーチャルアシスタント機能拡張(リアルタイム情報活用)
⇒カレンダーとかタスクの相談、メモとか出来てもいいですよね
12月12日現在、GoogleのGeminiのニュースなども流れ始めていて、今後はよりリアルタイムな情報取得や、規約面をクリアしたうえで映像の解析なども可能になれば、さらに面白いVRアシスタントが実現しそうだとわくわくしています。
あとは改善じゃないけど、この制作に触発されてやりたいこと出来ちゃったんでそれも世間的な冬休み期間にやりたいなあと思ってまする..
まとめ
今回は、VRChat内にAIキャラを召喚して対話するまでの流れを紹介しました。まだまだ改良の余地はありますが、ひとまず「VRで独りでもAIと会話できる環境」を実現できたのは、私にとっては大きな一歩です!
楽しい!
これからも技術の進歩やサービスの充実に合わせて、ちょぼちょぼとより自然なVR空間でのAIとのコミュニケーションができるよう遊んでいきたいと思ってます!
自己紹介
名前:toMo
X:@meyukumin
飛行機✈️と特撮と性の話とサイエンスとメタバースとAIが好きな掛け合わせも楽しんでいく物好き
とりあえずのノリも含め気軽に生成AIの話題とかVR、メタバースの話題を楽しんでいます!
交流したり一緒にお話も出来たら嬉しいです!