跨设备摄像头串流连不上的 7 类真实原因——iOS Safari 权限、WebRTC NAT 穿透、HTTPS 强制、微信浏览器限制全排查

· 约 5 分钟 📹 跨设备摄像头串流

把手机当 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 / Edge80+
Firefox75+
安卓 WebViewChrome 内核 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:

  1. PC 端打开本工具拿 ID
  2. iPhone 扫码推流,选 high 档(1080p)
  3. OBS 添加”浏览器源”指向本工具 PC 端页面
  4. OBS 推流到斗鱼 / B 站 / 视频会议

比专业 App(Camo / EpocCam)省钱——免费且不限分辨率。

场景 2:远程协助看现场

家里电器坏了想问朋友怎么修:

  1. 朋友 PC 打开本工具发链接给你
  2. 你手机扫码后摄像头对着电器
  3. 朋友看到现场画面 + 微信语音指挥

比微信视频好的点:可截图保存、可拖窗口放大、不占微信通话独占性。

场景 3:双屏录课

讲课时希望同时录手部演示(手机后摄拍纸笔)+ 屏幕(PC 屏录):

  1. PC 用屏录软件(OBS)抓屏
  2. PC 再开本工具拿手机推流
  3. 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%。

❓ 常见问题

PeerJS 已经连上但画面不出来,哪里出问题?

先看是哪一端没画面:(1) PC 端看不见手机画面——手机的 video track 没发出来。常见:iOS Safari 没给摄像头权限(地址栏左侧锁图标里勾上摄像头)、用了微信/微博/QQ 内置浏览器(getUserMedia 被禁,必须用系统 Safari/Chrome)、HTTP 站点(getUserMedia 在非 localhost 的 HTTP 下 mediaDevices 直接是 undefined)。(2) 手机端看不见 PC 画面——本工具是单向传输(手机推流给 PC),PC 是接收端不会回传,正常现象。快速定位:手机这一侧点"开始推流"按钮后,本地的预览视频框应该立刻出画面——如果连本地预览都没有,就是 getUserMedia 问题;本地预览有但 PC 没收到,是 WebRTC 连接问题。

两端都连上了,但显示"已连接"几秒后又断,反复连不稳,怎么办?

3 类不稳因素:(1) 跨运营商或严格 NAT——本工具只配置了 Google STUN 服务器(stun:stun.l.google.com:19302),没有 TURN 中继。如果两端各在不同运营商(电信 ↔ 移动)或一端是 4G/5G 移动网络,对称 NAT 概率高,无 TURN 时打不通最稳的环境:两端连同一个 WiFi。(2) iOS 后台冻结——手机锁屏或切走 App 5-10 秒后 iOS Safari 会冻结摄像头,回前台要让 video 重新 play。保持手机亮屏 + 本页常驻。(3) 质量太高超出网络带宽——选了"ultra"(4K @ 12Mbps)但 WiFi 信号弱,丢包严重连接重置。降到 high(1080p @ 5Mbps)或 med(720p @ 2.5Mbps)

为什么我在微信里点这个链接打不开摄像头?必须用 Safari/Chrome 吗?

是的。微信、QQ、微博、抖音、钉钉、Slack 等 App 的内置 WebView 都对 getUserMedia / WebRTC 做了限制——有的禁用,有的只允许特定域名,有的允许但不稳定。本工具会自动检测:UA 里识别到微信/微博就直接弹错误提示"请右上角 ··· → 在浏览器中打开"。iOS 上:点 ··· → 在 Safari 中打开。Android 上:点右上角菜单 → 在浏览器中打开(默认浏览器最好是 Chrome / Edge / Firefox,不要选自带的 X5 内核浏览器,部分老版本同样阉割 WebRTC)。

前后摄像头切换 / 1080p / 4K 不生效,是设备不支持吗?

两种可能:(1) 设备真不支持——facingMode: { ideal: ... } 是建议而非强制,iOS Safari 在 1080p / 4K 上对不同机型支持度差很多(iPhone 13 以上的后摄基本支持 4K,前摄到 1080p;老 iPhone 前摄可能只到 720p)。控制台看 applyConstraints failed 日志确认。(2) API 兼容性问题——applyConstraints 在某些 Android Chrome 旧版上不支持运行时切换分辨率,需要 stop 后重新 getUserMedia。本工具的"切换前后摄"按钮就是走这个路径(重新拉流);切画质则是用 applyConstraints 不重连,失败时降到 high 档(1080p)通常都能成。

画面延迟很高(>500ms)或一卡一卡,是工具问题吗?

WebRTC 本身的目标延迟是 < 200ms——超过这个数多半是网络问题。(1) 两端不在同一 WiFi——跨网穿透延迟天然 100-300ms,差网络下更高。改连同一 WiFi 后延迟通常降到 50-100ms。(2) WiFi 拥塞——同一路由器下连了 20+ 设备 / 邻居用同频段,5GHz WiFi 比 2.4GHz 稳很多。(3) 质量档太高——4K @ 30fps 单向 12Mbps,普通家庭 WiFi 上行不一定撑得住。先降到 med 试试,画质够用就别上 ultra。(4) CPU 编码慢——老手机编码 1080p 都吃力,发烫降频后帧率掉到 10fps。手机别戴厚壳、别边充电边推流。

数据真的不经过你们的服务器吗?信令和 STUN 是怎么回事?

画面数据 100% P2P 直连,不经我们服务器。但 WebRTC 建连过程需要"信令"——两端要先交换 SDP(描述要传什么 codec、什么分辨率)和 ICE candidate(自己有哪些可达 IP 端口)。本工具用的是 PeerJS 官方公共信令服务器(默认配置),扫码后 ID 在那里登记 + 中转 SDP/ICE。两个不同性质:(1) 信令服务器只看到"哪两个 ID 想通话",看不到画面——画面字节流走 P2P。(2) STUN 服务器 stun.l.google.com:19302 只做"问我外网 IP 是多少",不转数据。真隐私要求高时:自建 PeerJS Server 替换 PEER_OPTS——但本静态工具未提供此入口,要改源码。

📹 打开 跨设备摄像头串流 扫码即连·WebRTC P2P 直传摄像头画面·手机↔手机 / 手机↔PC 任意组合·同 WiFi 体验最佳