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

WebRTC视频会议应用:屏幕共享后麦克风开关按钮失效问题

WebRTC视频会议麦克风按钮异常修复方案

问题原因

停止屏幕共享后麦克风按钮报错Cannot read properties of undefined (reading 'enabled'),核心原因有两点:

  1. 停止共享时创建了局部localStream变量,未更新全局变量,导致流状态不一致
  2. 麦克风按钮逻辑未判断音频轨道是否存在,遇到轨道缺失时直接读取enabled引发报错

修复代码及步骤

1. 新增全局变量保存原摄像头轨道

在全局变量声明处添加,用于复用原摄像头流,避免重复获取媒体权限:

let screenStream = null;
let localStream = null;
let audioTrack = null;
let pc = null;
let originalVideoTrack = null; // 保存原摄像头轨道,避免重复调用getUserMedia

2. 修复屏幕共享切换逻辑

修改屏幕共享按钮事件,优先复用原localStream,更新全局变量并同步PeerConnection的音频轨道:

// Toggle screen sharing on/off
document.getElementById("share-screen-btn").addEventListener("click", async () => {
    try {
        const localVideo = document.getElementById("localVideo");
        const displayMediaOptions = {
            video: true,
            audio: true,
        };
        if (!screenStream) {
            screenStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
            const videoTracks = screenStream.getVideoTracks();
            // 保存原摄像头轨道
            if (localStream) {
                originalVideoTrack = localStream.getVideoTracks()[0];
            }
            await pc.getSenders().find(sender => sender.track.kind === 'video').replaceTrack(videoTracks[0], videoTracks[0].clone());
            localVideo.srcObject = screenStream;
            document.getElementById("share-screen-btn").classList.remove("btn-danger");
            document.getElementById("share-screen-btn").classList.add("btn-primary");

            // 禁用原本地流音频
            if (localStream) {
                audioTrack = localStream.getAudioTracks()[0];
                audioTrack.enabled = false;
            }
        } else {
            // 优先复用原localStream,无需重新获取媒体流
            if (localStream && originalVideoTrack) {
                const videoSender = pc.getSenders().find(sender => sender.track.kind === 'video');
                await videoSender.replaceTrack(originalVideoTrack);
                // 恢复原音频轨道
                if (audioTrack) {
                    audioTrack.enabled = true;
                }
                localVideo.srcObject = localStream;
            } else {
                // 兼容原逻辑,处理原localStream不存在的情况
                const localVideoStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
                const videoSender = pc.getSenders().find(sender => sender.track.kind === 'video');
                const localVideoTrack = localVideoStream.getVideoTracks()[0];
                const localAudioTrack = localVideoStream.getAudioTracks()[0];
                // 更新全局localStream,而非创建局部变量
                localStream = new MediaStream([localVideoTrack, localAudioTrack]);
                // 同步更新PeerConnection的音频轨道
                const audioSender = pc.getSenders().find(sender => sender.track.kind === 'audio');
                if (audioSender && localAudioTrack) {
                    await audioSender.replaceTrack(localAudioTrack);
                }
                await videoSender.replaceTrack(localVideoTrack);
                localVideo.srcObject = localStream;
                audioTrack = localAudioTrack;
            }
            document.getElementById("share-screen-btn").classList.remove("btn-primary");
            document.getElementById("share-screen-btn").classList.add("btn-danger");
            screenStream.getTracks().forEach(track => track.stop());
            screenStream = null;
        }
    } catch (e) {
        console.error("Error sharing screen: ", e);
    }
})

3. 修复麦克风按钮逻辑

添加音频轨道存在性判断,避免undefined报错:

// Toggle microphone on/off
document.getElementById("mute-audio-btn").addEventListener("click", () => {
    let localStream = document.getElementById("localVideo").srcObject;
    if (localStream) {
        let audioTrack = localStream.getAudioTracks()[0];
        // 新增判断:音频轨道不存在时直接返回
        if (!audioTrack) return;
        let enabled = audioTrack.enabled;
        if (enabled) {
            audioTrack.enabled = false;
            document.getElementById("mute-audio-btn").innerHTML = '<i class="fa-solid fa-microphone-slash"></i>'
        } else {
            audioTrack.enabled = true;
            document.getElementById("mute-audio-btn").innerHTML = '<i class="fa-solid fa-microphone"></i>'
        }
    }
})

关键修复说明

  • 复用原localStream减少重复调用getUserMedia,避免权限冲突和轨道缺失问题
  • 更新全局localStream保证流状态一致性
  • 同步PeerConnection的音频轨道,确保远端能接收音频状态变化
  • 麦克风按钮添加轨道存在性判断,从根源避免undefined报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:12:20