屏幕共享实现:桌面采集API、窗口选择机制、性能优化技巧
屏幕共享,说白了就是把你的电脑桌面或者某个窗口,实时地传给对方。这个功能在远程会议、在线教育、游戏直播里太常见了。我最早接触这块是在做一款远程协作工具的时候,当时踩了不少坑,今天我把这些经验都掏出来给你。
桌面采集API:getDisplayMedia
WebRTC 里做屏幕共享,核心 API 就一个——getDisplayMedia()。它是浏览器原生提供的,专门用来捕获屏幕内容。
// 最简单的调用
const stream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: false
});
// 然后像普通视频流一样处理
const pc = new RTCPeerConnection();
stream.getTracks().forEach(track => pc.addTrack(track, stream));
嗯,这里要注意:getDisplayMedia 必须在用户手势事件(比如点击按钮)中调用,否则浏览器会拒绝。我刚开始做的时候,在页面加载时自动调用,结果死活弹不出选择窗口,后来才意识到是安全策略的限制。
窗口选择机制:用户说了算
调用 getDisplayMedia 后,浏览器会弹出一个选择对话框,让用户自己选——是整个屏幕、某个应用窗口,还是浏览器标签页。这个选择权必须交给用户,你不能在代码里强行指定。
但你可以通过 displaySurface 约束来提示浏览器优先展示哪种类型:
const constraints = {
video: {
displaySurface: "window" // 优先显示窗口列表
}
};
const stream = await navigator.mediaDevices.getDisplayMedia(constraints);
displaySurface 有三个可选值:monitor(整个屏幕)、window(应用窗口)、browser(浏览器标签页)。注意这只是提示,最终选择权还是在用户手里。
性能优化技巧:别让CPU爆炸
屏幕共享最头疼的问题就是性能。你想想看,桌面可能是个4K屏,每秒60帧,直接编码传输的话,CPU直接拉满。我遇到过用户反馈"一共享屏幕电脑就卡死",后来总结了几条优化策略。
1. 控制帧率
屏幕共享不需要60fps,15fps就够用了。除非你在共享游戏画面,否则降低帧率能大幅减少编码压力。
const constraints = {
video: {
frameRate: { ideal: 15, max: 30 }
}
};
2. 限制分辨率
采集原始分辨率然后硬编码,是最傻的做法。我建议先降分辨率再编码,比如采集1080p,编码时降到720p。
const constraints = {
video: {
width: { ideal: 1280 },
height: { ideal: 720 }
}
};
3. 动态调整码率
根据网络状况动态调整视频码率,这个在 WebRTC 里可以通过 RTCRtpSender.setParameters() 实现。
const sender = pc.getSenders().find(s => s.track.kind === 'video');
const params = sender.getParameters();
params.encodings[0].maxBitrate = 500000; // 500kbps
await sender.setParameters(params);
知识体系总览
下面这张图帮你理清屏幕共享的核心流程和优化点:
实际项目中的避坑指南
做屏幕共享,光知道 API 还不够,实战中坑特别多。我挑几个典型的说说。
- 权限问题:用户第一次拒绝后,再次调用
getDisplayMedia可能不会弹出选择框。我建议在 UI 上给用户明确的提示,引导他们手动触发。 - 停止共享检测:用户点击浏览器的"停止共享"按钮后,你需要监听
track.onended事件来做清理工作。
const track = stream.getVideoTracks()[0];
track.onended = () => {
console.log('用户停止了屏幕共享');
// 清理连接、更新UI等
};
- 多显示器场景:如果用户有多个显示器,
getDisplayMedia会让用户选择共享哪个屏幕。你可以在约束里设置displaySurface: "monitor"来提示。
getUserMedia({ audio: true }) 单独采集麦克风,然后通过 pc.addTrack 添加到同一个 PeerConnection 里。
性能对比表
不同场景下,我建议的配置参数如下:
| 场景 | 帧率 | 分辨率 | 码率 |
|---|---|---|---|
| PPT/文档共享 | 5-10 fps | 720p | 300-500 kbps |
| 代码演示 | 10-15 fps | 1080p | 500-800 kbps |
| 视频播放 | 15-24 fps | 1080p | 1-2 Mbps |
| 游戏直播 | 30 fps | 1080p 或 4K | 2-5 Mbps |
嗯,这个表是我根据实际项目经验总结的。你想想看,共享PPT时画面变化很少,5fps就够;但游戏画面每帧都在变,30fps是底线。
最后说一句,屏幕共享的调试比较麻烦,因为浏览器安全策略限制,本地文件(file://)无法使用 getDisplayMedia。我建议用 localhost 或者 HTTPS 来开发测试。好了,这一章就到这里,下一章我们聊聊更进阶的话题。