Audio Worklet麦克风流捕获问题:Float32转Int16结果全为0
解决Audio Worklet捕获麦克风流时Float32转Int16Array全为0的问题
问题分析
你的代码存在两个核心问题导致转换后全为0:
- 对
inputs的结构理解错误,遍历层级不对,导致处理的是单个音频样本值而非整个通道数组 - Float32转Int16时未做范围映射,Web Audio的样本值归一化在
[-1, 1]区间,直接转Int16会被取整为0
修正后的代码
主JavaScript代码
let microphone, context, source, bufferDetectorNode; try { navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; microphone = navigator.getUserMedia({ audio: true, video: false }, onMicrophoneGranted, onMicrophoneDenied); } catch (e) { alert(e); } async function onMicrophoneGranted(stream) { console.log(stream); context = new AudioContext(); // 现代浏览器要求AudioContext需用户交互激活 if (context.state === 'suspended') { await context.resume(); } source = context.createMediaStreamSource(stream); await context.audioWorklet.addModule('/assets/js/buffer-detector.js'); bufferDetectorNode = new AudioWorkletNode(context, 'buffer-detector'); bufferDetectorNode.port.onmessage = (event) => { // 接收来自Worklet的Int16音频数据 console.log('捕获的Int16音频数据:', event.data.intArray); }; source.connect(bufferDetectorNode); bufferDetectorNode.connect(context.destination); } function onMicrophoneDenied() { console.log('麦克风权限被拒绝'); }
AudioWorklet代码(buffer-detector.js)
class BufferProcessor extends AudioWorkletProcessor { process(inputs) { // 检查是否有有效输入数据 if (inputs.length === 0 || inputs[0].length === 0) { return true; } // 取第一个输入端口的第一个通道(单声道场景) const inputChannel = inputs[0][0]; const intArray = new Int16Array(inputChannel.length); // 遍历样本做归一化值到Int16的映射 for (let i = 0; i < inputChannel.length; i++) { // 将[-1,1]的Float32值映射到[-32768, 32767]的Int16范围 let sample = inputChannel[i] * 32767; // 限制范围防止溢出 sample = Math.max(-32768, Math.min(32767, sample)); // 取整得到Int16值 intArray[i] = Math.round(sample); } // 通过port将数据发送到主线程 this.port.postMessage({ intArray }); return true; } static get parameterDescriptors() { return []; } constructor() { super(); // 若initBuffer无实际逻辑可删除,有则保留 // this.initBuffer(); } } registerProcessor('buffer-detector', BufferProcessor);
关键修改说明
修正inputs遍历逻辑:
Web Audio的inputs结构为Array<Array<Float32Array>>,外层是输入端口,中间是音频通道,内层是通道的样本数组。直接取第一个输入端口的第一个通道即可,避免多层错误遍历。正确的Float32到Int16转换:
Web Audio样本值归一化在[-1, 1],而Int16的有效范围是[-32768, 32767]。需将每个样本值乘以32767,限制范围后取整,才能得到正确的Int16音频数据。添加音频上下文激活逻辑:
现代浏览器要求AudioContext必须通过用户交互(如点击)激活,否则处于suspended状态无法处理音频,因此添加了context.resume()的判断。修复参数描述:
原参数描述不符合规范,若无需自定义参数,直接返回空数组即可。
内容的提问来源于stack exchange,提问作者Feroz Siddiqui
相关产品推荐
相关产品推荐

