|
|
@ -305,57 +305,60 @@ async function openLive(stream) { |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
await closeActiveLive() |
|
|
|
|
|
if (disposed) return |
|
|
|
|
|
opening = true |
|
|
opening = true |
|
|
const seq = ++openSeq |
|
|
|
|
|
try { |
|
|
try { |
|
|
const result = await joinLiveWithRetry(stream.dockId, {}, { |
|
|
|
|
|
shouldContinue: () => seq === openSeq && !disposed && opening, |
|
|
|
|
|
}) |
|
|
|
|
|
const session = result?.session |
|
|
|
|
|
const sessionId = session?.id |
|
|
|
|
|
|
|
|
await closeActiveLive() |
|
|
|
|
|
if (disposed) return |
|
|
|
|
|
const seq = ++openSeq |
|
|
|
|
|
try { |
|
|
|
|
|
const result = await joinLiveWithRetry(stream.dockId, {}, { |
|
|
|
|
|
shouldContinue: () => seq === openSeq && !disposed && opening, |
|
|
|
|
|
}) |
|
|
|
|
|
const session = result?.session |
|
|
|
|
|
const sessionId = session?.id |
|
|
|
|
|
|
|
|
|
|
|
if (seq !== openSeq || disposed) { |
|
|
|
|
|
if (sessionId) await safeLeave(stream.dockId, sessionId) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (seq !== openSeq || disposed) { |
|
|
|
|
|
if (sessionId) await safeLeave(stream.dockId, sessionId) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (!sessionId) { |
|
|
|
|
|
ui.toast('直播会话无效') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (!sessionId) { |
|
|
|
|
|
ui.toast('直播会话无效') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
activeLive.id = stream.id |
|
|
|
|
|
activeLive.dockId = stream.dockId |
|
|
|
|
|
activeLive.sessionId = sessionId |
|
|
|
|
|
activeLive.phase = session.phase || '' |
|
|
|
|
|
activeLive.playUrl = '' |
|
|
|
|
|
activeLive.playUrlExpiresAt = 0 |
|
|
|
|
|
scheduleHeartbeat(result.leaseExpiresAt) |
|
|
|
|
|
|
|
|
activeLive.id = stream.id |
|
|
|
|
|
activeLive.dockId = stream.dockId |
|
|
|
|
|
activeLive.sessionId = sessionId |
|
|
|
|
|
activeLive.phase = session.phase || '' |
|
|
|
|
|
activeLive.playUrl = '' |
|
|
|
|
|
activeLive.playUrlExpiresAt = 0 |
|
|
|
|
|
scheduleHeartbeat(result.leaseExpiresAt) |
|
|
|
|
|
|
|
|
|
|
|
if (session.phase !== 'streaming') { |
|
|
|
|
|
ui.toast('直播正在启动,请稍后重试') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (session.phase !== 'streaming') { |
|
|
|
|
|
ui.toast('直播正在启动,请稍后重试') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const play = await ensurePlayUrl(stream.dockId, sessionId) |
|
|
|
|
|
if (seq !== openSeq || disposed || activeLive.sessionId !== sessionId) return |
|
|
|
|
|
if (play?.playUrl && !play.playUrl.startsWith('fake://')) { |
|
|
|
|
|
if (!activeLive.playUrl) { |
|
|
|
|
|
activeLive.playUrl = play.playUrl |
|
|
|
|
|
|
|
|
const play = await ensurePlayUrl(stream.dockId, sessionId) |
|
|
|
|
|
if (seq !== openSeq || disposed || activeLive.sessionId !== sessionId) return |
|
|
|
|
|
if (play?.playUrl && !play.playUrl.startsWith('fake://')) { |
|
|
|
|
|
if (!activeLive.playUrl) { |
|
|
|
|
|
activeLive.playUrl = play.playUrl |
|
|
|
|
|
} |
|
|
|
|
|
} else if (!activeLive.playUrl) { |
|
|
|
|
|
ui.toast('控制面已验证,当前未配置可播放媒体流') |
|
|
} |
|
|
} |
|
|
} else if (!activeLive.playUrl) { |
|
|
|
|
|
ui.toast('控制面已验证,当前未配置可播放媒体流') |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
if (seq !== openSeq || disposed || e?.code === 'ABORTED') return |
|
|
|
|
|
if (isLeaseInvalidError(e)) { |
|
|
|
|
|
await rejoinAfterLeaseInvalid(stream.id, stream.dockId) |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
if (seq !== openSeq || disposed || e?.code === 'ABORTED') return |
|
|
|
|
|
if (isLeaseInvalidError(e)) { |
|
|
|
|
|
opening = false // unlock before nested openLive via rejoin |
|
|
|
|
|
await rejoinAfterLeaseInvalid(stream.id, stream.dockId) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
await closeActiveLive() |
|
|
|
|
|
ui.toast(e.message || '打开直播失败') |
|
|
} |
|
|
} |
|
|
await closeActiveLive() |
|
|
|
|
|
ui.toast(e.message || '打开直播失败') |
|
|
|
|
|
} finally { |
|
|
} finally { |
|
|
opening = false |
|
|
opening = false |
|
|
} |
|
|
} |
|
|
|