bai19940321 2024-02-03 22:07 采纳率: 9.5%
浏览 12

VUE3语音通话的一个问题

使用vue3做了一个语音通话程序。
调用AudioWorkletProcessor接口,但是他会将自己的声音也复制进音频中,这种情况应该怎么处理。

class AudioProcessor extends AudioWorkletProcessor {
  constructor() {
    super();
    this.bufferSize = 512; 
  }

  process(inputs, outputs, parameters) {
    const input = inputs[0];
    const output = outputs[0];

    for (let channel = 0; channel < input.length; ++channel) {
      const inputChannel = input[channel];
      const outputChannel = output[channel];

      for (let i = 0; i < inputChannel.length; ++i) {
        outputChannel[i] = inputChannel[i];
      }
    }

    // 将音频数据发送回主线程
    const outputData = output[0].slice(0, this.bufferSize);
    this.port.postMessage(outputData);

    return true;
  }
}

registerProcessor('audio-processor', AudioProcessor);


  • 写回答

2条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-02-03 22:09
    关注

    引自免费微信小程序:皆我百晓生

    在Vue3中,使用AudioWorkletProcessor实现语音通话时遇到回声(自己的声音被复制到音频流中)的问题,这是因为在处理音频数据时没有进行恰当的回声消除处理。为了解决这个问题,你需要引入适当的回声消除算法或者利用WebRTC提供的现成的AEC(Acoustic Echo Cancellation)功能。

    然而,在给出代码之前,请注意在浏览器环境中,直接对AudioWorkletProcessor进行回声消除可能并不简单,因为这通常涉及到复杂的信号处理技术。不过,我们可以展示如何将AEC集成到你的AudioWorkletProcessor中,但这通常需要配合Web Audio API中的其他组件来完成,并且通常不是简单的几行代码就能实现的。

    假设你决定继续在AudioWorkletProcessor内部尝试实现简易的回声抑制(非专业级的AEC),一种可能的方法是只发送未播放过的音频数据到对方,避免本地播放的声音再次进入输入流:

    class EchoCancellingAudioProcessor extends AudioWorkletProcessor {
      constructor() {
        super();
        this.bufferSize = 512;
        // 初始化历史缓冲区用于对比和抑制回声
        this.historyBuffer = new Float32Array(this.bufferSize);
      }
    
      process(inputs, outputs) {
        const input = inputs[0];
        const output = outputs[0];
    
        for (let channel = 0; channel < input.length; ++channel) {
          const inputChannel = input[channel];
          const outputChannel = output[channel];
    
          // 对比当前帧与历史缓冲区,尝试减去相似部分以抑制回声
          for (let i = 0; i < inputChannel.length; ++i) {
            // 这里仅做示例,实际回声消除算法会复杂得多
            // 简单地假定前一帧的数据就是回声(实际上应考虑延迟和衰减)
            let echoSample = this.historyBuffer[i];
            outputChannel[i] = inputChannel[i] - echoSample;
    
            // 更新历史缓冲区以便下一帧比较
            this.historyBuffer[i] = inputChannel[i];
          }
        }
    
        // 发送处理后的输出数据(假设已无明显回声)
        // 实际上,此处可能需要更精确的设计,例如仅发送对方语音
        const outputData = output[0].slice(0, this.bufferSize);
        // 这里仅作为演示,实际应用中可能不直接通过postMessage发送音频数据
        // 而是将其传递给合适的通信模块或存储以供后续处理
        // this.port.postMessage(outputData);
    
        return true;
      }
    }
    
    registerProcessor('echo-cancelling-audio-processor', EchoCancellingAudioProcessor);
    

    请注意:上述代码仅是一个简化的概念示例,实际应用中回声消除算法要复杂得多,并且浏览器内置的WebRTC AEC效果更好。如果你正在构建实时语音通话应用,强烈建议结合WebRTC并利用其内置的AEC特性,而非自行在AudioWorkletProcessor中实现。

    若要使用WebRTC实现,可以创建一个RTCPeerConnection对象并在其中设置相关的约束和处理函数,确保开启AEC属性:

    // 假设已经有了RTCPeerConnection实例 pc
    const constraints = {
      audio: {
        echoCancellation: true,
        autoGainControl: true,
        noiseSuppression: true,
      },
    };
    
    navigator.mediaDevices.getUserMedia(constraints)
      .then((stream) => {
        pc.addStream(stream);
      });
    

    这样,浏览器会自动处理回声消除问题,无需在AudioWorkletProcessor中手动处理。

    评论

报告相同问题?

问题事件

  • 创建了问题 2月3日