Workerman本身不直接支持读取USB摄像头或调用getUserMedia,因其是服务端PHP框架,硬件访问必须由前端浏览器通过WebRTC(getUserMedia+RTCPeerConnection)完成;Workerman仅承担信令交换(wss WebSocket)或UDP中继RTP流职责,严禁混淆前后端责任边界。

Workerman 本身**不直接支持读取本地 USB 摄像头或调用 getUserMedia**——它是一个服务端 PHP 框架,运行在服务器上,而硬件摄像头只存在于客户端(浏览器或本地设备)。所以“对接硬件摄像头”这个动作,必须拆解为:**前端采集 + 信令协调 + Workerman 转发/中继**。直接让 Workerman 打开摄像头是行不通的。
下面分三块说清楚怎么做、为什么这么设计、以及最容易卡住的地方。
前端必须用 WebRTC 采集视频流,不能绕过浏览器安全限制
浏览器强制要求:调用 getUserMedia 获取摄像头权限,必须在 HTTPS 环境下进行;HTTP 协议下会静默拒绝,控制台报错 NotAllowedError: Permission denied。
- 开发调试时可用
localhost(即使 HTTP)临时绕过,但部署到域名必须配 HTTPS 证书(哪怕自签名) -
getUserMedia返回的是MediaStream,不是原始帧数据;要传给远端,必须走RTCPeerConnection建立 P2P 连接,或通过RTCDataChannel发送编码后数据 - Workerman 不参与这一层采集,它只负责信令交换或中继已编码的媒体包(如 UDP/RTP)
Workerman 做信令服务器(Signaling Server)时,关键配置是 wss + SSL 上下文
WebRTC 的 Offer/Answer/ICE Candidate 必须通过信令通道交换,Workerman 可以用 websocket 或 wss 协议实现该服务,但生产环境必须用 wss(WebSocket over TLS)。
-
$SIGNALING_ADDRESS必须是wss://your-domain.com:8877格式,不能写ws:// -
ssl上下文中的local_cert和local_pk必须是绝对路径,且文件需有 PHP 进程读取权限(常见坑:Permission denied错误) - 若用自签名证书,
verify_peer和allow_self_signed都得设为true,否则浏览器连接会失败并静默断开 - 不要在
onMessage里做耗时操作(比如写文件、查数据库),否则阻塞整个事件循环,导致信令延迟甚至丢包
如果真要转发原始视频流(非 P2P),得走 UDP + 编码中继,不是靠 WebSocket
WebRTC 默认倾向 P2P,但内网穿透失败或需要服务端混流/录制时,就得让视频流经过 Workerman。这时不能走 websocket,因为 WebSocket 是基于 TCP 的,不适合实时音视频(高延迟、重传抖动大)。
- 必须启用
udp://0.0.0.0:1234这类 UDP Worker,接收 H.264 编码后的 RTP 包或裸 NALU - 客户端需自行完成采集 → 编码(如使用
ffmpeg.wasm或 native app)→ 封装 → UDP 发送,Workerman 只做无状态广播或单播转发 - UDP 没有连接概念,
onMessage回调里的$connection是UdpConnection实例,不支持$connection->send()给特定客户端(除非你手动记录 client 地址+端口) - 防火墙、NAT、运营商限 UDP 流量是常见故障点,测试务必先用
nc -u或ffplay验证端口可达性

















