如何将getDisplayMedia与getUserMedia获取的两路媒体流合并为一路
两路媒体流合并方案
核心合并逻辑分为两种场景,可根据你的使用需求选择:
基础合并(直接打包轨道,无内容混合)
如果你只需要把两路流的所有音视频轨道整合到同一个MediaStream对象中,不需要做画面叠加、音频混音,直接提取所有轨道传入新的MediaStream构造函数即可:
// 先获取两路独立媒体流 const displayStream = await navigator.mediaDevices.getDisplayMedia({ audio: true, video: true }); const cameraStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }); // 合并轨道生成新流 const mixedStream = new MediaStream([ ...displayStream.getTracks(), ...cameraStream.getTracks() ]);
注意:该方案生成的流会包含2条视频轨道、2条音频轨道,如果你后续需要推流、用
MediaRecorder录制,大多数播放器/录制工具默认只会读取第一条音视频轨道,这种场景需要使用进阶混合方案。
进阶混合(生成单音轨单视频轨的标准流)
如果需要输出仅有1条视频轨、1条音频轨的标准媒体流,需要分别做画面合成和音频混音:
1. 视频画面混合(支持摄像头画面叠加到屏幕共享)
用Canvas绘制两路视频画面,再通过captureStream()获取混合后的视频轨:
const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // 初始化画布尺寸和屏幕共享分辨率一致 const displayVideo = document.createElement('video'); displayVideo.srcObject = displayStream; await displayVideo.play(); canvas.width = displayVideo.videoWidth; canvas.height = displayVideo.videoHeight; // 初始化摄像头播放元素 const cameraVideo = document.createElement('video'); cameraVideo.srcObject = cameraStream; await cameraVideo.play(); // 循环绘制混合画面 function drawFrame() { // 绘制底层屏幕共享画面 ctx.drawImage(displayVideo, 0, 0, canvas.width, canvas.height); // 绘制右下角小窗口摄像头画面,尺寸为画布1/4 const cameraWidth = canvas.width / 4; const cameraHeight = canvas.height / 4; ctx.drawImage(cameraVideo, canvas.width - cameraWidth - 20, canvas.height - cameraHeight - 20, cameraWidth, cameraHeight); requestAnimationFrame(drawFrame); } drawFrame(); // 获取混合后的视频轨 const mixedVideoTrack = canvas.captureStream().getVideoTracks()[0];
2. 音频混音
用AudioContext混合两路音频后输出混合音频轨:
const audioCtx = new AudioContext(); // 创建两路音频源 const displayAudioSource = audioCtx.createMediaStreamSource(displayStream); const cameraAudioSource = audioCtx.createMediaStreamSource(cameraStream); // 创建混音输出节点 const mixOutput = audioCtx.createMediaStreamDestination(); // 连接到混音节点 displayAudioSource.connect(mixOutput); cameraAudioSource.connect(mixOutput); // 获取混合后的音频轨 const mixedAudioTrack = mixOutput.stream.getAudioTracks()[0];
3. 生成最终单路流
const finalMixedStream = new MediaStream([mixedVideoTrack, mixedAudioTrack]);
内容的提问来源于stack exchange,提问作者Abdul in a Hellcat
相关产品推荐
相关产品推荐

