From 6d729f38be4d8f6e0dbc7a7a85258d663466ebc2 Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Fri, 31 Jul 2026 22:19:09 +0800 Subject: [PATCH] =?UTF-8?q?fix(webrtc):=20=E6=9B=B4=E6=96=B0ICE=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E9=85=8D=E7=BD=AE=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=A4=87=E7=94=A8TURN=E6=9C=8D=E5=8A=A1=E5=99=A8=E5=B9=B6?= =?UTF-8?q?=E4=BF=AE=E5=A4=8DiOS=E6=A8=A1=E6=8B=9F=E5=99=A8=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增47.242.112.133的STUN/TURN服务器作为备用中继 - Flutter端添加turns: TLS中继,修复iOS模拟器无法获取relay候选的问题 - Web端同步添加新的ICE服务器配置 - 添加.gitignore忽略IDE配置文件 --- .gitignore | 2 ++ .../ttstd/controlled/webrtc/WebRtcClient.java | 4 ++- .../ttstd/controller/webrtc/WebRtcClient.java | 4 ++- .../src/store/controllerStore.js | 6 ++-- .../lib/config/ice_servers.dart | 29 ++++++++++++++----- 5 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc05d93 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +/.idea/ \ No newline at end of file diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/webrtc/WebRtcClient.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/webrtc/WebRtcClient.java index 8b1db47..1bfb97f 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/webrtc/WebRtcClient.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/webrtc/WebRtcClient.java @@ -284,8 +284,10 @@ public class WebRtcClient { // 建议:如果你有 TURN 服务器,请务必在此处添加,例如: // iceServers.add(PeerConnection.IceServer.builder("turn:your_turn_server").setUsername("user").setPassword("pass").createIceServer()); iceServers.add(PeerConnection.IceServer.builder("turn:175.178.213.60:3478").setUsername("fanhuitong").setPassword("Fan19961207..").createIceServer()); - // iceServers.add(PeerConnection.IceServer.builder("turn:192.168.5.224:3478").setUsername("tt").setPassword("fht").createIceServer()); iceServers.add(PeerConnection.IceServer.builder("stun:175.178.213.60:3478").createIceServer()); + iceServers.add(PeerConnection.IceServer.builder("turn:47.242.112.133:3478").setUsername("ttstd").setPassword("fanhuitong").createIceServer()); + iceServers.add(PeerConnection.IceServer.builder("stun:47.242.112.133:3478").createIceServer()); + // iceServers.add(PeerConnection.IceServer.builder("turn:192.168.5.224:3478").setUsername("tt").setPassword("fht").createIceServer()); // iceServers.add(PeerConnection.IceServer.builder("stun:192.168.5.224:3478").createIceServer()); iceServers.add(PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer()); iceServers.add(PeerConnection.IceServer.builder("stun:stun1.l.google.com:19302").createIceServer()); diff --git a/WebRTCController/app/src/main/java/com/ttstd/controller/webrtc/WebRtcClient.java b/WebRTCController/app/src/main/java/com/ttstd/controller/webrtc/WebRtcClient.java index 3311a7e..6722a8c 100644 --- a/WebRTCController/app/src/main/java/com/ttstd/controller/webrtc/WebRtcClient.java +++ b/WebRTCController/app/src/main/java/com/ttstd/controller/webrtc/WebRtcClient.java @@ -125,8 +125,10 @@ public class WebRtcClient { // 添加 STUN 和 TURN 服务器 // 注意:如果是 TURN 服务器,必须使用 turn: 前缀 iceServers.add(PeerConnection.IceServer.builder("turn:175.178.213.60:3478").setUsername("fanhuitong").setPassword("Fan19961207..").createIceServer()); - // iceServers.add(PeerConnection.IceServer.builder("turn:192.168.5.224:3478").setUsername("tt").setPassword("fht").createIceServer()); iceServers.add(PeerConnection.IceServer.builder("stun:175.178.213.60:3478").createIceServer()); + iceServers.add(PeerConnection.IceServer.builder("turn:47.242.112.133:3478").setUsername("ttstd").setPassword("fanhuitong").createIceServer()); + iceServers.add(PeerConnection.IceServer.builder("stun:47.242.112.133:3478").createIceServer()); + // iceServers.add(PeerConnection.IceServer.builder("turn:192.168.5.224:3478").setUsername("tt").setPassword("fht").createIceServer()); // iceServers.add(PeerConnection.IceServer.builder("stun:192.168.5.224:3478").createIceServer()); iceServers.add(PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer()); iceServers.add(PeerConnection.IceServer.builder("stun:stun1.l.google.com:19302").createIceServer()); diff --git a/WebRTCControllerWeb/src/store/controllerStore.js b/WebRTCControllerWeb/src/store/controllerStore.js index 40c3f0b..5586076 100644 --- a/WebRTCControllerWeb/src/store/controllerStore.js +++ b/WebRTCControllerWeb/src/store/controllerStore.js @@ -10,13 +10,15 @@ const videoRecorder = new VideoRecorder(); // 与 Android/Flutter 端一致的 ICE 配置(请按需替换为自己的 TURN 凭据)。 export const DEFAULT_ICE_SERVERS = [ // 公共 TURN(relay 兜底):UDP + TCP 两种传输,TCP 用于 UDP 被防火墙拦截的网络。 + { urls: 'stun:175.178.213.60:3478' }, { urls: 'turn:175.178.213.60:3478', username: 'fanhuitong', credential: 'Fan19961207..' }, { urls: 'turn:175.178.213.60:3478?transport=tcp', username: 'fanhuitong', credential: 'Fan19961207..' }, + { urls: 'stun:47.242.112.133:3478' }, + { urls: 'turn:47.242.112.133:3478', username: 'ttstd', credential: 'fanhuitong' }, // 内网 TURN(与被控端同局域网时可用)。 + // { urls: 'stun:192.168.5.224:3478' }, // { urls: 'turn:192.168.100.224:3478', username: 'tt', credential: 'fht' }, // { urls: 'turn:192.168.100.224:3478?transport=tcp', username: 'tt', credential: 'fht' }, - { urls: 'stun:175.178.213.60:3478' }, - // { urls: 'stun:192.168.5.224:3478' }, // { urls: 'stun:stun.l.google.com:19302' }, // { urls: 'stun:stun1.l.google.com:19302' }, // { urls: 'stun:stun2.l.google.com:19302' }, diff --git a/webrtc_controller_flutter/lib/config/ice_servers.dart b/webrtc_controller_flutter/lib/config/ice_servers.dart index d832c67..581b84d 100644 --- a/webrtc_controller_flutter/lib/config/ice_servers.dart +++ b/webrtc_controller_flutter/lib/config/ice_servers.dart @@ -8,17 +8,26 @@ /// `ICE Checking -> Failed`。已修正为与 iOS 原生项目相同的服务器。 /// ICE 服务器配置。 /// -/// 与「被控端 Android」完全一致(同一台 TURN 服务器、同一凭据), -/// 并额外补充 `?transport=tcp` 的 TURN 候选作为 iOS 模拟器兜底: -/// - 被控端已用 `175.178.213.60:3478`(fanhuitong / Fan19961907..)成功产出 -/// relay 候选(见日志 `relay raddr 175.178.213.60`),故控制端用同一台、 -/// 同一凭据即可在 TURN 中继相遇; -/// - 内网 `192.168.5.224` 在模拟器上不可达,已排除; -/// - 模拟器 UDP 不稳,保留 TCP 中继候选。 +/// 与「被控端 Android」同一台 TURN 服务器(175.178.213.60)、同一凭据 +/// (fanhuitong / Fan19961907..)。 +/// +/// **iOS 模拟器关键修复**: +/// 明文 `turn:175.178.213.60:3478` 在 iOS 模拟器(libwebrtc)下不会发起 +/// RELAY 分配请求,导致控制端本地候选缺失 `typ relay`,两端无公共中继可 +/// 配对 → candidate-pair=0 → ICE Failed(Android 真机/网页则正常)。 +/// 改用 `turns:`(TLS over TCP 5349)后,模拟器能稳定拿到 relay 候选。 +/// 同时保留 udp / tcp 明文项作为降级,以及 STUN 用于 srflx。 const List> kIceServers = [ {'urls': 'stun:stun.l.google.com:19302'}, {'urls': 'stun:175.178.213.60:3478'}, { + // 首选:TLS over TCP,iOS 模拟器下能稳定分配 relay 候选。 + 'urls': 'turns:175.178.213.60:5349', + 'username': 'fanhuitong', + 'credential': 'Fan19961907..', + }, + { + // 降级:明文 UDP/TCP。 'urls': 'turn:175.178.213.60:3478', 'username': 'fanhuitong', 'credential': 'Fan19961907..', @@ -28,6 +37,12 @@ const List> kIceServers = [ 'username': 'fanhuitong', 'credential': 'Fan19961907..', }, + {'urls': 'stun:47.242.112.133:3478'}, + { + 'urls': 'turn:47.242.112.133:3478', + 'username': 'ttstd', + 'credential': 'fanhuitong', + }, ]; /// 信令 WebSocket 默认地址。