neko 虚拟浏览器 WebRTC 网络配置完全指南:ICE、端口规划与带宽估计器调优
2026/9/13 2:03:20 网站建设 项目流程

neko 虚拟浏览器 WebRTC 网络配置完全指南:ICE、端口规划与带宽估计器调优

【免费下载链接】nekoA self hosted virtual browser that runs in docker and uses WebRTC.项目地址: https://gitcode.com/GitHub_Trending/ne/neko

本篇技术指南聚焦于 neko(基于 Docker 运行、通过 WebRTC 传输音视频的虚拟浏览器)的 WebRTC 与网络层配置。你将掌握 ICE 连接建立机制(Trickle/Lite/STUN/TURN)、服务器端口规划(临时 UDP 端口池与 UDP/TCP 多路复用)、NAT 场景下的公网 IP 处理,以及实验性带宽估计器的调优参数,从而在真实部署中实现低延迟、可穿透、稳定的点对点音视频流。文中所有配置项均可在 docker-compose.yaml 与 server/internal/config/webrtc.go 中找到实现依据。

WebRTC 在 neko 中的角色

neko 使用 WebRTC 在客户端与服务器之间建立点对点(peer-to-peer)连接,连接建立基于 Go 生态的 Pion 库。这条连接被用来双向传输音视频流与数据(包括鼠标键盘输入、剪贴板、光标图像/位置等控制信号),是 neko 全部交互能力的传输底座。

从源码结构看,WebRTC 相关实现集中在 server/internal/webrtc/ 目录:

  • manager.go 负责创建 PeerConnection、ICE 多路复用监听器、音视频 Track、DataChannel 与带宽估计器;
  • peer.go 封装单个对端的 SDP 协商、候选者注入、暂停/切换视频流与估计器读取循环;
  • 类型定义位于 server/pkg/types/webrtc.go,配置解析位于 server/internal/config/webrtc.go。

ICE 连接建立机制

ICE(Interactive Connectivity Establishment,交互式连接建立)是一套用于在两台对端(如客户端与服务器)之间寻找最佳连通路径的协议。它帮助双方发现各自的公网 IP 与端口,从而建立直接连接;携带这些信息的 ICE candidate(候选者)会通过信令服务器(Signaling Server)交换,以推进连接过程。

ICE Trickle:候选者边发现边发送

ICE Trickle 允许 ICE candidate 在发现后立即发送,而不是等全部候选者收集完毕再统一发送。这样服务器一旦拿到少量候选者即可开始连接客户端,无需等待全部收集完成,因此能显著缩短建连时间。

配置项默认值类型说明
webrtc.icetrickletrueboolean是否使用 Trickle ICE 异步发送候选者

环境变量对应NEKO_WEBRTC_ICETRICKLE。从 manager.go 可以看到:启用时,connection.OnICECandidate回调会将每个本地候选者通过SIGNAL_CANDIDATE事件即时推送给客户端;而在 peer.go 中,若关闭 Trickle,则setLocalDescription会通过GatheringCompletePromise阻塞等待 ICE 收集全部完成后才返回 SDP。

ICE Lite:面向公网 IP 的精简模式

ICE Lite 是 ICE 协议的最小实现,适用于直接运行在公网 IP 上的服务器。它默认关闭(false),以便开箱即用地支持更复杂的 ICE 配置。

:::info 当配置了 ICE Servers(STUN/TURN)时,必须关闭 ICE Lite。 :::

环境变量为NEKO_WEBRTC_ICELITE。在 manager.go 中,启用ICELite时服务器不会把后端 ICE Servers 写入 Pion 的webrtc.Configuration;同时 config/webrtc.go 会在「ICE Lite + 后端 ICE 服务器同时存在」时打印警告并忽略后端服务器。此外 manager.go 通过settings.SetLite(...)将 Pion Agent 设置为 Lite 模式。

ICE Servers:STUN 与 TURN

