复杂局域网里的 WebRTC 稳定性,重点不只是 WebRTC offer/answer 怎么转发,还包括外围控制链路如何恢复。 这个场景不是 2C 通话,而是更接近医疗、养老等机构里的设备群:大量共享设备长时间在线,集中运维,现场环境可能比较嘈杂,同时还要保证一定收音距离和通话音质。 我遇到的核心问题是:长连接不一定会明确断开,有时会出现“看起来还连着,但应用消息已经不通”的状态。结果是设备页面显示在线,但呼叫事件发不到对端,超时、挂断、多人通话清理都会变得不一致。 这篇文章聚焦几个点: WebSocket 长连接假连接为什么危险 为什么只依赖客户端主动重连不够 gRPC Gateway 如何做双向控制 自动发现和主节点状态表怎么帮助恢复 呼叫超时、自动挂断、一对一挂断、多人挂断如何收敛 嘈杂环境下,音频可观测性为什么也属于稳定性的一部分 我的结论是:这不是简单的 WebSocket 换 gRPC ,而是要补齐发现、状态和恢复闭环。媒体链路仍然走 WebRTC ,Go/gRPC 更适合做控制面和状态收敛。 原文地址: https://www.lodan.me/posts/webrtc-grpc-gateway-discovery-recovery/ 想听听大家在局域网、弱网、设备长时间运行场景里,是怎么处理长连接假在线和通话状态恢复的。
复杂局域网里的 WebRTC 稳定性,重点不只是 WebRTC offer/answer 怎么转发,还包括外围控制链路如何恢复。 这个场景不是 2C 通话,而是更接近医疗、养老等机构里的设备群:大量共享设备长时间在线,集中运维,现场环境可能比较嘈杂,同时还要保证一定收音距离和通话音质。 我遇到的核心问题是:长连接不一定会明确断开,有时会出现“看起来还连着,但应用消息已经不通”的状态。结果是设备页面显示在线,但呼叫事件发不到对端,超时、挂断、多人通话清理都会变得不一致。 这篇文章聚焦几个点: WebSocket 长连接假连接为什么危险 为什么只依赖客户端主动重连不够 gRPC Gateway 如何做双向控制 自动发现和主节点状态表怎么帮助恢复 呼叫超时、自动挂断、一对一挂断、多人挂断如何收敛 嘈杂环境下,音频可观测性为什么也属于稳定性的一部分 我的结论是:这不是简单的 WebSocket 换 gRPC ,而是要补齐发现、状态和恢复闭环。媒体链路仍然走 WebRTC ,Go/gRPC 更适合做控制面和状态收敛。 原文地址: https://www.lodan.me/posts/webrtc-grpc-gateway-discovery-recovery/ 想听听大家在局域网、弱网、设备长时间运行场景里,是怎么处理长连接假在线和通话状态恢复的。
复杂局域网里的 WebRTC 稳定性,重点不只是 WebRTC offer/answer 怎么转发,还包括外围控制链路如何恢复。 这个场景不是 2C 通话,而是更接近医疗、养老等机构里的设备群:大量共享设备长时间在线,集中运维,现场环境可能比较嘈杂,同时还要保证一定收音距离和通话音质。 我遇到的核心问题是:长连接不一定会明确断开,有时会出现“看起来还连着,但应用消息已经不通”的状态。结果是设备页面显示在线,但呼叫事件发不到对端,超时、挂断、多人通话清理都会变得不一致。 这篇文章聚焦几个点: WebSocket 长连接假连接为什么危险 为什么只依赖客户端主动重连不够 gRPC Gateway 如何做双向控制 自动发现和主节点状态表怎么帮助恢复 呼叫超时、自动挂断、一对一挂断、多人挂断如何收敛 嘈杂环境下,音频可观测性为什么也属于稳定性的一部分 我的结论是:这不是简单的 WebSocket 换 gRPC ,而是要补齐发现、状态和恢复闭环。媒体链路仍然走 WebRTC ,Go/gRPC 更适合做控制面和状态收敛。 原文地址: https://www.lodan.me/posts/webrtc-grpc-gateway-discovery-recovery/ 想听听大家在局域网、弱网、设备长时间运行场景里,是怎么处理长连接假在线和通话状态恢复的。
最近把一篇旧的 Android WebRTC + Go gRPC 对接记录重新整理成了脱敏后的工程复盘。 文章地址: https://www.lodan.me/zh-cn/posts/golang-grpc-webrtc-android/ 这次重点不是讲某个 API 怎么调,而是把边界拆清楚: - Go/gRPC 信令层负责设备注册、会话控制、回调事件和 SDP/ICE 转发。 - Android 客户端负责权限、页面生命周期、本地音视频资源和 UI 状态同步。 - WebRTC PeerConnection 负责 offer/answer 、ICE candidate 、track add/remove 和连接状态。 - 排查问题时,日志至少要能串起 call id 、peer id 、signaling state 、ICE state 和 selected candidate pair 。 我现在的判断是:如果这些边界混在一起,线上问题很容易变成“看起来像网络问题”“看起来像设备问题”“看起来像 SDK 问题”。边界清楚以后,排查路径会直接很多。 想讨论一下:大家做 Android WebRTC 或 RTC Gateway 时,通常会把多少信令/状态逻辑放在客户端,多少放在本地网关或服务端?
最近整理了一篇脱敏后的实验记录:把 WebRTC 音频从 Pion `OnTrack` 收到后,解码 Opus RTP 为 PCM ,再通过 FFmpeg `arnndn` 做 RNN 降噪,先输出文件做对比验证。 文章地址: https://www.lodan.me/zh-cn/posts/server-side-webrtc-noise-reduction-pion-ffmpeg-rnn/ 我现在的判断是: - 这条链路适合先做离线验证,不适合一上来就做实时转发。 - `int16` PCM 要对应 FFmpeg `s16le`,格式边界不能含糊。 - 真正难的是延迟、CPU 、缓冲、FFmpeg 进程生命周期、丢包和音视频同步。 - 如果设备侧硬件和 WebRTC 3A 表现不可控,服务端降噪可以作为补充方向,但不能当成免费能力。 想讨论一下:大家在 WebRTC 或实时音频场景里,有没有把降噪、增益、混音这类处理放到服务端做过?最后卡住的是延迟、效果,还是资源成本?
本周主要围绕实时数字人链路的 Direct WebRTC 稳定性、AV 同步、空闲态数字人策略和语音上下文恢复展开。 fix:修复音画不同步 bug 之前版本存在一个问题,随着对话的持续进行,会逐渐出现音画不同步的情况。为了修复这个问题,这周认真啃了一下 WebRTC 协议。把这个问题搞清楚了。问题的原因比较复杂,总的来说主要是三个原因: 发送端 pacing 不稳定 turn 间 idle gap 处理错误 浏览器 receiver 状态跨 turn 残留 要搞懂这三个问题,必须先看一下 CyberVerse 是怎么发送音视频到前端的。在 cached_video 模式下,数字人说话是一轮一轮的;当数字人没有说话时,会播放提前生成的视频(所以叫 cached_video 模式)。整个视频流大概是这样: speaking -> idle -> speaking -> idle -> speaking 中间的停顿时长是不确定的,可能是几秒,也可能是几十秒。问题就出在这里:我用了同一个 Direct WebRTC media path 去承载一段一段的实时音视频,但这条 media path 的发送节奏、RTP 时间线和浏览器 receiver 状态,之前都更像是在按「连续直播流」来处理。 第一个原因是发送端 pacing 不稳定。之前服务端发布视频时使用的是「写一帧视频,然后 sleep 一个 frameDur 」的相对节奏。这个写法看起来简单,但每次写包、调度、sleep 都会产生误差,而且误差会在一个 session 内逐帧累积。更麻烦的是,音频 Opus 帧之前是按视频帧分组一起写出去的,没有按 20ms 的节奏平滑发送,实际效果就是跟着视频帧一组一组发送出去。浏览器收到的 arrival pattern 不均匀,视频 jitter buffer 会被逐渐拉大,最后表现为画面越来越落后于声音。 第二个原因是 speaking turn 之间的 RTP idle gap 处理不正确。两个 speaking turn 之间可能停顿 2S ,也可能停顿两分钟,但之前 RTP timestamp gap correction 最多只跳过 2 秒。对浏览器来说,这就变成了一个很异常的信号:真实网络到达时间已经过去很久,但 RTP media clock 只前进了 2 秒。浏览器的视频 jitter buffer 会把后续包当成严重异常的延迟流来处理, video_jb 被污染后,就会继续影响后面的播放。 第三个原因是浏览器 receiver 状态会跨 speaking turn 残留。前端从 WebRTC 画面切到 idle 视频,只是视觉层的切换,并不会重置 RTCPeerConnection 、receiver 或 jitter buffer 。也就是说,一旦某一轮 speaking turn 把视频 jitter buffer 拉高,后面几轮即使生成端已经恢复正常,也可能继续继承这个异常状态。这就是为什么日志里会看到某一轮开始明显漂移,后面几轮 JBDelta(window) 仍然保持很高。 一开始我尝试以 vibe coding 的方式来解决这个问题,但是 vibe 了整整一天都没搞定。因为音画不同是一件“主观”的判断,AI 感知不到这个事情。所以无论 AI 无论怎么进行逻辑推理,它都感知不到“不同步”。于是乎我想到了给整个链路添加监控,并且调研了一些方法来量化“音画同步“的差值。 Commit ad470a7 。有了真实的反馈指标后,AI 就有了调优的方向。 搞清楚原因,解决起来就简单了。 Commit 0ad5730 feat:新增 silent_inference 推理模式 CyberVerse 此前一直都是采用的 cached_video 模式,这种模式有一些好处:节省算力、对数字人的编排空间更大,用户可以使用更强大的视频生成模型来生成更好看的待机视频,而且可以生成很多很多。但这个模式也有一个不好的地方,就是整个人物不够连贯,不说话——>说话——>不说话,这个过程画面是有割裂的。所以我新增了 silent_inference 模式来解决这个问题。这个模型会一直进行推理,说话的时候用语音音频推理,不说话的时候用静音音频推理。不说话——>说话——>不说话,这个过程就会变得非常连贯。不会出现任何跳帧的情况。当然这个模式的缺点就是不说话时的画面会一直重复,而且这个画面是没有办法控制的,不管使用静音驱动还是随机噪音驱动,都不会有太大区别。 Commit 57512f7 fix:语音链路与上下文恢复 修复超时重连后上下文丢失的问题。qwen omni 模型有设置 5 分钟的超时连接,超过过后可以,再次发送文件进行唤醒。但是重连之后有个 bug:没有上一轮回话的上下文带上。 Commit 0e1c171 工程规范文档调整 补充 Truth-First Reasoning Rules 到 AGENTS.md / Claude.md ,用于抑制 AI 左右脑互搏的情况。详见: X 移除了 andrej-karpathy-skills 四个原则,听网友说这个提示词没有什么卵用,可能已经被官方吸纳了。 Commit e6788a8 祝大家周末愉快
最近把一篇 WebRTC + gRPC 音视频通话方案做了脱敏整理,主要讨论复杂局域网/受限网络里,Android 终端之间做实时音视频时,信令、媒体链路和自恢复能力应该怎么拆。 这篇不是完整生产配置,而是一个架构复盘。重点是几个边界: - gRPC 信令层负责设备状态、会话控制和事件分发。 - WebRTC 负责 SDP/ICE 、track 和媒体传输。 - Android 客户端负责权限、采集、播放、UI 状态和资源释放。 - RTC Gateway 需要承担自动发现、状态同步、故障恢复和观测入口。 - 音频质量、弱网恢复、设备重启、会话残留这些问题不能只靠业务层 timeout 判断。 文章地址: https://www.lodan.me/posts/webrtc-grpc-lan-call-architecture/ 想请教大家:在局域网或受限网络里做 WebRTC 时,你们更倾向把信令网关做成独立服务,还是内置到客户端/边缘节点?故障恢复通常靠 WebSocket 重连、gRPC stream ,还是自定义心跳/发现机制?
最近把一篇 WebRTC + gRPC 音视频通话方案做了脱敏整理,主要讨论复杂局域网/受限网络里,Android 终端之间做实时音视频时,信令、媒体链路和自恢复能力应该怎么拆。 这篇不是完整生产配置,而是一个架构复盘。重点是几个边界: - gRPC 信令层负责设备状态、会话控制和事件分发。 - WebRTC 负责 SDP/ICE 、track 和媒体传输。 - Android 客户端负责权限、采集、播放、UI 状态和资源释放。 - RTC Gateway 需要承担自动发现、状态同步、故障恢复和观测入口。 - 音频质量、弱网恢复、设备重启、会话残留这些问题不能只靠业务层 timeout 判断。 文章地址: https://www.lodan.me/posts/webrtc-grpc-lan-call-architecture/ 想请教大家:在局域网或受限网络里做 WebRTC 时,你们更倾向把信令网关做成独立服务,还是内置到客户端/边缘节点?故障恢复通常靠 WebSocket 重连、gRPC stream ,还是自定义心跳/发现机制?
大概用法是:主持人在扩展里创建房间,选择一个媒体源;观看者通过网页端输入房间码,或者直接打开房间链接加入。 它不是把原始视频文件上传给别人,而是用 WebRTC 传输浏览器里解码后的媒体流。网络情况好的时候,画质会自动往上适配;网络差的时候就比较随缘。 目前能共享这些东西: 常见视频网站里的 <video> 标签,插件会嗅探页面上可见的视频元素,然后用 captureStream() 推流 标签页、窗口、屏幕 本地视频文件,扩展里会用 offscreen document 持有一个隐藏播放器,所以观看页刷新或关掉之后,推流也可以继续 房间内支持文字聊天、成员列表、踢人、可选密码 也做了语音和视频通话,能看到当前在线通话人数 为什么说偏玩具?主要是没钱。 国内没有中转服务器,现在只有 3 台 Oracle 的海外 TURN/中继。网络好(可以直连的)的用户体验还行,网络复杂一点,比如公司内网、校园网、运营商 NAT 比较怪,就可能连不上或者延迟比较高。 我感觉它可能比较适合两类场景: 网络还不错的异地情侣,一起看点东西 同办公室摸鱼的朋友,共享个画面或者本地视频 感兴趣可以装来玩玩。也欢迎提 issue ,尤其是网络穿透、TURN 、WebRTC 这块的建议。 主页: https://screenmate.recolly.com/ 插件地址: https://chromewebstore.google.com/detail/screenmate-webrtc-video-s/nlhckieejhbhoeeeiekjdpodemijblnl github: https://github.com/ekxs-dev/ScreenMate
大概用法是:主持人在扩展里创建房间,选择一个媒体源;观看者通过网页端输入房间码,或者直接打开房间链接加入。 它不是把原始视频文件上传给别人,而是用 WebRTC 传输浏览器里解码后的媒体流。网络情况好的时候,画质会自动往上适配;网络差的时候就比较随缘。 目前能共享这些东西: 常见视频网站里的 <video> 标签,插件会嗅探页面上可见的视频元素,然后用 captureStream() 推流 标签页、窗口、屏幕 本地视频文件,扩展里会用 offscreen document 持有一个隐藏播放器,所以观看页刷新或关掉之后,推流也可以继续 房间内支持文字聊天、成员列表、踢人、可选密码 也做了语音和视频通话,能看到当前在线通话人数 为什么说偏玩具?主要是没钱。 国内没有中转服务器,现在只有 3 台 Oracle 的海外 TURN/中继。网络好(可以直连的)的用户体验还行,网络复杂一点,比如公司内网、校园网、运营商 NAT 比较怪,就可能连不上或者延迟比较高。 我感觉它可能比较适合两类场景: 网络还不错的异地情侣,一起看点东西 同办公室摸鱼的朋友,共享个画面或者本地视频 感兴趣可以装来玩玩。也欢迎提 issue ,尤其是网络穿透、TURN 、WebRTC 这块的建议。 主页: https://screenmate.recolly.com/ 插件地址: https://chromewebstore.google.com/detail/screenmate-webrtc-video-s/nlhckieejhbhoeeeiekjdpodemijblnl github: https://github.com/ekxs-dev/ScreenMate
大概用法是:主持人在扩展里创建房间,选择一个媒体源;观看者通过网页端输入房间码,或者直接打开房间链接加入。 它不是把原始视频文件上传给别人,而是用 WebRTC 传输浏览器里解码后的媒体流。网络情况好的时候,画质会自动往上适配;网络差的时候就比较随缘。 目前能共享这些东西: 常见视频网站里的 <video> 标签,插件会嗅探页面上可见的视频元素,然后用 captureStream() 推流 标签页、窗口、屏幕 本地视频文件,扩展里会用 offscreen document 持有一个隐藏播放器,所以观看页刷新或关掉之后,推流也可以继续 房间内支持文字聊天、成员列表、踢人、可选密码 也做了语音和视频通话,能看到当前在线通话人数 为什么说偏玩具?主要是没钱。 国内没有中转服务器,现在只有 3 台 Oracle 的海外 TURN/中继。网络好(可以直连的)的用户体验还行,网络复杂一点,比如公司内网、校园网、运营商 NAT 比较怪,就可能连不上或者延迟比较高。 我感觉它可能比较适合两类场景: 网络还不错的异地情侣,一起看点东西 同办公室摸鱼的朋友,共享个画面或者本地视频 感兴趣可以装来玩玩。也欢迎提 issue ,尤其是网络穿透、TURN 、WebRTC 这块的建议。 主页: https://screenmate.recolly.com/ 插件地址: https://chromewebstore.google.com/detail/screenmate-webrtc-video-s/nlhckieejhbhoeeeiekjdpodemijblnl github: https://github.com/ekxs-dev/ScreenMate
大概用法是:主持人在扩展里创建房间,选择一个媒体源;观看者通过网页端输入房间码,或者直接打开房间链接加入。 它不是把原始视频文件上传给别人,而是用 WebRTC 传输浏览器里解码后的媒体流。网络情况好的时候,画质会自动往上适配;网络差的时候就比较随缘。 目前能共享这些东西: 常见视频网站里的 <video> 标签,插件会嗅探页面上可见的视频元素,然后用 captureStream() 推流 标签页、窗口、屏幕 本地视频文件,扩展里会用 offscreen document 持有一个隐藏播放器,所以观看页刷新或关掉之后,推流也可以继续 房间内支持文字聊天、成员列表、踢人、可选密码 也做了语音和视频通话,能看到当前在线通话人数 为什么说偏玩具?主要是没钱。 国内没有中转服务器,现在只有 3 台 Oracle 的海外 TURN/中继。网络好(可以直连的)的用户体验还行,网络复杂一点,比如公司内网、校园网、运营商 NAT 比较怪,就可能连不上或者延迟比较高。 我感觉它可能比较适合两类场景: 网络还不错的异地情侣,一起看点东西 同办公室摸鱼的朋友,共享个画面或者本地视频 感兴趣可以装来玩玩。也欢迎提 issue ,尤其是网络穿透、TURN 、WebRTC 这块的建议。 主页: https://screenmate.recolly.com/ 插件地址: https://chromewebstore.google.com/detail/screenmate-webrtc-video-s/nlhckieejhbhoeeeiekjdpodemijblnl github: https://github.com/ekxs-dev/ScreenMate
大概用法是:主持人在扩展里创建房间,选择一个媒体源;观看者通过网页端输入房间码,或者直接打开房间链接加入。 它不是把原始视频文件上传给别人,而是用 WebRTC 传输浏览器里解码后的媒体流。网络情况好的时候,画质会自动往上适配;网络差的时候就比较随缘。 目前能共享这些东西: 常见视频网站里的 <video> 标签,插件会嗅探页面上可见的视频元素,然后用 captureStream() 推流 标签页、窗口、屏幕 本地视频文件,扩展里会用 offscreen document 持有一个隐藏播放器,所以观看页刷新或关掉之后,推流也可以继续 房间内支持文字聊天、成员列表、踢人、可选密码 也做了语音和视频通话,能看到当前在线通话人数 为什么说偏玩具?主要是没钱。 国内没有中转服务器,现在只有 3 台 Oracle 的海外 TURN/中继。网络好(可以直连的)的用户体验还行,网络复杂一点,比如公司内网、校园网、运营商 NAT 比较怪,就可能连不上或者延迟比较高。 我感觉它可能比较适合两类场景: 网络还不错的异地情侣,一起看点东西 同办公室摸鱼的朋友,共享个画面或者本地视频 感兴趣可以装来玩玩。也欢迎提 issue ,尤其是网络穿透、TURN 、WebRTC 这块的建议。 主页: https://screenmate.recolly.com/ 插件地址: https://chromewebstore.google.com/detail/screenmate-webrtc-video-s/nlhckieejhbhoeeeiekjdpodemijblnl github: https://github.com/ekxs-dev/ScreenMate
大概用法是:主持人在扩展里创建房间,选择一个媒体源;观看者通过网页端输入房间码,或者直接打开房间链接加入。 它不是把原始视频文件上传给别人,而是用 WebRTC 传输浏览器里解码后的媒体流。网络情况好的时候,画质会自动往上适配;网络差的时候就比较随缘。 目前能共享这些东西: 常见视频网站里的 <video> 标签,插件会嗅探页面上可见的视频元素,然后用 captureStream() 推流 标签页、窗口、屏幕 本地视频文件,扩展里会用 offscreen document 持有一个隐藏播放器,所以观看页刷新或关掉之后,推流也可以继续 房间内支持文字聊天、成员列表、踢人、可选密码 也做了语音和视频通话,能看到当前在线通话人数 为什么说偏玩具?主要是没钱。 国内没有中转服务器,现在只有 3 台 Oracle 的海外 TURN/中继。网络好(可以直连的)的用户体验还行,网络复杂一点,比如公司内网、校园网、运营商 NAT 比较怪,就可能连不上或者延迟比较高。 我感觉它可能比较适合两类场景: 网络还不错的异地情侣,一起看点东西 同办公室摸鱼的朋友,共享个画面或者本地视频 感兴趣可以装来玩玩。也欢迎提 issue ,尤其是网络穿透、TURN 、WebRTC 这块的建议。 主页: https://screenmate.recolly.com/ 插件地址: https://chromewebstore.google.com/detail/screenmate-webrtc-video-s/nlhckieejhbhoeeeiekjdpodemijblnl github: https://github.com/ekxs-dev/ScreenMate
大概用法是:主持人在扩展里创建房间,选择一个媒体源;观看者通过网页端输入房间码,或者直接打开房间链接加入。 它不是把原始视频文件上传给别人,而是用 WebRTC 传输浏览器里解码后的媒体流。网络情况好的时候,画质会自动往上适配;网络差的时候就比较随缘。 目前能共享这些东西: 常见视频网站里的 <video> 标签,插件会嗅探页面上可见的视频元素,然后用 captureStream() 推流 标签页、窗口、屏幕 本地视频文件,扩展里会用 offscreen document 持有一个隐藏播放器,所以观看页刷新或关掉之后,推流也可以继续 房间内支持文字聊天、成员列表、踢人、可选密码 也做了语音和视频通话,能看到当前在线通话人数 为什么说偏玩具?主要是没钱。 国内没有中转服务器,现在只有 3 台 Oracle 的海外 TURN/中继。网络好(可以直连的)的用户体验还行,网络复杂一点,比如公司内网、校园网、运营商 NAT 比较怪,就可能连不上或者延迟比较高。 我感觉它可能比较适合两类场景: 网络还不错的异地情侣,一起看点东西 同办公室摸鱼的朋友,共享个画面或者本地视频 感兴趣可以装来玩玩。也欢迎提 issue ,尤其是网络穿透、TURN 、WebRTC 这块的建议。 主页: https://screenmate.recolly.com/ 插件地址: https://chromewebstore.google.com/detail/screenmate-webrtc-video-s/nlhckieejhbhoeeeiekjdpodemijblnl github: https://github.com/ekxs-dev/ScreenMate
大概用法是:主持人在扩展里创建房间,选择一个媒体源;观看者通过网页端输入房间码,或者直接打开房间链接加入。 它不是把原始视频文件上传给别人,而是用 WebRTC 传输浏览器里解码后的媒体流。网络情况好的时候,画质会自动往上适配;网络差的时候就比较随缘。 目前能共享这些东西: 常见视频网站里的 <video> 标签,插件会嗅探页面上可见的视频元素,然后用 captureStream() 推流 标签页、窗口、屏幕 本地视频文件,扩展里会用 offscreen document 持有一个隐藏播放器,所以观看页刷新或关掉之后,推流也可以继续 房间内支持文字聊天、成员列表、踢人、可选密码 也做了语音和视频通话,能看到当前在线通话人数 为什么说偏玩具?主要是没钱。 国内没有中转服务器,现在只有 3 台 Oracle 的海外 TURN/中继。网络好(可以直连的)的用户体验还行,网络复杂一点,比如公司内网、校园网、运营商 NAT 比较怪,就可能连不上或者延迟比较高。 我感觉它可能比较适合两类场景: 网络还不错的异地情侣,一起看点东西 同办公室摸鱼的朋友,共享个画面或者本地视频 感兴趣可以装来玩玩。也欢迎提 issue ,尤其是网络穿透、TURN 、WebRTC 这块的建议。 主页: https://screenmate.recolly.com/ 插件地址: https://chromewebstore.google.com/detail/screenmate-webrtc-video-s/nlhckieejhbhoeeeiekjdpodemijblnl github: https://github.com/ekxs-dev/ScreenMate
最近整理了一次 WebRTC 问题排查,脱敏后记录一下。 背景是一个 Android WebRTC 音视频通话场景。原来主要在内部网络使用,后续为了支持更复杂的网络边界,引入了 `coturn` 做 TURN 中继。 问题现象: - Android 14 设备和旧版 Android 设备通话时,Android 14 端经常在 30-60 秒内自动退出。 - 旧版 Android 设备基本正常。 - 少数情况下双方也能持续正常通话。 - 强制走 TURN relay 后更容易稳定复现。 一开始日志里有一条本地地址相关的中继协商 timeout ,而且经常出现在断开前后,所以很容易误判为根因。 后面看 WebRTC 状态变化,真正关键的是: ```text IceConnectionChange -> DISCONNECTED / FAILED StandardizedIceConnectionChange -> DISCONNECTED / FAILED ``` 排查过程大概是: 1. 先统一链路,强制走 `coturn`,避免内部网络直连把问题掩盖掉。 2. 替换过 WebRTC 依赖版本,排除单纯的 SDK 版本问题。 3. 扩大设备矩阵,问题逐渐收敛到 Android 14 设备。 4. 回到 TURN 服务侧检查证书、安全参数和端口开放。 5. 调整 `coturn` 相关配置后,同样测试矩阵下不再出现 30-60 秒自动断开。 这次最大的教训是:WebRTC 问题不要只盯某一条高频日志。更可靠的路径是先看 ICE 状态机、candidate pair 、当前到底走的是直连还是 relay 。 另外,直连和中继混在一起测,很容易让问题看起来像“网络随机抖动”。强制走 relay 后,问题才变成可复现、可分析。 欢迎交流 Android WebRTC 、coturn 、TURN relay 和 RTC Gateway 稳定性问题。 完整整理在这里: https://snowlyg.github.io/posts/android14-coturn-webrtc-disconnect/
最近整理了一次 WebRTC 问题排查,脱敏后记录一下。 背景是一个 Android WebRTC 音视频通话场景。原来主要在内部网络使用,后续为了支持更复杂的网络边界,引入了 `coturn` 做 TURN 中继。 问题现象: - Android 14 设备和旧版 Android 设备通话时,Android 14 端经常在 30-60 秒内自动退出。 - 旧版 Android 设备基本正常。 - 少数情况下双方也能持续正常通话。 - 强制走 TURN relay 后更容易稳定复现。 一开始日志里有一条本地地址相关的中继协商 timeout ,而且经常出现在断开前后,所以很容易误判为根因。 后面看 WebRTC 状态变化,真正关键的是: ```text IceConnectionChange -> DISCONNECTED / FAILED StandardizedIceConnectionChange -> DISCONNECTED / FAILED ``` 排查过程大概是: 1. 先统一链路,强制走 `coturn`,避免内部网络直连把问题掩盖掉。 2. 替换过 WebRTC 依赖版本,排除单纯的 SDK 版本问题。 3. 扩大设备矩阵,问题逐渐收敛到 Android 14 设备。 4. 回到 TURN 服务侧检查证书、安全参数和端口开放。 5. 调整 `coturn` 相关配置后,同样测试矩阵下不再出现 30-60 秒自动断开。 这次最大的教训是:WebRTC 问题不要只盯某一条高频日志。更可靠的路径是先看 ICE 状态机、candidate pair 、当前到底走的是直连还是 relay 。 另外,直连和中继混在一起测,很容易让问题看起来像“网络随机抖动”。强制走 relay 后,问题才变成可复现、可分析。 欢迎交流 Android WebRTC 、coturn 、TURN relay 和 RTC Gateway 稳定性问题。 完整整理在这里: https://snowlyg.github.io/posts/android14-coturn-webrtc-disconnect/
最近整理了一次 WebRTC 问题排查,脱敏后记录一下。 背景是一个 Android WebRTC 音视频通话场景。原来主要在内部网络使用,后续为了支持更复杂的网络边界,引入了 `coturn` 做 TURN 中继。 问题现象: - Android 14 设备和旧版 Android 设备通话时,Android 14 端经常在 30-60 秒内自动退出。 - 旧版 Android 设备基本正常。 - 少数情况下双方也能持续正常通话。 - 强制走 TURN relay 后更容易稳定复现。 一开始日志里有一条本地地址相关的中继协商 timeout ,而且经常出现在断开前后,所以很容易误判为根因。 后面看 WebRTC 状态变化,真正关键的是: ```text IceConnectionChange -> DISCONNECTED / FAILED StandardizedIceConnectionChange -> DISCONNECTED / FAILED ``` 排查过程大概是: 1. 先统一链路,强制走 `coturn`,避免内部网络直连把问题掩盖掉。 2. 替换过 WebRTC 依赖版本,排除单纯的 SDK 版本问题。 3. 扩大设备矩阵,问题逐渐收敛到 Android 14 设备。 4. 回到 TURN 服务侧检查证书、安全参数和端口开放。 5. 调整 `coturn` 相关配置后,同样测试矩阵下不再出现 30-60 秒自动断开。 这次最大的教训是:WebRTC 问题不要只盯某一条高频日志。更可靠的路径是先看 ICE 状态机、candidate pair 、当前到底走的是直连还是 relay 。 另外,直连和中继混在一起测,很容易让问题看起来像“网络随机抖动”。强制走 relay 后,问题才变成可复现、可分析。 欢迎交流 Android WebRTC 、coturn 、TURN relay 和 RTC Gateway 稳定性问题。 完整整理在这里: https://snowlyg.github.io/posts/android14-coturn-webrtc-disconnect/
需要在手机端运行个代理程序,就可以通过 pc/ios/手机浏览器连接。通过 webrtc 直连,类似于 scrcpy 的网页版。 还需要部署个信令服务器,信令服务器可以部署在 window/mac/linux/android 本机上,或者在云服务上,相当于云手机。 主要特性: 1 ,局域网延时 100ms 以内,支持带宽估算和动态码流。 2 ,webrtc udp p2p 直连,家里有 ipv6 可以在外面连。 3 ,有简单的按键映射功能,在 pc 玩手机游戏 4 ,可以脱离有线/无线 adb 运行 一开始的目的是用旧手机当监控,用模拟器玩小游戏。 https://github.com/hqw700/ScrcpyOverWebRTC