import { useEffect, useRef, useImperativeHandle, forwardRef } from 'react' import WaveSurfer from 'wavesurfer.js' // @ts-ignore: No types for timeline.esm.js import TimelinePlugin from 'wavesurfer.js/dist/plugins/timeline.esm.js' import API from '../API' export interface AudioPlayerHandle { getCurrentTime: () => number setTime: (t: number) => void play: () => void pause: () => void } const AudioPlayer = forwardRef< AudioPlayerHandle, { src: string playing: boolean // seekTo: number onPlay: () => void onPause: () => void onAudioProcess?: (currentTime: number) => void } >(({ src, playing, onPlay, onPause, onAudioProcess }, ref) => { const containerRef = useRef(null) const wavesurferRef = useRef(null) useImperativeHandle(ref, () => ({ getCurrentTime: () => wavesurferRef.current?.getCurrentTime() || 0, setTime: (t: number) => wavesurferRef.current?.setTime(t), play: () => wavesurferRef.current?.play(), pause: () => wavesurferRef.current?.pause(), })) // Sync play/pause and seek useEffect(() => { if (wavesurferRef.current) { // wavesurferRef.current.setTime(seekTo) if (playing) { wavesurferRef.current.play() } else { wavesurferRef.current.pause() } } }, [ playing, // seekTo ]) useEffect(() => { if (!containerRef.current) return if (wavesurferRef.current) { wavesurferRef.current.destroy() wavesurferRef.current = null } const proxiedUrl = API.getProxiedUrl(src) const bottomTimeline = TimelinePlugin.create({ height: 16, timeInterval: 0.1, primaryLabelInterval: 1, style: { fontSize: '10px' }, }) wavesurferRef.current = WaveSurfer.create({ container: containerRef.current, waveColor: 'rgb(200, 0, 200)', progressColor: 'rgb(100, 0, 100)', url: proxiedUrl, minPxPerSec: 100, mediaControls: true, plugins: [bottomTimeline], }) wavesurferRef.current.on('play', onPlay) wavesurferRef.current.on('pause', onPause) if (onAudioProcess) { wavesurferRef.current.on('audioprocess', onAudioProcess) } return () => { if (wavesurferRef.current && onAudioProcess) { wavesurferRef.current.un('audioprocess', onAudioProcess) } wavesurferRef.current?.destroy() wavesurferRef.current = null } }, [src]) return (
) }) export default AudioPlayer