ICE 服务器用于帮助建立客户端与服务器之间的连接,分为两类:

  • STUN(Session Traversal Utilities for NAT):用于发现客户端的公网 IP,从而建立客户端与服务器之间的直接连接;
  • TURN(Traversal Using Relays around NAT):当无法建立直接连接时,作为中继在客户端与服务器之间转发数据。

单个 ICE 服务器配置由以下字段组成:

字段说明类型
urlsICE 服务器 URL 列表;若同一服务器在多个 URL 上提供相同凭据,可在此一并列出string[]
username服务器要求认证时使用的用户名string
credential服务器要求认证时使用的凭据string

对应的 Go 类型定义见 server/pkg/types/webrtc.go。neko 在未配置任何 ICE 服务器时,会自动使用内置默认 STUN 服务器stun:stun.l.google.com:19302(常量defStunSrv,见 config/webrtc.go)。

多 ICE 服务器配置示例

YAML 形式(适用于配置文件):

- urls: "turn:<MY-COTURN-SERVER>:3478" username: "neko" credential: "neko" - urls: "stun:stun.l.google.com:19302"

JSON 形式(可配合环境变量使用):

[ { "urls": "turn:<MY-COTURN-SERVER>:3478", "username": "neko", "credential": "neko" }, { "urls": "stun:stun.l.google.com:19302" } ]

:::tip 可以在docker-compose.yaml中把 ICE 服务器以JSON 字符串形式写入NEKO_WEBRTC_ICESERVERS_FRONTENDNEKO_WEBRTC_ICESERVERS_BACKEND环境变量:

NEKO_WEBRTC_ICESERVERS_FRONTEND: | [{ "urls": [ "turn:<MY-COTURN-SERVER>:3478" ], "username": "neko", "credential": "neko" },{ "urls": [ "stun:stun.nextcloud.com:3478" ] }]

:::

这种「JSON 字符串自动解码」的能力来自配置层的utils.JsonStringAutoDecode解码钩子(见 config/webrtc.go),也就是说同一配置既可以是 YAML 数组,也可以是通过环境变量传入的 JSON 字符串。

Frontend 与 Backend 分组

ICE 服务器被划分为两组:

配置项默认值类型说明
webrtc.iceservers.frontend[]array发送给客户端的 ICE 服务器,用于建立客户端与服务器之间的连接
webrtc.iceservers.backend[]array服务器端收集 ICE candidate 时使用的 ICE 服务器,可能包含私网 IP 等不应下发给客户端的信息

对应环境变量为NEKO_WEBRTC_ICESERVERS_FRONTENDNEKO_WEBRTC_ICESERVERS_BACKEND。二者在服务端的用途不同:前端服务器通过 manager.go 的ICEServers()暴露给客户端;后端服务器则在 manager.go 中被写入 Pion 配置用于收集候选者。若两者都未配置,则统一回落到全局webrtc.iceservers(v2 兼容项)或默认 STUN 服务器,并同时填充 frontend 与 backend(config/webrtc.go)。

Coturn 服务器部署示例
docker-compose 中部署 Coturn 的完整示例
services: coturn: image: 'coturn/coturn:latest' network_mode: "host" command: | -n --realm=localhost --fingerprint --listening-ip=0.0.0.0 --external-ip=<MY-COTURN-SERVER> --listening-port=3478 --min-port=49160 --max-port=49200 --log-file=stdout --user=neko:neko --lt-cred-mech

<MY-COTURN-SERVER>替换为你的局域网或公网 IP,并在防火墙放行49160-49200/udp3478/tcp--user用于指定 TURN 服务器的用户名与密码,--lt-cred-mech用于启用长期凭证(long-term credentials)认证机制。注意--external-ip必须与docker-compose.yaml中 ICE 服务器配置里的 TURN 地址保持一致,否则中继候选者无法被客户端正确使用。

网络规划:端口、防火墙与反向代理边界

