把手机当 PC 的摄像头用、把 PC 屏录的画面分享到手机看、远程协助时让对方手机拍现场——跨设备摄像头串流是这类需求的统一解法。
本工具基于 WebRTC P2P + PeerJS 信令,扫码即连,画面字节流不经服务器。但 WebRTC 涉及的环节比想象中多——HTTPS 限制、摄像头权限、NAT 穿透、编码协商、网络带宽——任何一环卡住整个链路就断。
这篇按”扫码 → 建连 → 拿摄像头 → 画质调整 → 保持稳定”五个阶段,拆开每一步的失败点和修复路径。
WebRTC 串流的完整链路
[手机端] [信令服务器] [PC 端]
│ │ │
│ │ ① 注册接收端 ID │
│ │◀──────────────────────│
│ │ │
│ ② 扫码拿 ID │ │
│─────────────────────────▶│ │
│ │ │
│ ③ 交换 SDP + ICE │ │
│◀────────────────────────▶│◀─────────────────────▶│
│ │ │
│ ④ STUN: 问外网 IP │ │
│─────────────▶ [Google STUN] ◀───────────────────│
│ │
│ ⑤ 画面字节流 P2P 直传(理想路径) │
│═════════════════════════════════════════════════▶│
│ │
│ ⑤' 跨 NAT 失败时本应走 TURN 中继(本工具未配置) │
│ ✗ NAT 严格时直接连不通 │
关键点:
- ① ② ③ 走信令服务器(PeerJS 官方)—— 只传协商信息,不传画面
- ④ STUN 解决”我外网 IP 是什么”—— 一次性查询
- ⑤ 画面字节流 100% P2P—— 真不经服务器
- ⑤’ 本工具不提供 TURN—— 严格 NAT 直接失败,必须改网络环境
7 类失败原因对照
1. HTTPS 强制(最常被忽略)
iOS Safari / Chrome / Firefox 都把 getUserMedia 限制在 HTTPS 或 localhost:
navigator.mediaDevices === undefined // HTTP 站点直接 undefined
症状:本地预览都没出来,控制台报 “Cannot read properties of undefined”。
修复:
- 用本工具的公网 HTTPS 地址(默认就是 https://)
- 自部署一定要装证书(Let’s Encrypt 免费)
- 内网调试用 localhost / 127.0.0.1 不要用 IP 地址
2. 微信 / QQ / 微博内置浏览器
这类内嵌 WebView 出于安全策略禁用或限制 getUserMedia:
| App | 摄像头 | 处理 |
|---|---|---|
| 微信 X5 | 禁用 | 右上角 ··· → 在 Safari/系统浏览器中打开 |
| 微博 | 禁用 | 同上 |
| QQ 内嵌 | 部分禁用 | 同上 |
| 钉钉 | 限制 | 用钉钉视频会议(非这类工具) |
| Slack 桌面 | 允许(基于 Chromium) | 通常 OK |
本工具会自动识别 UA 并弹错误提示。
3. iOS Safari 摄像头权限
首次点"开始推流" → 弹"允许使用摄像头吗"
├─ 允许 → 拿到 stream
├─ 拒绝 → 报错,但下次还会弹
└─ 不允许(永久)→ 再也不弹,永远报错
永久拒绝后的恢复:
- iOS:设置 → Safari → 网站 → 摄像头 → 找到本站改”允许”
- Mac Safari:偏好设置 → 网站 → 摄像头 → 改”允许”
- Chrome:地址栏左侧锁图标 → 摄像头 → 允许
4. NAT 穿透失败(无 TURN 兜底)
WebRTC 的 NAT 类型穿透矩阵:
| 双方 NAT 类型 | 直连成功率 |
|---|---|
| Full Cone + 任意 | ≥ 95% |
| Restricted Cone + Restricted Cone | ~ 80% |
| Port Restricted + Port Restricted | ~ 50% |
| 对称 NAT 一方 | ~ 20% |
| 双方都对称 NAT | 几乎 0% |
家庭路由器 90% 是 Full Cone 或 Restricted Cone—— 同一 WiFi 下基本都能连。
移动网络(4G/5G)90% 是对称 NAT—— 跨 4G 失败率极高。
结论:
- 两端连同一 WiFi——成功率 ≥ 95%
- 跨家庭网络(不同运营商)——成功率 ≤ 50%
- 一端走移动网络——失败率高
真要跨网用:自建 TURN 服务器(coturn 开源),修改本工具源码的 PEER_OPTS 添加 turn URL。
5. 浏览器不支持 / 版本太老
本工具用 PeerJS + WebRTC + getUserMedia + applyConstraints,最低要求:
| 浏览器 | 最低版本 |
|---|---|
| Safari (iOS / macOS) | 14.1+ |
| Chrome / Edge | 80+ |
| Firefox | 75+ |
| 安卓 WebView | Chrome 内核 80+ |
iOS Safari 14 以下 getUserMedia 体验明显差(不稳、不支持 applyConstraints 切换分辨率)—— 升级到 iOS 15+ 再用。
6. 高画质超出网络带宽
ultra: 3840×2160 @ 30fps @ 12 Mbps
high: 1920×1080 @ 30fps @ 5 Mbps
med: 1280×720 @ 30fps @ 2.5 Mbps
low: 854×480 @ 24fps @ 0.8 Mbps
家庭 WiFi 上行带宽典型值:
- 千兆光纤上行 50-100Mbps —— 可推 ultra
- 百兆光纤上行 30Mbps —— 可推 high
- 移动网络 4G —— 不稳定,用 med 或 low
切档失败的兜底:本工具的”切画质”按钮用 applyConstraints 不重连,失败时降到 high 通常都能成;如果 ultra 始终失败说明设备不支持 4K。
7. iOS 后台冻结
iOS Safari 切到后台或锁屏 5-10 秒后强制冻结摄像头——不是工具 bug,是系统行为。
保持串流稳定:
- 手机保持亮屏(设置自动锁屏更长)
- 不要切到其它 App
- 用充电器供电(防止省电模式触发冻结)
回前台自动恢复:本工具监听 visibilitychange 让 video 重新 play,但远端可能要 2-3 秒才能恢复画面。
画质档与码率的选择策略
| 场景 | 推荐档位 | 理由 |
|---|---|---|
| 远程协助拍现场 | med (720p) | 看清就行,延迟低 |
| 替代笔记本摄像头开会 | high (1080p) | 主流视频会议都用 1080p |
| 录制教程 / 演示 | high 或 ultra | 看高清细节 |
| 移动网络(4G)下 | low (480p) | 防止丢包断连 |
| 同一 WiFi 千兆 + 新机型 | ultra (4K) | 体验最佳 |
避免误区:画质 ≠ 越高越好。1080p 在小屏看和 4K 区别不大,但 12Mbps 编码对老手机 CPU 是负担——发烫降频后实际帧率反而掉到 10fps。
实战场景
场景 1:手机当电脑摄像头(直播 / 视频会议)
iPhone 后摄拍出来的画质远超笔记本前摄。配合 OBS Studio:
- PC 端打开本工具拿 ID
- iPhone 扫码推流,选 high 档(1080p)
- OBS 添加”浏览器源”指向本工具 PC 端页面
- OBS 推流到斗鱼 / B 站 / 视频会议
比专业 App(Camo / EpocCam)省钱——免费且不限分辨率。
场景 2:远程协助看现场
家里电器坏了想问朋友怎么修:
- 朋友 PC 打开本工具发链接给你
- 你手机扫码后摄像头对着电器
- 朋友看到现场画面 + 微信语音指挥
比微信视频好的点:可截图保存、可拖窗口放大、不占微信通话独占性。
场景 3:双屏录课
讲课时希望同时录手部演示(手机后摄拍纸笔)+ 屏幕(PC 屏录):
- PC 用屏录软件(OBS)抓屏
- PC 再开本工具拿手机推流
- OBS 把两路画面合成(手机拍手部 + 屏幕拍 PPT)
默认不做的事
- 不做服务器中转——画面字节流 100% P2P,工具方看不到画面
- 不提供 TURN 服务器——跨严格 NAT 失败时无兜底,要求同 WiFi
- 不支持多端同时接收——本工具是 1 推 1 收,多端要分别开页面
- 不录制画面——只做实时串流,要录画面用 PC 端的 OBS / 系统屏录
- 不调整曝光 / 焦距等专业参数——getUserMedia 标准只暴露分辨率、帧率、前后摄
如果你只是要在两台设备之间共享文件(不是实时画面),用本站的 [[archive-extract]] / [[base64-file]] 等离线工具;要把视频压一压再传,用 [[video-compress]];要把手机录的视频提取音频,用 [[video-audio-extract]]。phone-cam 专攻”扫码即连的实时画面”——理解上面 7 类失败原因,跑通率从 30% 提到 90%。