diff --git a/.gitignore b/.gitignore index 09f10e08..2523c7e0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ node_modules npm-debug.log +# bun +bun.lock + # mac .DS_Store @@ -20,3 +23,4 @@ turnserver.conf output env.txt +.idea diff --git a/public/js/detectSpeaking.js b/public/js/detectSpeaking.js index e2e5e7fa..9f2376ac 100644 --- a/public/js/detectSpeaking.js +++ b/public/js/detectSpeaking.js @@ -22,29 +22,33 @@ async function getMicrophoneVolumeIndicator(stream) { console.log('Start microphone volume indicator for audio track', stream.getAudioTracks()[0]); const audioContext = new (window.AudioContext || window.webkitAudioContext)(); const microphone = audioContext.createMediaStreamSource(stream); - scriptProcessor = audioContext.createScriptProcessor(1024, 1, 1); - scriptProcessor.onaudioprocess = function (event) { - const inputBuffer = event.inputBuffer.getChannelData(0); - let sum = 0; - for (let i = 0; i < inputBuffer.length; i++) { - sum += inputBuffer[i] * inputBuffer[i]; + + // 创建并配置 AudioWorkletNode + await audioContext.audioWorklet.addModule('volume-processor.js'); + const workletNode = new AudioWorkletNode(audioContext, 'volume-processor', { + processorOptions: { + threshold: 10, // 音量阈值 + peerId: myPeerId, // 你的 peer ID + myAudioStatus: myAudioStatus, // 你的音频状态 + }, + }); + + // 监听处理器发送的消息 + workletNode.port.onmessage = (event) => { + const data = event.data; + + if (data.type === 'micVolume') { + // 发送数据到 DataChannel + sendToDataChannel(data); + handleMyVolume(data); // 自定义处理函数 + } else if (data.type === 'volumeIndicator') { + updateVolumeIndicator(data.volume); // 更新音量指示器 } - const rms = Math.sqrt(sum / inputBuffer.length); - const volume = Math.max(0, Math.min(1, rms * 10)); - const finalVolume = Math.round(volume * 100); - if (myAudioStatus && finalVolume > 10) { - const config = { - type: 'micVolume', - peer_id: myPeerId, - volume: finalVolume, - }; - handleMyVolume(config); - sendToDataChannel(config); - } - updateVolumeIndicator(volume); }; - microphone.connect(scriptProcessor); - scriptProcessor.connect(audioContext.destination); + + // 连接音频图 + microphone.connect(workletNode); + workletNode.connect(audioContext.destination); } else { console.warn('Microphone volume indicator not supported for this browser'); } diff --git a/public/js/volume-processor.js b/public/js/volume-processor.js new file mode 100644 index 00000000..a4e2a58c --- /dev/null +++ b/public/js/volume-processor.js @@ -0,0 +1,39 @@ +// volume-processor.js +class VolumeProcessor extends AudioWorkletProcessor { + constructor(options) { + super(); + this.threshold = options.processorOptions.threshold || 10; + this.peerId = options.processorOptions.peerId || ''; + this.myAudioStatus = options.processorOptions.myAudioStatus || false; + } + + process(inputs, outputs, parameters) { + const input = inputs[0][0]; // 获取输入音频数据 + let sum = 0; + for (let i = 0; i < input.length; i++) { + sum += input[i] * input[i]; + } + const rms = Math.sqrt(sum / input.length); + const volume = Math.max(0, Math.min(1, rms * 10)); + const finalVolume = Math.round(volume * 100); + + // 只有当音量超过阈值且状态为 true 时才发送数据 + if (this.myAudioStatus && finalVolume > this.threshold) { + this.port.postMessage({ + type: 'micVolume', + peer_id: this.peerId, + volume: finalVolume, + }); + } + + // 发送音量数据用于 UI 更新 + this.port.postMessage({ + type: 'volumeIndicator', + volume: volume, + }); + + return true; + } +} + +registerProcessor('volume-processor', VolumeProcessor); \ No newline at end of file