Spaces:
Running
Running
| import { useRef, useEffect, useState, useCallback } from "react"; | |
| import WaveSurfer from "wavesurfer.js"; | |
| interface UseWaveSurferOptions { | |
| url: string; | |
| color: string; | |
| height?: number; | |
| instanceId: string; | |
| } | |
| export function useWaveSurfer({ | |
| url, | |
| color, | |
| height = 64, | |
| instanceId, | |
| }: UseWaveSurferOptions) { | |
| const containerRef = useRef<HTMLDivElement>(null); | |
| const wsRef = useRef<WaveSurfer | null>(null); | |
| const [isPlaying, setIsPlaying] = useState(false); | |
| const [currentTime, setCurrentTime] = useState(0); | |
| const [duration, setDuration] = useState(0); | |
| const [isReady, setIsReady] = useState(false); | |
| useEffect(() => { | |
| if (!containerRef.current || !url) return; | |
| const ws = WaveSurfer.create({ | |
| container: containerRef.current, | |
| url, | |
| waveColor: color + "30", | |
| progressColor: color + "ee", | |
| height, | |
| barWidth: 2, | |
| barGap: 1, | |
| barRadius: 2, | |
| cursorWidth: 1, | |
| cursorColor: "#ffffff40", | |
| normalize: true, | |
| interact: true, | |
| }); | |
| wsRef.current = ws; | |
| ws.on("ready", () => { | |
| setDuration(ws.getDuration()); | |
| setIsReady(true); | |
| }); | |
| ws.on("timeupdate", (time) => { | |
| setCurrentTime(time); | |
| }); | |
| ws.on("play", () => setIsPlaying(true)); | |
| ws.on("pause", () => setIsPlaying(false)); | |
| ws.on("finish", () => setIsPlaying(false)); | |
| // Exclusive playback: pause when another player starts | |
| const handleStemPlay = (e: Event) => { | |
| const detail = (e as CustomEvent).detail; | |
| if (detail !== instanceId) { | |
| ws.pause(); | |
| } | |
| }; | |
| window.addEventListener("stem-play", handleStemPlay); | |
| return () => { | |
| window.removeEventListener("stem-play", handleStemPlay); | |
| ws.destroy(); | |
| wsRef.current = null; | |
| setIsReady(false); | |
| setIsPlaying(false); | |
| }; | |
| }, [url, color, height, instanceId]); | |
| const togglePlay = useCallback(() => { | |
| if (!wsRef.current) return; | |
| if (wsRef.current.isPlaying()) { | |
| wsRef.current.pause(); | |
| } else { | |
| // Dispatch event to pause other players | |
| window.dispatchEvent( | |
| new CustomEvent("stem-play", { detail: instanceId }) | |
| ); | |
| wsRef.current.play(); | |
| } | |
| }, [instanceId]); | |
| return { | |
| containerRef, | |
| isPlaying, | |
| isReady, | |
| currentTime, | |
| duration, | |
| togglePlay, | |
| }; | |
| } | |