この記事では、OpenAI Realtime API を使用して会話中断機能を実装する方法を紹介します。
実装の詳細は、GitHub リポジトリで入手できます。
この実装は、Azure-Samples/aoai-realtime-audio-sdk のコードに基づいています。コードの詳細な説明は、この記事にあります。
この実装では、オーディオの入出力にローカル PC のマイクとスピーカーを使用します。
マイクからキャプチャされた音声は、処理のために OpenAI Realtime API サーバーに送信されます。
ローカル PC のマイクからオーディオをキャプチャするには、pyaudio ライブラリのストリーム機能を使用します。次のコードは、オーディオ入力用のストリームを設定します:
p = pyaudio.PyAudio() input_default_input_index = p.get_default_input_device_info()['index'] input_stream = p.open( format=STREAM_FORMAT, channels=INPUT_CHANNELS, rate=INPUT_SAMPLE_RATE, input=True, output=False, frames_per_buffer=INPUT_CHUNK_SIZE, input_device_index=input_default_input_index, start=False, ) input_stream.start_stream()
オーディオ キャプチャは、並列処理のために threading.Thread を使用して実行されます。マイクから取得した音声データはbase64形式にエンコードされキューに格納されます。
def listen_audio(input_stream: pyaudio.Stream): while True: audio_data = input_stream.read(INPUT_CHUNK_SIZE, exception_on_overflow=False) if audio_data is None: continue base64_audio = base64.b64encode(audio_data).decode("utf-8") audio_input_queue.put(base64_audio) threading.Thread(target=listen_audio, args=(input_stream,), daemon=True).start()
キューに保存された Base64 文字列は、「input_audio_buffer.append」メッセージとして OpenAI Realtime API サーバーに送信されます。
async def send_audio(client: RTLowLevelClient): while not client.closed: base64_audio = await asyncio.get_event_loop().run_in_executor(None, audio_input_queue.get) await client.send(InputAudioBufferAppendMessage(audio=base64_audio)) await asyncio.sleep(0)
オーディオ再生は、OpenAI Realtime API サーバーから受信したオーディオ データを使用して、ローカル PC のスピーカーを通じて実行されます。
音声データはサーバーから「response.audio.delta」メッセージとして受信されます。受信したデータはbase64でエンコードされているため、デコードしてキューに格納し、再生可能な形式に変換します。
async def receive_messages(client: RTLowLevelClient): while True: message = await client.recv() if message is None: continue match message.type: case "response.audio.delta": audio_data = base64.b64decode(message.delta) for i in range(0, len(audio_data), OUTPUT_CHUNK_SIZE): audio_output_queue.put(audio_data[i:i+OUTPUT_CHUNK_SIZE]) await asyncio.sleep(0)
キューに保存されたデータは、並列処理を使用してローカル PC のスピーカーから再生されます。この再生プロセスでは、threading.Thread を使用して、オーディオ データがリアルタイムでスムーズに再生されるようにします。
def play_audio(output_stream: pyaudio.Stream): while True: audio_data = audio_output_queue.get() output_stream.write(audio_data) p = pyaudio.PyAudio() output_default_output_index = p.get_default_output_device_info()['index'] output_stream = p.open( format=STREAM_FORMAT, channels=OUTPUT_CHANNELS, rate=OUTPUT_SAMPLE_RATE, input=False, output=True, frames_per_buffer=OUTPUT_CHUNK_SIZE, output_device_index=output_default_output_index, start=False, ) output_stream.start_stream() threading.Thread(target=play_audio, args=(output_stream,), daemon=True).start()
OpenAI Realtime API は、サーバー側で会話セグメントを自動的に検出します。これにより、AI が応答している間でも、新しい音声を検出し、リアルタイムの応答を作成することができます。
ただし、ローカル PC で音声を再生する場合は、会話が自然に中断されるように、進行中の音声の再生を停止することが重要です。この点は注意が必要です。ユーザーの音声の検出は、OpenAI Realtime API サーバーから「input_audio_buffer.speech_started」メッセージとして受信されます。このメッセージを受信すると、キューに保存されている音声データをクリアして再生を停止します。
async def receive_messages(client: RTLowLevelClient): while True: message = await client.recv() # print(f"{message=}") if message is None: continue match message.type: case "input_audio_buffer.speech_started": print("Input Audio Buffer Speech Started Message") print(f" Item Id: {message.item_id}") print(f" Audio Start [ms]: {message.audio_start_ms}") while not audio_output_queue.empty(): audio_output_queue.get()
オーディオ出力に関しては、変更は必要ありません。前に説明したコードで説明されているように動作します。
今回は、会話中断のためのPython実装を紹介しました。
この記事が、私と同じように、AI の音声を効果的に停止するという課題に直面している人にとって役立つことを願っています。
さらに、ストリーム インスタンスの定義と構成は、オーディオ再生の品質に影響を与える可能性があります。オーディオの再生が中断される場合は、これらの設定を確認すると状況が改善される可能性があります。
最後まで読んでいただきありがとうございます
以上がステップバイステップ ガイド: OpenAI Realtime API を使用した中断管理の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。