常见问题排查与高级调优 (FAQ)
本章节整理了在局域网多开或公网部署云手机服务时,最常碰到的网络、触控映射及音视频积压故障,并给出了推荐的排错步骤与技术原理。
🔍 问题一:Web 页面加载成功,但提示 WebRTC 连接超时,或一直显示黑屏?
📌 可能原因:
- UDP 媒体端口未放行:WebRTC 的前期协商是通过 WebSocket 信令通道(默认 TCP 8443)传输的。即便信令连接成功,如果实际走 UDP 传输的 WebRTC 端口被封禁,依然无法获取画面。
- NAT 协商打洞失败:客户端与云手机处于对称型 NAT(Symmetric NAT)后,无法建立 P2P 直连。
🛠️ 解决方案:
- 步骤一:检查宿主机或云服务器的安全组规则,放行中转服务使用的 UDP 端口段(例如
3478与55000-55100)。 - 步骤二:若是 Docker 内运行,请在 Agent 启动命令行中显式指定宿主机的对外访问 IP 和 UDP 映射端口,以构建有效的 Candidate:bash
-external-addr "<宿主机真实公网/内网IP>" -webrtc-port 50000 - 步骤三:若为复杂对称 NAT 场景,请在一键包启动命令行中传入有效的中转服务配置
-ice-servers,强制协商走 TURN 中继服务进行流量中转。
🔍 问题二:初次触控屏幕时画面会有明显卡顿,或频繁发生丢包与马赛克风暴?
📌 原理解析:
- 在早期版本中,系统为了保证触控即时响应,设计为每次监听到鼠标点击
ACTION_DOWN时,均会瞬间向 Android 底层发送一次 PLI 物理请求,迫使编码器立即产生一个 I 帧(关键帧)。 - 冲突点:连续且高频地请求 I 帧会导致编码器瞬间产生数百 KB 的巨型数据包,直接冲垮 UDP 发送缓存并导致 MTU 溢出分包丢失。由此触发浏览器侧连续发包重传与 PLI 重请求,陷入丢包风暴。
🛠️ 解决方案:
我们已在最新版的 Agent 中完全移除了触控强刷 I 帧的落后设计。通过在 Android 底层 Surface 编码配置 KEY_REPEAT_PREVIOUS_FRAME_AFTER (100ms),当屏幕画面完全静止时,编码器仍能以 10 FPS 吐出带有连续时钟时间戳的“保活重复帧”。
- 浏览器 Jitter Buffer 维持极高活跃与低延迟。
- 点击屏幕瞬间不再爆发大包,首触响应降至毫秒级。
🔍 问题三:长时间画面静止后,首发操作引发画面回弹、跳跃或卡顿?
📌 原理解析:
一些方案为了抹平静止画面后突发的巨大 PTS 跳变,引入了跳变抑制算法(强行截断时间增量,强制将增量改为固定 10ms)。 这会导致编码器的真实墙上时钟流逝与 WebRTC 的内部时间轴脱节,从而引发 Jitter Buffer 误判并积压了长达数秒的数据。
🛠️ 解决方案:
在最新版本中,我们彻底废除了人工猜测的跳变抑制机制,直接通过硬件级时间轴(HW-PTS)透传 Android MediaCodec 产生的高精 PTS 增量。WebRTC 引擎能够完美消化大跨度的时间流逝,保证静止画面恢复后的点击瞬间渲染,画面流畅无抖动。
🔍 问题四:云手机画面投屏正常且极度丝滑,但鼠标点击、改键均无法控制?
📌 解决方案:
- 开发者选项安全控制 (真机):
- 请检查手机端是否是小米、魅族等特定国产品牌手机。
- 必须进入手机的「开发者选项」,除了开启「USB 调试」外,还必须开启 「USB 调试(安全设置 - 允许通过 USB 输入)」。否则 Android 系统会直接拦截一切外部注入的 Input 模拟事件。
- DataChannel 被阻断:
- 观察网页右上角的状态栏,确认
Control Channel(控制通道) 是否已建立并处于 Open 状态。 - 如果视频流正常但 DataChannel 异常,通常是因为局域网防火墙阻断了 SCTP 协议数据包,请更换浏览器(推荐最新版 Chrome)或检查网络安全阻拦截。
- 观察网页右上角的状态栏,确认
🔍 问题五:音视频延迟落后画面严重,或者声音播放变慢、沙哑失真?
📌 解决方案:
早期我们直接使用 Android 的原始音频 PTS 作为 RTP 发送间隔,但受限于 Android Playback 播放捕获策略,音频采样时钟容易产生漂移,导致浏览器中声音播放变调、失真或缓慢。
- 我们已重构音频同步机制:在 Agent 发送端,废弃 Android 提供的采集 PTS。每次收到采集的 Opus 包时,直接通过解析 Opus TOC 帧头 获取包内的物理 Duration 增量,并累加到墙上时钟上进行 RTP 封包发送。
- 完美修复了声音延迟积压以及变调失真,实现了全链路音视频高精同步。