From 53166b648f74f79041ba3656ba510362985c908c Mon Sep 17 00:00:00 2001 From: stary <834207172@qq.com> Date: Sat, 16 May 2026 18:16:57 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90m=E3=80=91=E8=A7=A3=E5=86=B3=E8=BF=9C?= =?UTF-8?q?=E7=AB=AF=E9=BB=91=E5=B1=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/renderstreaming.js | 14 +++++++------- src/class/websockethandler.ts | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/client/src/renderstreaming.js b/client/src/renderstreaming.js index 52cbef1..a42f7df 100644 --- a/client/src/renderstreaming.js +++ b/client/src/renderstreaming.js @@ -75,10 +75,11 @@ export class RenderStreaming { if (this._isHost) { // host端:为该participant创建或复用peer + // host端始终使用polite=false(impolite),确保perfect negotiation中host的offer优先 let peer = this._peers.get(participantId); if (!peer || (peer.pc && peer.pc.iceConnectionState === 'disconnected')) { if (peer) peer.close(); - peer = this._preparePeerConnection(this._connectionId, offer.polite, participantId); + peer = this._preparePeerConnection(this._connectionId, false, participantId); } const desc = new RTCSessionDescription({ sdp: offer.sdp, type: "offer" }); try { @@ -87,13 +88,13 @@ export class RenderStreaming { Logger.warn(`Error on GotDescription for participant ${participantId}: ${error}`); } } else { - // participant端:使用单一peer + // participant端:使用单一peer,始终使用polite=true if (this._peer && this._peer.pc && this._peer.pc.iceConnectionState === 'disconnected') { this._peer.close(); this._peer = null; } if (!this._peer) { - this._preparePeerConnection(offer.connectionId, offer.polite, null); + this._preparePeerConnection(offer.connectionId, true, null); } const desc = new RTCSessionDescription({ sdp: offer.sdp, type: "offer" }); try { @@ -171,10 +172,9 @@ export class RenderStreaming { const participantId = data.participantId; Logger.log(`Participant joined: ${participantId}`); - // host端:为新participant创建peer - if (this._isHost && !this._peers.has(participantId)) { - this._preparePeerConnection(this._connectionId, false, participantId); - } + // host端:不在此处创建peer,等待participant的offer到达后在_onOffer中创建 + // 这样避免host和participant同时发offer导致的glare冲突 + // _onOffer会在收到participant的offer时自动创建peer(如果不存在) this.onParticipantJoined(participantId); } diff --git a/src/class/websockethandler.ts b/src/class/websockethandler.ts index 2acf2de..53eb5cb 100644 --- a/src/class/websockethandler.ts +++ b/src/class/websockethandler.ts @@ -239,7 +239,8 @@ function onOffer(ws: WebSocket, message: any): void { } } else { // participant发送offer给host,携带该participant的participantId - newOffer.polite = true; + // host端应为impolite(polite=false),确保perfect negotiation中host优先 + newOffer.polite = false; group.host.send(JSON.stringify({ from: connectionId, to: "", type: "offer", data: newOffer, participantId: senderParticipantId })); } }