如何在WebRTC中识别媒体流类型?能否通过SDP添加自定义信息?
区分摄像头流与屏幕共享流的方案
一、可以在SDP中添加自定义标识
当然可以通过修改发送端的SDP来注入额外信息,以此区分流类型,具体实现步骤如下:
- 创建Offer后,遍历SDP的媒体描述行(以
m=开头的行),定位到目标视频轨道对应的媒体段
- 创建Offer后,遍历SDP的媒体描述行(以
- 为该媒体段添加自定义属性行,比如用
a=stream-type:screen标记屏幕共享流,a=stream-type:camera标记摄像头流
- 为该媒体段添加自定义属性行,比如用
- 将修改后的SDP重新赋值给Offer,再设置到本地会话并发送给接收端
- 接收端解析SDP时,读取对应的自定义属性即可完成流类型区分
示例代码:
// 发送端修改SDP pc.createOffer().then(offer => { // 先判断当前视频轨道是否为屏幕共享流(可通过track的label或获取流的方式判断) const isScreenShare = pc.getSenders().some(sender => sender.track?.kind === 'video' && sender.track.label.includes('screen') ); // 替换SDP,添加自定义标识 offer.sdp = offer.sdp.replace( /m=video.*\r\n/, match => match + `${isScreenShare ? 'a=stream-type:screen\r\n' : 'a=stream-type:camera\r\n'}` ); return pc.setLocalDescription(offer); }).then(() => { // 发送修改后的Offer到接收端 }); // 接收端解析SDP pc.setRemoteDescription(remoteOffer).then(() => { const sdpLines = remoteOffer.sdp.split('\r\n'); let currentVideoType = ''; for (const line of sdpLines) { if (line.startsWith('a=stream-type:')) { currentVideoType = line.split(':')[1]; break; } } if (currentVideoType === 'screen') { // 处理屏幕共享流逻辑 } else { // 处理摄像头流逻辑 } });
二、为什么MediaStream的label属性未生效
MediaStream的label属性属于浏览器本地属性,不会被自动映射到SDP协议字段中,因此接收端无法通过SDP或轨道信息获取到这个值,这就是你之前尝试无效的原因。
三、更兼容的替代方案
除了修改SDP,还有两种更稳妥的方式:
- 直接标记MediaStreamTrack:在发送端为轨道添加自定义标识(注意部分浏览器可能会限制自定义属性,建议结合信令同步)
// 获取屏幕流时标记轨道 navigator.mediaDevices.getDisplayMedia({video: true}).then(stream => { const track = stream.getVideoTracks()[0]; track.streamType = 'screen'; // 添加自定义属性 pc.addTrack(track, stream); }); // 摄像头流同理 navigator.mediaDevices.getUserMedia({video: true}).then(stream => { const track = stream.getVideoTracks()[0]; track.streamType = 'camera'; pc.addTrack(track, stream); });
- 信令同步轨道类型:发送SDP的同时,通过信令单独发送轨道ID与类型的映射关系,接收端根据ID匹配类型,兼容性最好
// 发送端 pc.createOffer().then(offer => pc.setLocalDescription(offer)).then(() => { const trackInfos = pc.getSenders() .filter(sender => sender.track?.kind === 'video') .map(sender => ({ trackId: sender.track.id, type: sender.track.label.includes('screen') ? 'screen' : 'camera' })); // 通过信令发送Offer和轨道类型信息 sendSignal({ type: 'offer', sdp: pc.localDescription.sdp, trackInfos }); }); // 接收端 onSignalReceived(msg => { if (msg.type === 'offer') { pc.setRemoteDescription(new RTCSessionDescription(msg)).then(() => { pc.getReceivers().forEach(receiver => { const info = msg.trackInfos.find(item => item.trackId === receiver.track.id); if (info?.type === 'screen') { // 处理屏幕共享流 } else { // 处理摄像头流 } }); }); } });
内容的提问来源于stack exchange,提问作者Ansh saxena
相关产品推荐
相关产品推荐

