import { useRef, useCallback, useEffect } from "react"; export function AudioVisualizer({ stream, ...props }) { const canvasRef = useRef(null); const visualize = useCallback((stream) => { const audioContext = new (window.AudioContext || window.webkitAudioContext)(); const source = audioContext.createMediaStreamSource(stream); const analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; source.connect(analyser); const canvas = canvasRef.current; const canvasCtx = canvas.getContext("2d"); const bufferLength = analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); const drawVisual = () => { requestAnimationFrame(drawVisual); analyser.getByteTimeDomainData(dataArray); canvasCtx.fillStyle = "rgb(255, 255, 255)"; canvasCtx.fillRect(0, 0, canvas.width, canvas.height); canvasCtx.lineWidth = 2; canvasCtx.strokeStyle = "rgb(0, 0, 0)"; canvasCtx.beginPath(); const sliceWidth = (canvas.width * 1.0) / bufferLength; let x = 0; for (let i = 0; i < bufferLength; ++i) { const v = dataArray[i] / 128.0; const y = (v * canvas.height) / 2; if (i === 0) { canvasCtx.moveTo(x, y); } else { canvasCtx.lineTo(x, y); } x += sliceWidth; } canvasCtx.lineTo(canvas.width, canvas.height / 2); canvasCtx.stroke(); }; drawVisual(); }, []); useEffect(() => { stream && visualize(stream); }, [visualize, stream]); return ; }