'use client' import { useEffect, useRef } from 'react' export interface WaveformDisplayProps { audioFile: File | string height?: number barWidth?: number barGap?: number barColor?: string progressColor?: string currentTime?: number onSeek?: (time: number) => void } export function WaveformDisplay({ audioFile, height = 80, barWidth = 2, barGap = 1, barColor = 'rgb(63 63 70)', progressColor = 'rgb(168 85 247)', currentTime = 0, onSeek }: WaveformDisplayProps) { const canvasRef = useRef(null) const waveformData = useRef([]) useEffect(() => { if (!audioFile) return const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)() const canvas = canvasRef.current if (!canvas) return const loadAudio = async () => { try { let audioBuffer: ArrayBuffer if (typeof audioFile === 'string') { const response = await fetch(audioFile) audioBuffer = await response.arrayBuffer() } else { audioBuffer = await audioFile.arrayBuffer() } const decodedData = await audioContext.decodeAudioData(audioBuffer) const rawData = decodedData.getChannelData(0) const samples = canvas.width / (barWidth + barGap) const blockSize = Math.floor(rawData.length / samples) const filteredData: number[] = [] for (let i = 0; i < samples; i++) { let blockStart = blockSize * i let sum = 0 for (let j = 0; j < blockSize; j++) { sum += Math.abs(rawData[blockStart + j]) } filteredData.push(sum / blockSize) } const multiplier = Math.pow(Math.max(...filteredData), -1) waveformData.current = filteredData.map(n => n * multiplier) drawWaveform() } catch (error) { console.error('Error loading audio:', error) } } loadAudio() return () => { audioContext.close() } }, [audioFile]) useEffect(() => { drawWaveform() }, [currentTime]) const drawWaveform = () => { const canvas = canvasRef.current if (!canvas) return const ctx = canvas.getContext('2d') if (!ctx) return ctx.clearRect(0, 0, canvas.width, canvas.height) const data = waveformData.current if (data.length === 0) return const duration = data.length * (barWidth + barGap) / canvas.width const progress = currentTime / duration data.forEach((value, index) => { const x = index * (barWidth + barGap) const barHeight = value * height const y = (height - barHeight) / 2 ctx.fillStyle = index < data.length * progress ? progressColor : barColor ctx.fillRect(x, y, barWidth, barHeight) }) } const handleClick = (e: React.MouseEvent) => { if (!onSeek) return const canvas = canvasRef.current if (!canvas) return const rect = canvas.getBoundingClientRect() const x = e.clientX - rect.left const percentage = x / canvas.width const duration = waveformData.current.length * (barWidth + barGap) / canvas.width onSeek(percentage * duration) } return (
) }