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

HTML/JS中屏幕共享+系统音频时本地麦克风无法协同工作问题

屏幕共享音频与麦克风无法协同工作的问题分析与解决

问题描述

我们尝试实现屏幕音频共享,但在共享屏幕时,麦克风与屏幕共享音频无法协同工作:开启系统音频后麦克风失效,开启麦克风后系统音频无法正常工作。

现有实现代码

function startScreenShare() {
        if (screenSharing) {
            stopScreenSharing()
        }
        navigator.mediaDevices.getDisplayMedia(
            { video: { mediaSource: "screen" }, audio: true }
        ).then((stream) => {
            setScreenSharingStream(stream);
    
            screenStream = stream;
            let videoTrack = screenStream.getAudioTracks()[0];
            videoTrack.onended = () => {
                stopScreenSharing()
            }
            if (peer) {
                let sender = currentPeer.peerConnection.getSenders().find(function (s) {
                    return s.track.kind == videoTrack.kind;
                })
                sender.replaceTrack(videoTrack)
                screenSharing = true
            }
            console.log(screenStream)
        })
    }

问题根源

你的代码逻辑是替换了已有的音频Sender轨道:当开启屏幕共享时,会找到PeerConnection中所有音频类型的Sender,并用屏幕共享的音频轨道替换它。这就导致原本传输麦克风音频的Sender被覆盖,麦克风自然失效;反之如果先开麦克风,再开屏幕共享,麦克风的音频轨道会被替换成屏幕音频,系统音频正常但麦克风无法工作。

WebRTC的PeerConnection允许同时传输多路媒体轨道,你不需要替换已有轨道,而是应该添加新的音频Sender来传输屏幕共享音频。

修复方案

修改startScreenShare函数,添加新的音频Sender而非替换原有麦克风轨道:

function startScreenShare() {
    if (screenSharing) {
        stopScreenSharing()
    }
    navigator.mediaDevices.getDisplayMedia(
        { video: { mediaSource: "screen" }, audio: true }
    ).then((stream) => {
        setScreenSharingStream(stream);

        screenStream = stream;
        const screenAudioTrack = screenStream.getAudioTracks()[0];
        screenAudioTrack.onended = () => stopScreenSharing();

        if (peer && currentPeer) {
            // 添加新的屏幕音频Sender,保留原麦克风音频Sender
            currentPeer.peerConnection.addTrack(screenAudioTrack, screenStream);
            screenSharing = true;
        }
        console.log(screenStream);
    })
}

同时更新stopScreenSharing函数,移除屏幕音频Sender并释放资源:

function stopScreenSharing() {
    if (!screenStream) return;

    // 停止所有屏幕共享轨道
    screenStream.getTracks().forEach(track => track.stop());
    
    // 移除屏幕音频Sender
    if (currentPeer) {
        currentPeer.peerConnection.getSenders().forEach(sender => {
            if (sender.track?.kind === 'audio' && sender.track?.label.includes('screen')) {
                currentPeer.peerConnection.removeTrack(sender);
            }
        });
    }

    screenSharing = false;
    setScreenSharingStream(null);
}

额外说明

接收端需要区分麦克风音频和屏幕共享音频轨道,可以通过轨道的label属性(通常屏幕音频标签会包含"screen"相关字样)或者媒体来源信息来识别,分别处理播放逻辑。

内容的提问来源于stack exchange,提问作者raj codonnier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:52:37