54 lines
1.4 KiB
JavaScript
54 lines
1.4 KiB
JavaScript
import { useEffect, useState } from 'react';
|
|
import getConfig from 'next/config';
|
|
|
|
export const useAudioLevel = (stream) => {
|
|
const [micVolume, setMicVolume] = useState(0);
|
|
const { assetPrefix } = getConfig().publicRuntimeConfig;
|
|
|
|
useEffect(() => {
|
|
if (!stream) {
|
|
setMicVolume(0);
|
|
return;
|
|
}
|
|
const AudioCtx =
|
|
typeof AudioContext !== 'undefined'
|
|
? AudioContext
|
|
: typeof webkitAudioContext !== 'undefined'
|
|
? webkitAudioContext
|
|
: null;
|
|
if (!AudioCtx) return;
|
|
const audioContext = new AudioCtx();
|
|
const mediaStreamSource = audioContext.createMediaStreamSource(stream);
|
|
let node;
|
|
|
|
const startProcessing = async () => {
|
|
try {
|
|
await audioContext.audioWorklet.addModule(
|
|
`${assetPrefix}/audiolevel-processor.js`
|
|
);
|
|
|
|
node = new AudioWorkletNode(audioContext, 'audiolevel');
|
|
|
|
node.port.onmessage = (event) => {
|
|
let volume = 0;
|
|
if (event.data.volume) volume = event.data.volume;
|
|
if (!node) return;
|
|
setMicVolume(volume);
|
|
};
|
|
|
|
mediaStreamSource.connect(node).connect(audioContext.destination);
|
|
} catch {}
|
|
};
|
|
|
|
startProcessing();
|
|
|
|
return () => {
|
|
node?.disconnect();
|
|
node = null;
|
|
mediaStreamSource?.disconnect();
|
|
audioContext?.close();
|
|
};
|
|
}, [assetPrefix, stream]);
|
|
|
|
return micVolume;
|
|
}; |