2 changed files with 106 additions and 79 deletions
@ -0,0 +1,93 @@ |
|||||
|
import { computed, reactive } from 'vue' |
||||
|
import { getLivePlayURL, heartbeatLive, joinLive, leaveLive } from '@/api/live' |
||||
|
|
||||
|
export function useMonitorLive({ getDockId, ui, getLivePlayer }) { |
||||
|
const live = reactive({ session: null, dockId: '', playUrl: '', heartbeatTimer: null }) |
||||
|
|
||||
|
const livePhaseText = computed(() => { |
||||
|
if (!live.session) return '待机' |
||||
|
const phase = live.session.phase |
||||
|
if (phase === 'streaming') return live.playUrl.startsWith('fake://') ? '模拟直播' : '直播中' |
||||
|
if (phase === 'starting') return '启动中' |
||||
|
if (phase === 'reconnecting') return '重连中' |
||||
|
if (phase === 'stopping') return '停止中' |
||||
|
if (phase === 'failed') return '启动失败' |
||||
|
return '已停止' |
||||
|
}) |
||||
|
|
||||
|
const canFullscreenLive = computed(() => !!live.playUrl && !live.playUrl.startsWith('fake://')) |
||||
|
|
||||
|
function toggleLive() { |
||||
|
if (live.session) closeLive() |
||||
|
else openLive() |
||||
|
} |
||||
|
|
||||
|
function fullscreenLive() { |
||||
|
if (!canFullscreenLive.value) { |
||||
|
ui.toast('当前无可全屏播放的视频流') |
||||
|
return |
||||
|
} |
||||
|
const ok = getLivePlayer()?.requestFullscreen?.() |
||||
|
if (!ok) ui.toast('当前浏览器不支持全屏') |
||||
|
} |
||||
|
|
||||
|
async function openLive() { |
||||
|
const dockId = getDockId?.() |
||||
|
if (!dockId) return |
||||
|
try { |
||||
|
const result = await joinLive(dockId) |
||||
|
live.session = result.session |
||||
|
live.dockId = dockId |
||||
|
scheduleLiveHeartbeat(result.leaseExpiresAt) |
||||
|
if (result.session.phase === 'streaming') await refreshPlayURL() |
||||
|
} catch (e) { |
||||
|
ui.toast(e.message || '打开直播失败') |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function refreshPlayURL() { |
||||
|
if (!live.dockId) return |
||||
|
const play = await getLivePlayURL(live.dockId) |
||||
|
live.playUrl = play.playUrl || '' |
||||
|
} |
||||
|
|
||||
|
function scheduleLiveHeartbeat(expiresAt) { |
||||
|
window.clearTimeout(live.heartbeatTimer) |
||||
|
const delay = Math.max(5000, (Number(expiresAt) * 1000 - Date.now()) / 2) |
||||
|
live.heartbeatTimer = window.setTimeout(async () => { |
||||
|
try { |
||||
|
const result = await heartbeatLive(live.dockId, live.session.id) |
||||
|
live.session = result.session |
||||
|
scheduleLiveHeartbeat(result.leaseExpiresAt) |
||||
|
if (result.session.phase === 'streaming' && !live.playUrl) await refreshPlayURL() |
||||
|
} catch (e) { |
||||
|
ui.toast(e.message || '直播观看已结束') |
||||
|
await closeLive(false) |
||||
|
} |
||||
|
}, delay) |
||||
|
} |
||||
|
|
||||
|
async function closeLive(sendRequest = true) { |
||||
|
window.clearTimeout(live.heartbeatTimer) |
||||
|
const session = live.session |
||||
|
const dockId = live.dockId |
||||
|
live.session = null |
||||
|
live.dockId = '' |
||||
|
live.playUrl = '' |
||||
|
if (sendRequest && session && dockId) { |
||||
|
try { |
||||
|
await leaveLive(dockId, session.id) |
||||
|
} catch (_) {} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
live, |
||||
|
livePhaseText, |
||||
|
canFullscreenLive, |
||||
|
toggleLive, |
||||
|
fullscreenLive, |
||||
|
openLive, |
||||
|
closeLive, |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue