useVisualizerFrame
The useVisualizerFrame
hook is a wrapper around the useVisualizer
hook that integrates the getFrequencyData()
function with requestAnimationFrame()
.
It returns a frame
, which is a number[]
representing the frequency data as a React state.
This frame updates in real-time as the audio plays, allowing you to render your visualizer without any additional concerns about data management or updates.
This hook accepts an optional dataPoints
parameter, which defaults to 64
if not specified. This value determines the length of the frame
.
// AudioPlayer.tsx
import { Audio, useVisualizerFrame, formatTime } from '../components/ReAudio';
const Visualizer = () => {
const frame = useVisualizerFrame(16);
return (
<div className='flex justify-center gap-x-1'>
<div className='flex flex-row-reverse items-end justify-center gap-x-1 h-28 overflow-x-hidden'>
{frame.map((f, index) => (
<div
key={index}
style={{ height: `${(f / 255) * 100}%` }}
className='w-1.5 min-h-2.5 bg-white/50 rounded-t-full'
/>
))}
</div>
<div className='flex items-end justify-center gap-x-1 h-28 overflow-x-hidden'>
{frame.map((f, index) => (
<div
key={index}
style={{ height: `${(f / 255) * 100}%` }}
className='w-1.5 min-h-2.5 bg-white/50 rounded-t-full'
/>
))}
</div>
</div>
);
};
const AudioPlayer = () => {
return (
<CodeBlock code={code}>
<div className='re-audio-sample'>
<Audio
playlist={[
{ id: 1, src: '/audio/1.mp3', name: 'for-her-chill' },
{ id: 2, src: '/audio/2.mp3', name: 'trap-type-beat-rap-instrumental-riff' },
{ id: 3, src: '/audio/3.mp3', name: 'whip-afro-dancehall' },
]}
>
{({
loading,
trackIndex,
playlist,
playing,
togglePlay,
duration,
currentTime,
volume,
setVolume,
prevTrack,
nextTrack,
rewindTrack,
forwardTrack,
setCurrentTime,
}) => (
<div>
<div className='flex'>
<div className='flex max-md:flex-col justify-between gap-4 w-full'>
<div className='flex items-center gap-4'>
<div className='size-[60px] bg-[#c4c4c4] rounded' />
<div className='flex flex-col'>
<span className='capitalize'>
{/* @ts-ignore */}
{playlist[trackIndex].name.split(/-/).join(' ')}
</span>
<span>{formatTime(currentTime)}</span>
</div>
</div>
<div className='flex items-center max-md:justify-center gap-x-4'>
<button type='button' onClick={rewindTrack.bind(null, 10)}>
<IconPlayerSkipBackFilled />
</button>
<button type='button' onClick={prevTrack}>
<IconPlayerTrackPrevFilled />
</button>
<button type='button' onClick={togglePlay}>
{playing ? <IconPlayerPauseFilled /> : <IconPlayerPlayFilled />}
</button>
<button type='button' onClick={nextTrack}>
<IconPlayerTrackNextFilled />
</button>
<button type='button' onClick={forwardTrack.bind(null, 10)}>
<IconPlayerSkipForwardFilled />
</button>
</div>
</div>
</div>
<div className='mt-4'>
<input
type='range'
min='0'
max={duration}
step='1'
className='w-full'
value={currentTime}
onChange={e => setCurrentTime(+e.currentTarget.value)}
/>
</div>
<div className='flex items-center justify-between gap-x-4'>
<div className='flex items-center gap-x-2 mt-4'>
<IconVolume2 />
<input
type='range'
min='0'
max='100'
className='w-full md:w-[150px]'
value={volume}
onChange={e => setVolume(+e.currentTarget.value)}
/>
<IconVolume />
</div>
{loading && <span className='max-lg:text-sm mt-2'>loading...</span>}
</div>
<div className='mt-8'>
<Visualizer />
</div>
</div>
)}
</Audio>
</div>
</CodeBlock>
);
};
export default AudioPlayer;
http://localhost:3000
for her chill00:00
warning
In case of any issues, try refreshing the page.