From 537ddcd841ef8dcd9f06ffa748a67f8fd58511ac Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Thu, 4 Jun 2026 13:59:04 -0400 Subject: [PATCH] fix: play Opus TTS audio directly instead of WAV-converting it The backend sends Opus-encoded audio from OpenAI TTS (tts-1 with response_format=opus). The frontend was treating it as raw PCM16 and wrapping it in a WAV container, which corrupted the audio into static. Now plays the Opus data directly as audio/ogg. --- frontend/src/hooks/useConversation.ts | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/frontend/src/hooks/useConversation.ts b/frontend/src/hooks/useConversation.ts index b1c2543..8f44cc6 100644 --- a/frontend/src/hooks/useConversation.ts +++ b/frontend/src/hooks/useConversation.ts @@ -151,28 +151,14 @@ export function useConversation() { break; case 'audio': { - // Incoming PCM16 audio from Kira + // Incoming Opus audio from TTS (full response, not streamed) if (msg.data && audioRef.current) { - // Accumulate audio chunks and create a blob const binary = atob(msg.data); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) { bytes[i] = binary.charCodeAt(i); } - audioBufferRef.current.push(bytes); - - // Convert accumulated PCM16 to WAV blob for playback - const allChunks = audioBufferRef.current; - const totalLen = allChunks.reduce((s, c) => s + c.length, 0); - const combined = new Uint8Array(totalLen); - let offset = 0; - for (const chunk of allChunks) { - combined.set(chunk, offset); - offset += chunk.length; - } - - const wav = pcm16ToWav(combined); - const blob = new Blob([wav], { type: 'audio/wav' }); + const blob = new Blob([bytes], { type: 'audio/ogg' }); const url = URL.createObjectURL(blob); audioRef.current.src = url; audioRef.current.play().catch(() => {});