Web Audio API 如何合并本地音频与语音输入到同一MediaStream流
问题修复方案
问题根源
- 你当前的实现是将本地音频通过AudioContext渲染输出到MediaStream,再直接将麦克风的音频轨道追加到该流中。浏览器的
<audio>元素默认不会自动混合同一条MediaStream下的多条音频轨道,只会优先播放第一条轨道,因此只有本地音频的声音正常输出。 - 追加到MediaStream的外部轨道没有经过AudioContext的混音链路,也会导致部分浏览器无法识别渲染。
修复思路
把麦克风的音频输入也接入AudioContext的处理链路,和本地文件音频在AudioContext内部完成混音后,统一输出到MediaStream,再交给audio元素播放。
修正后的完整代码
HTML部分(无改动)
<input id="sourcepath" type="file" accept="audio/*" /> <audio controls id="audio-player"></audio> <button id="play" onclick="playsound()">start</button>
JS部分
async function playsound(){ // 原有本地音频处理逻辑保留 const file = $("#sourcepath").prop('files')[0]; const fileUrl = window.URL.createObjectURL(file); const fileResponse = await window.fetch(fileUrl); const AudioPlayer = document.getElementById('audio-player'); const audioContext = new AudioContext(); const fileBuffer = await fileResponse.arrayBuffer(); const audioBuffer = await audioContext.decodeAudioData(fileBuffer); const fileSource = audioContext.createBufferSource(); fileSource.buffer = audioBuffer; const streamDestination = audioContext.createMediaStreamDestination(); fileSource.connect(streamDestination); fileSource.loop = true; fileSource.start(); // 麦克风处理逻辑修改 const micStream = await navigator.mediaDevices.getUserMedia({ audio:true, video: false }); // 将麦克风流转为AudioContext的源节点 const micSource = audioContext.createMediaStreamSource(micStream); // 麦克风源也连接到输出目标,自动和本地音频混音 micSource.connect(streamDestination); // 最终流已经包含混音后的音频,直接赋值给播放器即可 const mixedStream = streamDestination.stream; AudioPlayer.srcObject = mixedStream; // 可选:如果需要单独拿到两条轨道做其他处理,可以按原有方式addTrack // for (const track of micStream.getTracks()) { // mixedStream.addTrack(track); // } }
补充说明
- 如果后续需要对麦克风音频做增益、降噪等处理,直接在micSource和streamDestination之间插入对应的AudioNode即可,不需要修改整体链路。
- 测试时注意允许页面的麦克风权限,同时避免麦克风和扬声器同开产生啸叫。
内容的提问来源于stack exchange,提问作者Arijit
相关产品推荐
相关产品推荐

