This code worked for me to get the chunks streaming in:
`await websocket.send_text('|AUDIO_START|')
with openai_client.audio.speech.with_streaming_response.create( model="tts-1", voice="nova", response_format="mp3", # Changed to mp3 format input=text_message, ) as response: for chunk in response.iter_bytes(chunk_size=1024): await websocket.send_bytes(chunk) await websocket.send_text('|AUDIO_END|')`
Then, the challenge was figuring it out on the frontend on React.
// Handle incoming messages useEffect(() => { if (lastMessage?.data === '|AUDIO_START|') { setAudioBuffers([]); // Clear existing buffers setIsAudioStreaming(true); chunksRef.current = []; } else if (lastMessage?.data === '|AUDIO_END|') { setIsAudioStreaming(false); playAudioChunks(); } else if (isAudioStreaming && lastMessage?.data) { console.log('trying to parse audio chunk:'); console.log(lastMessage.data); chunksRef.current.push(lastMessage.data); // playAudioChunk(lastMessage.data); } }, []); const playAudioChunks = async () => { const audioBlob = new Blob(chunksRef.current, { type: 'audio/mp3' }); const audioUrl = URL.createObjectURL(audioBlob); const audio = new Audio(audioUrl); try { await audio.play(); } catch (err) { console.error('Error playing audio:', err); } // Clean up the URL after audio is done playing audio.onended = () => { URL.revokeObjectURL(audioUrl); }; };
Sorry for the bad formatting, but hope this helps if you are struggling.
I am trying to figure out how to play chunk by chunk the best way. If I play each chunk as it comes in, the audio sounds weird so need to look into modifying this code (a larger chunk size? a delay?). Feel free to comment if any insights to share with the community.
const playAudioChunk = async (chunk) => { const audioBlob = new Blob([chunk], { type: 'audio/mp3' }); const audioUrl = URL.createObjectURL(audioBlob); const audio = new Audio(audioUrl); try { await audio.play(); } catch (err) { console.error('Error playing audio:', err); } // Clean up the URL after audio is done playing audio.onended = () => { URL.revokeObjectURL(audioUrl); }; };
Top comments (0)