# Monitor HLS Playback Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 监控详情页可在 Chrome/Edge 真实播放 HLS,并补齐启动轮询、playUrl 续期、播放错误重建、停止直播与退出观看分离。 **Architecture:** `LivePlayer` 只负责媒体(Safari 原生 HLS / 其他动态 `import('hls.js')`);`useMonitorLive` 管 join、phase 轮询、heartbeat、playUrl 续期、错误重试、leave/stop;`MonitorDetailPanel` 标题行加「停止直播」按钮。 **Tech Stack:** Vue 3、`hls.js`、现有 axios `src/utils/http.js`、Pinia `useUiStore`、`useMonitorLive` / `LivePlayer` / `MonitorDetailPanel` **Spec:** `docs/superpowers/specs/2026-09-02-monitor-hls-playback-design.md` --- ## File map | 文件 | 职责 | |---|---| | `package.json` / `package-lock.json` | 增加 `hls.js` | | `src/config/urls.js` | `LIVE_SESSION` / `LIVE_STOP` | | `src/api/live.js` | `getLiveSession` / `stopLive` | | `src/components/LivePlayer.vue` | HLS 挂载/销毁/错误上报 | | `src/composables/useMonitorLive.js` | 轮询、续期、重试、stop | | `src/components/MonitorDetailPanel.vue` | 「停止直播」按钮 + emit | | `src/views/MonitorView/MonitorView.vue` | 接线 `onPlayError` / `stopLiveStream` | 辅助约定: - 请求:`import request from '@/utils/http'`(成功已解包 `res.data`) - Toast / Confirm:`ui.toast(...)` / `await ui.confirm(title, desc, checks?)` - `GET .../sessions/:id` 解包后是 **`LiveSession` 本体**(含 `phase`/`id`),不是 `{ session }` - 本仓库无前端单测惯例:用 `npm run build` + 静态核对;不新增测试文件 - 精确 `git add`;commit 信息简短祈使句 --- ### Task 1: 安装 hls.js + URL/API **Files:** - Modify: `package.json` / `package-lock.json` - Modify: `src/config/urls.js` - Modify: `src/api/live.js` - [ ] **Step 1: 安装依赖** ```bash npm install hls.js ``` 确认 `package.json` `dependencies` 出现 `hls.js`。 - [ ] **Step 2: URL 常量** 在 `src/config/urls.js` 现有 live 段落后追加: ```js export const LIVE_SESSION = (dockId, sessionId) => `/v1/live/${dockId}/sessions/${sessionId}` export const LIVE_STOP = (dockId) => `/v1/live/${dockId}/stop` ``` 保留现有: ```js export const LIVE_SESSIONS = (dockId) => `/v1/live/${dockId}/sessions` export const LIVE_PLAY_URL = (dockId) => `/v1/live/${dockId}/play-url` export const LIVE_HEARTBEAT = (dockId, sessionId) => `/v1/live/${dockId}/sessions/${sessionId}/heartbeat` export const LIVE_LEAVE = (dockId, sessionId) => `/v1/live/${dockId}/sessions/${sessionId}/viewers/me` ``` - [ ] **Step 3: API 封装** `src/api/live.js` 最终应为: ```js import request from '@/utils/http' export function joinLive(dockId, payload = {}) { return request.post(`/v1/live/${dockId}/sessions`, payload) } export function getLiveSession(dockId, sessionId) { return request.get(`/v1/live/${dockId}/sessions/${sessionId}`) } export function getLivePlayURL(dockId, sessionId) { return request.get(`/v1/live/${dockId}/play-url`, { params: { streamSessionId: sessionId } }) } export function heartbeatLive(dockId, sessionId) { return request.post(`/v1/live/${dockId}/sessions/${sessionId}/heartbeat`) } export function leaveLive(dockId, sessionId) { return request.delete(`/v1/live/${dockId}/sessions/${sessionId}/viewers/me`) } export function stopLive(dockId) { return request.post(`/v1/live/${dockId}/stop`) } ``` - [ ] **Step 4: Commit** ```bash git add package.json package-lock.json src/config/urls.js src/api/live.js git commit -m "feat: add hls.js and live session/stop APIs" ``` --- ### Task 2: LivePlayer HLS 适配 **Files:** - Modify: `src/components/LivePlayer.vue` - [ ] **Step 1: 重写组件(template 去掉 :src 绑定)** 完整文件: ```vue {{ cameraLabel }} {{ qualityText }} {{ statusMessage }} ``` 若原文件另有 `