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