You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
2.2 KiB
79 lines
2.2 KiB
import { useEffect, useRef, useState } from "react";
|
|
|
|
export default function VoiceAnalysis(){
|
|
|
|
const [volume, setVolume] = useState(0);
|
|
const refVolumeInterval=useRef();
|
|
const refAnalyser=useRef();
|
|
const refVolumes=useRef();
|
|
|
|
|
|
async function setup(){
|
|
try{
|
|
|
|
|
|
|
|
const audioStream = await navigator.mediaDevices.getUserMedia({
|
|
audio: {
|
|
echoCancellation: true
|
|
},
|
|
video: false
|
|
});
|
|
|
|
audioStream.getAudioTracks().forEach(track => {
|
|
console.log(`Track ID: ${track.id}, Label: ${track.label}`);
|
|
});
|
|
|
|
const audioContext = new AudioContext();
|
|
const source = audioContext.createMediaStreamSource(audioStream);
|
|
const analyser = audioContext.createAnalyser();
|
|
analyser.fftSize = 512;
|
|
analyser.minDecibels = -127;
|
|
analyser.maxDecibels = 0;
|
|
analyser.smoothingTimeConstant = 0.4;
|
|
|
|
source.connect(analyser);
|
|
|
|
const volumes = new Uint8Array(analyser.frequencyBinCount);
|
|
|
|
refAnalyser.current = analyser;
|
|
refVolumes.current = volumes;
|
|
}catch(e){
|
|
console.error('error start audio stream',e);
|
|
}
|
|
|
|
}
|
|
const volumeCallback = () => {
|
|
|
|
const volumes = refVolumes.current;
|
|
|
|
refAnalyser.current.getByteFrequencyData(volumes);
|
|
|
|
let volumeSum = 0;
|
|
for(const volume of volumes)
|
|
volumeSum += volume;
|
|
const averageVolume = volumeSum / volumes.length;
|
|
// console.log(`Average Volume: ${averageVolume}`);
|
|
setVolume(averageVolume);
|
|
|
|
};
|
|
|
|
useEffect(()=>{
|
|
setup().then(() => {
|
|
refVolumeInterval.current = setInterval(() => {
|
|
volumeCallback();
|
|
}, 100); // Adjust the interval as needed
|
|
});
|
|
|
|
return () => {
|
|
clearInterval(refVolumeInterval.current);
|
|
};
|
|
},[]);
|
|
|
|
return (
|
|
<div className="voice-analysis border flex flex-col justify-end">
|
|
{/* <p>Volume: {volume}</p> */}
|
|
<div className="w-full bg-amber-600" style={{ height: `${volume/127*100}%` }}></div>
|
|
</div>
|
|
);
|
|
} |