如何在添加轨道前检查WebRTC PeerConnection中是否已存在该轨道?
如何在添加轨道前检查WebRTC PeerConnection中是否已存在该轨道?
我完全懂你遇到的麻烦——每次调用getUserMedia拿到的音频轨道ID都会变,想用ID来判断有没有重复添加根本行不通,确实挺闹心的。不过咱们可以换个思路,不用不可靠的轨道ID,而是用设备唯一标识来做判断,或者直接检查PeerConnection里已有的发送轨道,这两种方法都能解决问题。
方法一:维护本地已添加设备的记录
我们可以用一个Set来存储已经添加过的音频设备ID,因为同一个麦克风/音频设备的deviceId在浏览器会话里是固定的,不会像轨道ID那样每次都变。每次获取新轨道时,先检查这个Set里有没有对应设备的ID,没有再执行添加操作。
修改后的代码示例:
// 模块或全局范围维护的Set,记录已添加的音频设备ID const addedAudioDeviceIds = new Set(); async function addAudioTracks() { const localStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true, }); localStream.getAudioTracks().forEach((track) => { const deviceId = track.getSettings().deviceId; // 检查该设备的轨道是否已添加过 if (!addedAudioDeviceIds.has(deviceId)) { mapPeerConnection.forEach((peerConnection, userId) => { peerConnection.addTrack(track, localStream); sendOffer(userId); // 触发信令流程 }); // 标记该设备已添加 addedAudioDeviceIds.add(deviceId); } }); }
方法二:直接检查PeerConnection中的已有发送轨道
如果不想维护额外的本地状态,也可以直接从PeerConnection本身获取已有的发送器(Sender),对比轨道的设备ID来判断是否重复。这种方法更直接,能实时反映PeerConnection的当前状态。
代码示例:
async function addAudioTracks() { const localStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true, }); localStream.getAudioTracks().forEach((track) => { const trackDeviceId = track.getSettings().deviceId; mapPeerConnection.forEach((peerConnection, userId) => { // 检查当前PeerConnection是否已有同设备的音频轨道 const hasDuplicateTrack = peerConnection.getSenders().some(sender => { return sender.track && sender.track.kind === 'audio' && sender.track.getSettings().deviceId === trackDeviceId; }); if (!hasDuplicateTrack) { peerConnection.addTrack(track, localStream); sendOffer(userId); } }); }); }
额外说明
- 为什么不用
track.id?因为每次调用getUserMedia生成的轨道实例都是新的,哪怕是同一个设备,轨道ID也会刷新,所以这个值完全不可靠。 deviceId是浏览器给每个媒体设备分配的唯一标识,只要用户没有清除设备权限、没有更换设备,这个值就不会变,用来做重复判断非常合适。- 如果用户需要切换音频设备,这两种方法也能正常工作——切换后新设备的
deviceId不同,会允许添加新的轨道。
备注:内容来源于stack exchange,提问作者Dash
相关产品推荐
相关产品推荐

