g3nbl0k
01/14/2026, 1:58 AMlistenUrl. I'm able to successfully process the data without any issues and I'm attempting to play it back using the Web Audio API. The playback audio is somewhat audible and the voices don't sound distorted or slow/fast, but the quality is poor and it almost sounds muffled (like there's static or something).
Any examples, suggestions or guidance would be much appreciated! I've looked through the documentation and the discord tickets and haven't found anything that is helpful for my situation.
Below is a snippet of my code:
wsRef.current.onmessage = async (event) => {
// Check if it's binary data (PCM audio)
if (event.data instanceof ArrayBuffer) {
try {
// Convert PCM (16-bit signed) to Float32 immediately
const int16Array = new Int16Array(event.data);
const float32Array = new Float32Array(int16Array.length);
for (let i = 0; i < int16Array.length; i++) {
float32Array[i] = int16Array[i] / 32768.0;
}
// Create audio buffer - 16kHz stereo
// VAPI Channel mapping: Left = Customer, Right = Assistant TTS
const sampleRate = 16000;
const channels = 2; // Stereo
const framesPerChannel = float32Array.length / 2; // Divide by 2 because input is stereo interleaved
const audioBuffer = audioContextRef.current.createBuffer(
channels,
framesPerChannel,
sampleRate
);
// De-interleave stereo channels
...
// Play immediately
const source = audioContextRef.current.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioContextRef.current.destination);
source.start(0);
}
Thanks!Chiranjeet Mishra
01/14/2026, 8:32 AMg3nbl0k
01/14/2026, 4:36 PMlistenUrl). This what I'm expected and I actually got
So the issue is not so much that I'm not receiving the data via the listenUrl, but rather the audio quality when I'm attempting to play it back in the browser live is poor.
When i write all the binary data to a PCM file and then play it back using an app called Audacity, then the playback sounds perfect.
The issue arises when I'm trying to process and playback the audio live using the Web Audio API.
My app is written using React (JavaScript/TypeScript). Do you have any guidance or potentially example of doing this successfully in a web app setting?Chiranjeet Mishra
01/14/2026, 7:14 PMChiranjeet Mishra
01/14/2026, 7:53 PMg3nbl0k
01/15/2026, 6:05 PMChiranjeet Mishra
01/16/2026, 11:12 AMg3nbl0k
01/22/2026, 5:33 PMg3nbl0k
01/22/2026, 5:36 PMg3nbl0k
01/22/2026, 5:39 PMusage-example.js
/**
* VAPI Audio Streaming Usage Examples
*
* This file demonstrates how to use the VAPIAudioStreamer class
* to integrate with VAPI's real-time audio streaming.
*/
import VAPIAudioStreamer from './VAPIAudioStreamer.js';
// ============================================
// Example 1: Basic Usage
// ============================================
async function basicExample() {
// Get listenUrl from VAPI API when creating a call
// Format: wss://api.vapi.ai/call/listen/{callId}
const listenUrl = 'wss://api.vapi.ai/call/listen/your-call-id';
// Create streamer instance
const streamer = new VAPIAudioStreamer(listenUrl);
try {
// Initialize and start streaming
await streamer.initialize();
console.log('🎧 Audio streaming started');
// The audio will now stream in real-time until you call cleanup()
} catch (err) {
console.error('Failed to start audio stream:', err);
}
// When the call ends, clean up resources
// streamer.cleanup();
}
// ============================================
// Example 2: With Error Handling and Retry
// ============================================
async function exampleWithRetry(listenUrl, maxRetries = 3) {
const streamer = new VAPIAudioStreamer(listenUrl);
let attempts = 0;
while (attempts < maxRetries) {
try {
await streamer.initialize();
console.log('✅ Audio streaming started successfully');
return streamer;
} catch (err) {
attempts++;
console.error(`❌ Attempt ${attempts} failed:`, err.message);
// Handle specific AudioWorklet race condition
if (err.message.includes('not defined in AudioWorkletGlobalScope') && attempts < maxRetries) {
const delay = 1000 * Math.pow(2, attempts - 1); // Exponential backoff
console.log(`⏳ Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw err; // Give up after max retries
}
}
}
}