You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过单个WebRTC对等端用JS实现单流传输双音频轨道?

实现单个媒体流传输麦克风与音频文件音频的两种方案

方案1:将两个独立音频轨道加入同一个MediaStream

这种方式会在流中保留两个独立的音频轨道,接收端可分别处理或播放各自的音频内容。

实现步骤

  • 获取麦克风的音频轨道
  • 加载音频文件并捕获其音频轨道
  • 将两个轨道添加至同一个MediaStream

代码示例

// 获取麦克风音频轨道
async function getMicTrack() {
  const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });
  return micStream.getAudioTracks()[0];
}

// 加载音频文件并获取其轨道
async function getAudioFileTrack(filePath) {
  const audio = new Audio(filePath);
  audio.crossOrigin = "anonymous"; // 处理跨域,同域名可省略
  await audio.play(); // 需用户交互触发,规避浏览器自动播放限制
  const fileStream = audio.captureStream();
  return fileStream.getAudioTracks()[0];
}

// 合并轨道到单个MediaStream
async function createCombinedStream(micTrack, fileTrack) {
  const combinedStream = new MediaStream();
  combinedStream.addTrack(micTrack);
  combinedStream.addTrack(fileTrack);
  return combinedStream;
}

// 使用示例
(async () => {
  try {
    const micTrack = await getMicTrack();
    const fileTrack = await getAudioFileTrack("./audio-file.mp3");
    const combinedStream = await createCombinedStream(micTrack, fileTrack);
    
    // 此时combinedStream包含两个音频轨道,可用于WebRTC传输或录制
    console.log("合并后的轨道数量:", combinedStream.getAudioTracks().length);
  } catch (err) {
    console.error("出错:", err);
  }
})();

注意事项

  • 音频文件需处理CORS问题,若文件与页面同域名可省略crossOrigin设置
  • 浏览器存在自动播放限制,必须在用户交互(如按钮点击)中触发音频播放
  • 停止传输时需调用track.stop()释放麦克风和文件轨道资源

方案2:混合两个音频为单个轨道传输

如果接收端不需要区分两个音频源,可通过Web Audio API将麦克风与音频文件的音频混合为单个轨道,再通过媒体流传输。

实现步骤

  • 初始化AudioContext
  • 创建麦克风和音频文件的音频源节点
  • 混合两个音频源并输出到MediaStreamDestination
  • 获取混合后的轨道并生成MediaStream

代码示例

async function createMixedAudioStream(micStream, audioFile) {
  const audioContext = new AudioContext();
  
  // 创建麦克风源节点
  const micSource = audioContext.createMediaStreamSource(micStream);
  
  // 创建音频文件源节点
  const fileSource = audioContext.createMediaElementSource(audioFile);
  
  // 可选:调整音量避免混合后失真
  const micGain = audioContext.createGain();
  micGain.gain.value = 0.7;
  const fileGain = audioContext.createGain();
  fileGain.gain.value = 0.5;
  
  // 创建用于捕获混合音频的目标节点
  const destination = audioContext.createMediaStreamDestination();
  
  // 连接音频链路
  micSource.connect(micGain).connect(destination);
  fileSource.connect(fileGain).connect(destination);
  
  // 启动音频文件播放(需用户交互触发)
  audioFile.play();
  
  // 返回包含混合音频的MediaStream
  return destination.stream;
}

// 使用示例
(async () => {
  try {
    // 获取麦克风流
    const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });
    
    // 加载音频文件
    const audioFile = new Audio("./audio-file.mp3");
    audioFile.crossOrigin = "anonymous";
    
    // 创建混合流
    const mixedStream = await createMixedAudioStream(micStream, audioFile);
    
    // mixedStream仅包含一个混合后的音频轨道
    console.log("混合后的轨道数量:", mixedStream.getAudioTracks().length);
    
    // 可用于WebRTC传输或本地录制
  } catch (err) {
    console.error("出错:", err);
  }
})();

注意事项

  • AudioContext需在用户交互事件中初始化,规避浏览器安全限制
  • 需根据实际情况调整增益值,防止音频混合后音量过高导致失真
  • 停止传输时需关闭AudioContext并调用track.stop()释放所有资源

内容的提问来源于stack exchange,提问作者Davi Costa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 18:48:38