"use client"; import React, { useEffect, useRef, useState } from 'react'; import WaveSurfer from 'wavesurfer.js'; import { Play, Pause, FastForward, Rewind, Activity, Music } from 'lucide-react'; interface SmartCompareStudioProps { originalUrl: string; cleanedUrl: string; audioRef?: React.RefObject; } export default function SmartCompareStudio({ originalUrl, cleanedUrl, audioRef }: SmartCompareStudioProps) { const containerRef = useRef(null); const originalContainerRef = useRef(null); const originalAudioRef = useRef(null); const localCleanedAudioRef = useRef(null); const [isPlaying, setIsPlaying] = useState(false); const [activeTrack, setActiveTrack] = useState<'original' | 'cleaned'>('cleaned'); const [isReady, setIsReady] = useState(false); const originalWs = useRef(null); const cleanedWs = useRef(null); useEffect(() => { if (!containerRef.current || !originalContainerRef.current) return; // Initialize Original Waveform (Hidden from view but plays audio when active) const originalOptions: any = { container: originalContainerRef.current, waveColor: '#3f3f46', progressColor: '#71717a', height: 10, }; if (originalAudioRef.current) { originalOptions.media = originalAudioRef.current; } else { originalOptions.url = originalUrl; } originalWs.current = WaveSurfer.create(originalOptions); // Initialize Cleaned Waveform (Visible) const cleanedOptions: any = { container: containerRef.current, waveColor: '#1877F2', progressColor: '#60A5FA', cursorColor: '#ffffff', barWidth: 2, barGap: 2, barRadius: 2, height: 100, }; if (audioRef && audioRef.current) { cleanedOptions.media = audioRef.current; } else if (localCleanedAudioRef.current) { cleanedOptions.media = localCleanedAudioRef.current; } else { cleanedOptions.url = cleanedUrl; } cleanedWs.current = WaveSurfer.create(cleanedOptions); // Sync play/pause cleanedWs.current.on('play', () => { setIsPlaying(true); originalWs.current?.play(); }); cleanedWs.current.on('pause', () => { setIsPlaying(false); originalWs.current?.pause(); }); // Sync seeking (When user clicks on the visible waveform) cleanedWs.current.on('seeking', (currentTime) => { originalWs.current?.setTime(currentTime); }); Promise.all([ new Promise(resolve => originalWs.current?.on('ready', resolve)), new Promise(resolve => cleanedWs.current?.on('ready', resolve)) ]).then(() => { setIsReady(true); // Default to playing cleaned originalWs.current?.setVolume(0); cleanedWs.current?.setVolume(1); }); return () => { originalWs.current?.destroy(); cleanedWs.current?.destroy(); }; }, [originalUrl, cleanedUrl, audioRef]); const togglePlayback = () => { if (isPlaying) { cleanedWs.current?.pause(); // originalWs is synced via events } else { cleanedWs.current?.play(); // originalWs is synced via events } }; const handleTrackSwitch = (track: 'original' | 'cleaned') => { setActiveTrack(track); if (track === 'original') { originalWs.current?.setVolume(1); cleanedWs.current?.setVolume(0); } else { originalWs.current?.setVolume(0); cleanedWs.current?.setVolume(1); } }; return (
{/* Hidden container and audio for original track */}

Smart Compare Studio

{/* A/B Toggle Switch */}
{/* Waveform Container */}
{!isReady && (
)}
{/* Controls */}
); }