After recording audio, React Voice Visualizer provides comprehensive playback controls with synchronized waveform visualization. This page explains how playback works, the audio element management, and how visualization is synchronized with playback progress.
The startAudioPlayback() function initiates or resumes playback:
// From useVoiceVisualizer.tsx:310-323const startAudioPlayback = () => { if (!audioRef.current || isRecordingInProgress) return; requestAnimationFrame(handleTimeUpdate); startPlayingAudio(); audioRef.current.addEventListener('ended', onEndedRecordedAudio); setIsPausedRecordedAudio(false); if (onStartAudioPlayback && currentAudioTime === 0) { onStartAudioPlayback(); } if (onResumedAudioPlayback && currentAudioTime !== 0) { onResumedAudioPlayback(); }};
1
Start Time Updates
Begins the requestAnimationFrame loop to track current playback time
2
Play Audio
Calls audio.play() with error handling
3
Add Event Listener
Listens for the ‘ended’ event to reset playback when audio finishes
4
Update State
Sets isPausedRecordedAudio to false
5
Trigger Callbacks
Calls onStartAudioPlayback or onResumedAudioPlayback based on current time
The actual play() call includes error handling:
// From useVoiceVisualizer.tsx:294-308const startPlayingAudio = () => { if (audioRef.current && audioRef.current.paused) { const audioPromise = audioRef.current.play(); if (audioPromise !== undefined) { audioPromise.catch((error) => { console.error(error); if (onErrorPlayingAudio) { onErrorPlayingAudio( error instanceof Error ? error : new Error('Error playing audio') ); } }); } }};
The audio.play() method returns a Promise that can reject if playback is prevented (e.g., by browser autoplay policies). The error is caught and passed to the onErrorPlayingAudio callback.
During playback, the current time is tracked using requestAnimationFrame:
// From useVoiceVisualizer.tsx:205-211const handleTimeUpdate = () => { if (!audioRef.current) return; setCurrentAudioTime(audioRef.current.currentTime); rafCurrentTimeUpdateRef.current = requestAnimationFrame(handleTimeUpdate);};
This creates a ~60fps update loop that synchronizes the visualization with playback.
Using requestAnimationFrame instead of the audio element’s timeupdate event provides smoother, more frequent updates for visualization (useVoiceVisualizer.tsx:210).
const { audioRef, // HTMLAudioElement ref isPausedRecordedAudio, // true when paused isAvailableRecordedAudio, // true when audio is ready currentAudioTime, // current position in seconds duration, // total duration in seconds formattedRecordedAudioCurrentTime, // formatted current time formattedDuration, // formatted duration audioSrc, // blob URL for download startAudioPlayback, // function to play stopAudioPlayback, // function to pause togglePauseResume, // function to toggle setCurrentAudioTime, // function to seek} = useVoiceVisualizer();
Browsers may block audio.play() if it’s not triggered by a user interaction. Always initiate playback from a click/tap handler. See Autoplay policy for details.