WebRTC 是点对点协议,要求客户端与服务器之间能建立直接连接,可通过以下两种方式达成:

  • 为服务器使用公网 IP(若部署在私网,则至少保证客户端可达);
  • 在无法直连时,使用 TURN 服务器 中继数据。

所有已配置端口会连同服务器 IP 一起写入 ICE candidate 下发给客户端,因此必须确保这些端口在服务器防火墙上处于开放状态未被重映射到其他端口,且从客户端可达。

:::danger 牢记 WebRTC 不使用 HTTP 协议,因此无法通过 nginx 或其他反向代理转发 WebRTC 流量。如果你的服务器只暴露了443端口,则必须额外暴露 WebRTC 端口,或使用 TURN 服务器。 :::

neko 支持两种连接方式:

  • 临时 UDP 端口池(Ephemeral UDP port range):服务器用于与客户端建连的一段 UDP 端口范围。每次建立新连接都会使用该范围内的一个新端口,该范围必须在服务器防火墙中放行;
  • UDP/TCP 多路复用(Multiplexing):服务器用单个端口承载多个连接,同样需要在防火墙中放行。

临时 UDP 端口池(EPR)

配置项默认值类型说明
webrtc.epr未设置(默认59000-59100string限制 ICE UDP 连接可分配的临时端口池

环境变量为NEKO_WEBRTC_EPR,格式为min-max,例如59000-59100。该范围包含 101 个端口,需在防火墙全部放行。端口数量决定可承载的并发连接规模,可按预期并发数酌情增减。

未配置eprtcpmuxudpmux中任何一个时,config/webrtc.go 会启用默认范围59000-59100并打印告警日志。解析逻辑(config/webrtc.go)会校验端口格式与大小关系:min大于max会直接Panic,非法端口会解析失败。

:::tip 务必注意 在docker-compose.yaml中指定临时 UDP 端口范围时,端口映射必须同样使用 UDP 协议

environment: NEKO_WEBRTC_EPR: "59000-59100" ports: - "59000-59100:59000-59100/udp"

必须将相同端口原样暴露到宿主机,不要重映射。例如49000-49100:59000-59100/udp是错误写法,59000-59100:59000-59100/udp才是正确写法,否则客户端收到的候选者端口与真实监听端口不一致,导致连接失败。 :::

UDP/TCP 多路复用(Mux)

配置项默认值类型说明
webrtc.udpmux未设置int所有对端共用的单个 UDP mux 端口,设置后取代 EPR
webrtc.tcpmux未设置int所有对端共用的单个 TCP mux 端口

环境变量为NEKO_WEBRTC_UDPMUXNEKO_WEBRTC_TCPMUX。服务器仅用59000一个端口同时承载 UDP 与 TCP 连接。可以只启用其中一个协议,也可以两个都启用。UDP 通常延迟更低,但部分网络会屏蔽 UDP,因此保留 TCP 作为回退是稳妥做法。

对应实现中,manager.go 在Start()阶段分别创建 TCP listener(ice.NewTCPMuxDefault,读写缓冲分别为 50 包与 4MB)与 UDP listener(ice.NewMultiUDPMuxFromPort);随后在 manager.go 按启用的 mux 组合设置网络类型(UDP4/UDP6/TCP4/TCP6)。注意当UDPMux存在时,EPR 端口池将不再生效——两者是互斥的。

:::tip 务必注意 在docker-compose.yaml中指定 mux 端口时,必须正确区分协议

environment: NEKO_WEBRTC_UDPMUX: "59000" NEKO_WEBRTC_TCPMUX: "59000" ports: - "59000:59000/udp" - "59000:59000/tcp"

同样地,必须将端口原样暴露,不做重映射,例如使用59000:59000/udp而不是49000:59000/udp。 :::

服务器 IP 地址

服务器 IP 会写入 ICE candidate 下发给客户端,供其建立连接。默认情况下,服务器会自动解析自身的公网 IP。如果服务器位于 NAT 之后、希望指定其他 IP,或仅在局域网内使用 neko,则可以手动指定服务器 IP。

NAT 1-to-1
配置项默认值类型说明
webrtc.nat1to1strings1:1 (D)NAT 的外部 IP 列表,以及该外部 IP 对应的候选者类型

环境变量为NEKO_WEBRTC_NAT1TO1,示例值10.10.0.5。当前只能指定一个地址。因此如果你希望同时从内网与公网访问实例,路由器必须支持 NAT loopback(hairpinning,NAT 回环)。

从源码看,该列表通过settings.SetNAT1To1IPs(manager.config.NAT1To1IPs, webrtc.ICECandidateTypeHost)写入 Pion SettingEngine(manager.go),即用指定的外部 IP 替换 host 类型候选者。

IP 获取 URL
配置项默认值类型说明
webrtc.ip_retrieval_urlhttps://checkip.amazonaws.comstring用于获取外部 IP 的 URL 地址

环境变量为NEKO_WEBRTC_IP_RETRIEVAL_URL。当未指定nat1to1时,服务器会向该 URL 发送 HTTP GET 请求以获取自身公网 IP(config/webrtc.go)。获取成功后将结果追加进NAT1To1IPs;失败则仅打印警告并继续(服务不会因此退出)。如果所在网络无法访问该默认 URL(例如被墙或离线环境),请替换为可用的公网 IP 查询服务,或直接配置NEKO_WEBRTC_NAT1TO1

带宽估计器(Bandwidth Estimator)

:::danger 带宽估计器是实验性功能,可能无法按预期工作。 :::

带宽估计器允许服务器估算客户端与服务器之间的可用带宽,并根据可用带宽在不同视频质量(码率档位)之间自动切换。默认关闭。

全部参数一览

配置项默认值类型说明
webrtc.estimator.enabledfalseboolean启用带宽估计器
webrtc.estimator.passivefalseboolean被动模式:只做估算、不切换视频管线
webrtc.estimator.debugfalseboolean启用带宽估计器的调试日志
webrtc.estimator.initial_bitrate1000000int估计器的初始码率(bps)
webrtc.estimator.read_interval2sduration读取并处理带宽估算报告的频率
webrtc.estimator.stable_duration12sduration连接稳定(上升或中性趋势)持续多久后升级码率
webrtc.estimator.unstable_duration6sduration连接不稳定(下行趋势)持续多久后降级码率
webrtc.estimator.stalled_duration24sduration带宽估算停滞持续多久后降级
webrtc.estimator.downgrade_backoff10sduration上一次降级后再次降级前的最短等待时间
webrtc.estimator.upgrade_backoff5sduration上一次升级后再次升级前的最短等待时间
webrtc.estimator.diff_threshold0.15float估算码率与当前流码率之间的差异达到多大才触发升级/降级

对应环境变量为NEKO_WEBRTC_ESTIMATOR_ENABLEDNEKO_WEBRTC_ESTIMATOR_PASSIVENEKO_WEBRTC_ESTIMATOR_DEBUGNEKO_WEBRTC_ESTIMATOR_INITIAL_BITRATE等(规则同 Viper 的webrtc.estimator.*键)。这些参数的默认值与类型定义均可在 server/internal/config/webrtc.go 的WebRTCEstimator结构体及 webpage/docs/configuration/help.json 中核对。

工作原理:从 RTCP 反馈到码率切换

估计器在连接层通过 Pion 的GCC(Google Congestion Control)发送端带宽估计实现。在 manager.go 中,启用后会将一个拥塞控制器(cc.NewInterceptor+gcc.NewSendSideBWE)注册进 interceptor registry,并为引擎配置TWCC(Transport- Wide Congestion Control)RTP 头扩展,用于收集传输层拥塞反馈;同时默认使用gcc.NewNoOpPacer(不实际限速发包,只做估算)。

随后,每个对端在 peer.go 的estimatorReader循环中以read_interval(默认 2 秒)为周期执行决策:

  1. 读取estimator.GetTargetBitrate()得到估计目标码率;
  2. 通过 utils/trenddetector.go 的TrendDetector判定码率趋势方向(NEUTRAL/UPWARD/DOWNWARD,内部采用Kendall's Tau秩相关算法,并配置RequiredSamples=8DownwardTrendThreshold=-0.5);
  3. 计算目标码率与当前流码率的比值diff
  4. 降级:当趋势向下或长期停滞(stalled_duration)时,若差异未超阈值且超过降级退避时间与不稳定持续时间,则通过SetVideo请求选择更低码率的流(StreamSelectorTypeLower);
  5. 升级:当趋势中性/向上、估算码率超出当前流码率diff_threshold以上、且稳定持续满stable_duration并超过升级退避时间时,请求选择更高码率的流(StreamSelectorTypeHigher)。

流档位选择由 server/internal/capture/streamselector.go 完成,它支持按 ID 或按码率选取 lower/higher/nearest 流;若已处于最低/最高档,GetStream返回ErrWebRTCStreamNotFound,估计器会记录「already on the lowest/highest stream」日志。

值得注意的是,估计器只在videoAuto开启、视频未禁用、未暂停、且非passive模式时才做切换决策(peer.go)。客户端侧是否开启「自动」由视频信号(PeerVideo.Auto)控制,passive模式则让估计器只输出估算结果而不动视频管线,便于先观察估算质量再决定是否启用。配合debug: true可以查看每个周期的difftarget_bitratestream_bitratedirection日志,是调优stable_duration/unstable_duration/diff_threshold等参数的重要依据。

与多档位视频流的配合

带宽估计器的价值建立在多个不同码率的视频管线之上。neko 通过capture.video.pipelines(多管线映射)与capture.video.ids(有序 ID 列表)配置多档位流,见 server/internal/config/capture.go 与 webpage/docs/configuration/capture.md。只有video.ids中列出的流才会参与估计器的升降级选择;若只配置单档main流,估计器即使启用也无法产生实际切换效果。

快速上手检查清单

综合以上配置,一次典型的公网部署至少需要核对以下项:

  1. 连接方式:三选一——配置NEKO_WEBRTC_EPR(临时 UDP 端口池)、或NEKO_WEBRTC_UDPMUX/NEKO_WEBRTC_TCPMUX(单端口多路复用,建议同时启用 TCP 作为 UDP 被屏蔽时的回退);
  2. 端口放行:将上述端口以相同端口号、正确协议原样映射到宿主机并在防火墙放行,严禁端口重映射;WebRTC 流量无法走 HTTP 反向代理;
  3. NAT 场景:公网直连可开启NEKO_WEBRTC_ICELITE;NAT 之后配置NEKO_WEBRTC_NAT1TO1(公网 IP),或确认路由器支持 NAT hairpinning;也可保留NEKO_WEBRTC_IP_RETRIEVAL_URL自动获取公网 IP;
  4. 跨网络复杂拓扑:配置 frontend/backend 两组 ICE 服务器,必要时部署 Coturn 作为 TURN 中继(此时必须关闭 ICE Lite);
  5. 可选优化:启用带宽估计器并在capture.video.pipelines中配置多档码率流,实现按网络状况自动升降级。

官方仓库的 docker-compose.yaml 给出了一个最小可用示例(NEKO_WEBRTC_EPR: 52000-52100配合NEKO_WEBRTC_ICELITE: 1与对应 UDP 端口映射),可作为部署起点;配置项的完整清单与默认值可在 webpage/docs/configuration/help.json 中一次性查阅。

【免费下载链接】nekoA self hosted virtual browser that runs in docker and uses WebRTC.项目地址: https://gitcode.com/GitHub_Trending/ne/neko

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询