From da0bcae823369cdd05be22968041d3a7e13ee3ba Mon Sep 17 00:00:00 2001 From: whm <973418690@qq.com> Date: Wed, 25 Mar 2026 16:55:05 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9B=B4=E6=92=AD=E8=A7=82=E4=BC=97=EF=BC=9Ane?= =?UTF-8?q?gotiate=20=E5=A4=B1=E8=B4=A5=E5=90=8E=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E8=BD=AE=E8=AF=A2=EF=BC=9B=E9=98=B2=E5=B9=B6=E5=8F=91=20poll?= =?UTF-8?q?=EF=BC=9B=E9=95=BF=E6=97=B6=20502=20=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made-with: Cursor --- web/src/utils/liveWebRTC.js | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/web/src/utils/liveWebRTC.js b/web/src/utils/liveWebRTC.js index 2368f12..f774ed3 100644 --- a/web/src/utils/liveWebRTC.js +++ b/web/src/utils/liveWebRTC.js @@ -47,6 +47,8 @@ export function startViewing(videoEl, opts = {}) { let ws = null let pollTimer = null let currentPollMs = pollMs + let pollInFlight = false + let upstreamErrorStreak = 0 let stopped = false let blackFrameTimer = null @@ -109,8 +111,12 @@ export function startViewing(videoEl, opts = {}) { if (pollTimer) return rebuildPeer() currentPollMs = pollMs + upstreamErrorStreak = 0 schedulePollLoop() - poll() + // 下一轮再 poll,避免从 poll() 内同步调用时 pollInFlight 仍为 true 导致被跳过 + setTimeout(() => { + if (!stopped) poll() + }, 0) } async function negotiate() { @@ -173,10 +179,17 @@ export function startViewing(videoEl, opts = {}) { async function poll() { if (stopped) return + if (pollInFlight) return + pollInFlight = true try { const { live, upstreamError } = await fetchLiveStatus() if (upstreamError) { - onStatus('无法连接服务器(网关 502/离线),将放慢重试…') + upstreamErrorStreak += 1 + const extra = + upstreamErrorStreak >= 6 + ? ' 若长时间如此,多为服务端未启动或网关异常,请刷新页面或联系管理员。' + : '' + onStatus(`无法连接服务器(网关 502/离线),将放慢重试…${extra}`) const next = Math.min(Math.round(currentPollMs * 1.5), 30000) if (next !== currentPollMs) { currentPollMs = next @@ -184,6 +197,7 @@ export function startViewing(videoEl, opts = {}) { } return } + upstreamErrorStreak = 0 if (currentPollMs !== pollMs) { currentPollMs = pollMs schedulePollLoop() @@ -195,12 +209,23 @@ export function startViewing(videoEl, opts = {}) { } onLive() onStatus('检测到直播,正在连接…') - await negotiate() + try { + await negotiate() + } catch (err) { + onStatus( + err?.message + ? `拉流连接失败:${err.message}` + : '拉流连接失败,将恢复轮询…' + ) + resumePollingAfterDisconnect('') + } return } onStatus('等待主播开播…') } catch { onStatus('无法获取直播状态') + } finally { + pollInFlight = false } }