需安装live server扩展并搭配https服务(如mkcert生成证书+node.js/webpack-dev-server配置),或改用支持localhost的serve工具;webrtc调试还需手动实现信令交换、正确配置iceservers及在用户手势后创建rtcpeerconnection实例。

需要装哪些扩展和依赖,而不是只装个 Live Server
VSCode 本身不提供 WebRTC 运行时能力,Live Server 扩展起的 HTTP 服务默认用 http:// 协议,而现代浏览器(Chrome 120+、Firefox 125+)强制要求 getUserMedia、RTCPeerConnection 等 API 必须在 https:// 或 localhost 下运行——所以直接开 Live Server 是能跑 HTML,但调用摄像头/麦克风会静默失败,控制台连错误都不抛。
必须满足以下任一条件:
-
localhost域名(端口任意),且文件由本地 HTTP 服务托管(不是双击打开file://) - HTTPS 服务(需证书,开发阶段不推荐)
- 使用
web-dev-server或webpack-dev-server并启用https: true
推荐做法:用 Node.js 起一个最小化 HTTPS 服务,或改用支持 localhost 的轻量工具。例如安装 serve:
npm install -g serve然后在项目根目录执行:
serve -s . -p 8080访问
http://localhost:8080 即可安全调用 getUserMedia。
调试 WebRTC 连接时,为什么 RTCPeerConnection 一直卡在 connecting
这是最常被忽略的环节:WebRTC 不是“开箱即用”的通信协议,它需要信令服务器(signaling server)交换 SDP 和 ICE 候选者。VSCode 只是编辑器,不参与这个过程,但你写的 JS 代码如果没处理好信令流程,RTCPeerConnection 就永远等不到远端 offer/answer,状态就卡在 connecting 或 checking。
快速验证是否是信令问题:
- 打开两个浏览器标签页,都访问同一页面(如
http://localhost:8080) - 在第一个标签页点“创建 Offer”,复制控制台输出的
offerSDP 字符串 - 在第二个标签页点“设置 Remote Description”,粘贴该字符串
- 再在第二个标签页点“创建 Answer”,复制 answer 字符串
- 回到第一个标签页点“设置 Remote Description”,粘贴 answer
如果此时连接成功(iceConnectionState 变为 connected),说明你的 RTCPeerConnection 配置没问题,问题出在信令通道(比如 WebSocket 连接失败、JSON 解析错位、事件监听漏绑定)。
constraints 设错导致 getUserMedia 拒绝或黑屏
常见错误是写成:
navigator.mediaDevices.getUserMedia({ video: true, audio: true })看似没问题,但在某些笔记本/虚拟机上,系统可能默认禁用麦克风或没有物理摄像头,这时 Promise 会 reject,但很多人没加 .catch,导致静默失败。
更稳妥的写法是显式声明约束并处理 fallback:
- 优先尝试高清视频:
{ video: { width: { ideal: 1280 }, height: { ideal: 720 } }, audio: true } - 允许降级(避免黑屏):
{ video: { facingMode: "user" }, audio: true }(移动端常用) - 捕获屏幕(仅桌面 Chrome/Firefox):
{ video: { mediaSource: "screen" } },注意需用户手动授权弹窗 - 始终加
.catch(e => console.error("getUserMedia failed:", e)),常见错误码包括:NotAllowedError(用户拒授)、NotFoundError(设备不存在)、OverconstrainedError(约束冲突)
本地测试时如何绕过 STUN/TURN,又不被 ICE 失败卡住
WebRTC 默认需要 STUN 服务器来获取公网 IP 和端口映射。如果你没配 iceServers,Chrome 会用内置的 Google STUN(stun:stun.l.google.com:19302),但国内不稳定;Firefox 则可能直接失败。
开发阶段最简方案是显式配置免费 STUN(非 TURN):
const pc = new RTCPeerConnection({
iceServers: [
{ urls: "stun:stun.l.google.com:19302" },
{ urls: "stun:stun1.l.google.com:19302" }
]
});
注意:urls 字段必须是数组,不能写成字符串;多个 STUN 地址可提高成功率;不需要配 TURN(除非要穿企业防火墙或 NAT 类型为 symmetric);如果仍看到大量 iceCandidate 为空或 iceGatheringState === "gathering" 长时间不结束,大概率是网络拦截了 UDP 19302 端口,可临时换用 HTTP-based STUN(如 stun:stun.sipnet.net)或改用 iceTransportPolicy: "relay" 强制走中继(仅调试用)。
真正容易被忽略的是:RTCPeerConnection 实例必须在用户手势(如 click)后创建,否则部分浏览器会拒绝初始化 ICE Agent——也就是说,不要在页面加载完成就 new RTCPeerConnection(),而要在按钮点击回调里做。











