Browse Source
Tasked LivePlayer HLS softening, startup window, media recover, and onPlayError policy verify before build/deploy smoke.main
1 changed files with 214 additions and 0 deletions
@ -0,0 +1,214 @@ |
|||||
|
# Live Playback Stabilize 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:** Reduce dock live stutter / artifacting / full-player reconnects by tuning HLS for normal (non-LL) live and narrowing play-url rebuilds. |
||||
|
|
||||
|
**Architecture:** Keep responsibilities: `LivePlayer.vue` owns media attach/retry/recover; `useMonitorLive.js` owns session/lease/play-url. Soften hls.js for 6–12s segments, lengthen startup same-URL 404 window, attempt one media recover before bubbling fatals, leave TLS/403/57006 paths unchanged. |
||||
|
|
||||
|
**Tech Stack:** Vue 3, hls.js, existing Monitor live composable |
||||
|
|
||||
|
**Spec:** `docs/superpowers/specs/2026-09-03-live-playback-stabilize-design.md` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### Task 1: LivePlayer HLS config + startup window |
||||
|
|
||||
|
**Files:** |
||||
|
- Modify: `src/components/LivePlayer.vue` |
||||
|
|
||||
|
- [ ] **Step 1: Lengthen startup retry constants** |
||||
|
|
||||
|
Near top of `<script setup>` replace: |
||||
|
|
||||
|
```js |
||||
|
const STARTUP_RETRY_DELAYS_MS = [500, 1000, 2000, 4000] |
||||
|
const STARTUP_WINDOW_MS = 15_000 |
||||
|
``` |
||||
|
|
||||
|
with: |
||||
|
|
||||
|
```js |
||||
|
const STARTUP_RETRY_DELAYS_MS = [500, 1000, 2000, 4000, 6000, 8000] |
||||
|
const STARTUP_WINDOW_MS = 30_000 |
||||
|
``` |
||||
|
|
||||
|
- [ ] **Step 2: Switch Hls to normal live + wider load retries** |
||||
|
|
||||
|
In `attachPlayer`, replace the `new Hls({...})` block with: |
||||
|
|
||||
|
```js |
||||
|
// 现网为普通 6–12s HLS,不是 LL-HLS;放宽分片重试,启动 404 仍由同 URL 窗口控制 |
||||
|
hls = new Hls({ |
||||
|
enableWorker: true, |
||||
|
lowLatencyMode: false, |
||||
|
manifestLoadingMaxRetry: 2, |
||||
|
manifestLoadingRetryDelay: 1000, |
||||
|
levelLoadingMaxRetry: 2, |
||||
|
levelLoadingRetryDelay: 1000, |
||||
|
fragLoadingMaxRetry: 4, |
||||
|
fragLoadingRetryDelay: 1000, |
||||
|
}) |
||||
|
``` |
||||
|
|
||||
|
- [ ] **Step 3: One-shot media recover before bubbling other fatals** |
||||
|
|
||||
|
Still inside the `hls.on(Hls.Events.ERROR, ...)` handler, **after** the startup-404 branch and **before** the final `emitFatal` for generic fatals, insert: |
||||
|
|
||||
|
```js |
||||
|
// 播放中解码/媒体缓冲类 fatal:先尝试一次 recover,避免整段重建 |
||||
|
if (data.type === Hls.ErrorTypes.MEDIA_ERROR) { |
||||
|
try { |
||||
|
console.warn('[live-player] hls media fatal, recover once', data) |
||||
|
hls.recoverMediaError() |
||||
|
return |
||||
|
} catch (recoverErr) { |
||||
|
console.warn('[live-player] hls recover failed', recoverErr) |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
Keep existing branches for: |
||||
|
- `isSecurityFailure` → `SecurityError` fatal |
||||
|
- `httpCode === 403` → fatal |
||||
|
- startup `404` / `MANIFEST_LOAD_ERROR` → `scheduleSameUrlRetry` then fatal |
||||
|
|
||||
|
Do **not** call `recoverMediaError` for network/manifest fatals already handled above. |
||||
|
|
||||
|
- [ ] **Step 4: Static check** |
||||
|
|
||||
|
Run: |
||||
|
|
||||
|
```bash |
||||
|
rg -n "lowLatencyMode|STARTUP_WINDOW_MS|STARTUP_RETRY_DELAYS_MS|recoverMediaError|fragLoadingMaxRetry" src/components/LivePlayer.vue |
||||
|
``` |
||||
|
|
||||
|
Expected: |
||||
|
- `lowLatencyMode: false` |
||||
|
- `STARTUP_WINDOW_MS = 30_000` |
||||
|
- delays include `6000, 8000` |
||||
|
- `fragLoadingMaxRetry: 4` |
||||
|
- `recoverMediaError` present once |
||||
|
|
||||
|
- [ ] **Step 5: Commit** |
||||
|
|
||||
|
```bash |
||||
|
git add src/components/LivePlayer.vue |
||||
|
git commit -m "$(cat <<'EOF' |
||||
|
fix: stabilize LivePlayer for normal HLS live |
||||
|
|
||||
|
Disable lowLatencyMode, widen fragment retries, extend startup 404 |
||||
|
window to 30s, and recover media fatals once before bubbling. |
||||
|
EOF |
||||
|
)" |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### Task 2: Tighten `onPlayError` comments / branch clarity |
||||
|
|
||||
|
**Files:** |
||||
|
- Modify: `src/composables/useMonitorLive.js` |
||||
|
|
||||
|
Behavior should already mostly match the spec. This task only adjusts comments / ordering if needed so the policy is explicit; **do not** change heartbeat math, phase poll, stop gate, or 57006 rejoin. |
||||
|
|
||||
|
- [ ] **Step 1: Read current `onPlayError`** |
||||
|
|
||||
|
Confirm current order is effectively: |
||||
|
|
||||
|
1. ignore `AbortError` / `NotAllowedError` |
||||
|
2. ignore `recoverable === true` |
||||
|
3. `57006` → `rejoinAfterLeaseInvalid` |
||||
|
4. TLS/403 → `markPlayFatal` (no play-url refresh) |
||||
|
5. `HlsError` (startup exhausted etc.) → `markPlayFatal` |
||||
|
6. else limited `refreshPlayURL({ fromRetry: true })` up to `PLAY_RETRY_MAX` |
||||
|
|
||||
|
- [ ] **Step 2: If comments are misleading, rewrite the header comment only** |
||||
|
|
||||
|
Replace / add above `onPlayError`: |
||||
|
|
||||
|
```js |
||||
|
// 播放错误策略(稳播): |
||||
|
// - 启动 404 由 LivePlayer 同 URL 窗口消化,recoverable 不上冒 |
||||
|
// - TLS/403 致命,禁止刷 play-url |
||||
|
// - 其它 LivePlayer fatal:有限次 refreshPlayURL;57006 整段 rejoin |
||||
|
``` |
||||
|
|
||||
|
Only change control flow if Step 1 finds a real divergence from the spec (e.g. TLS path accidentally refreshing). Prefer minimal diff. |
||||
|
|
||||
|
- [ ] **Step 3: Commit (skip if no file change)** |
||||
|
|
||||
|
```bash |
||||
|
git add src/composables/useMonitorLive.js |
||||
|
git commit -m "docs: clarify live onPlayError stabilize policy" |
||||
|
``` |
||||
|
|
||||
|
If unchanged: |
||||
|
|
||||
|
```bash |
||||
|
git status -sb |
||||
|
``` |
||||
|
|
||||
|
Expected: clean for that file / nothing to commit. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### Task 3: Build + smoke notes + deploy |
||||
|
|
||||
|
**Files:** |
||||
|
- None required (verification) |
||||
|
|
||||
|
- [ ] **Step 1: Production build** |
||||
|
|
||||
|
```bash |
||||
|
npm run build |
||||
|
``` |
||||
|
|
||||
|
Expected: success (chunk size warnings OK). |
||||
|
|
||||
|
- [ ] **Step 2: Manual / API smoke checklist (dock-1)** |
||||
|
|
||||
|
Against deployed or local-proxied env: |
||||
|
|
||||
|
1. Open live on `dock-1` → may show「正在等待直播流就绪」briefly → picture appears (no instant fail on first 404). |
||||
|
2. Keep playing ~1–2 minutes → no frequent full black-flash reconnect loops. |
||||
|
3. Stop dialog → Cancel still closes only (no `/stop`). |
||||
|
4. Optional: confirm console no longer configures `lowLatencyMode: true`. |
||||
|
|
||||
|
If browser automation blocked, API-level checks from the design evidence section remain acceptable for start/play-url; UI reconnect feel still needs a human glance when possible. |
||||
|
|
||||
|
- [ ] **Step 3: Deploy (same pipeline as recent frontend ships)** |
||||
|
|
||||
|
```bash |
||||
|
git push origin main |
||||
|
tar -C dist -czf - . | ssh -o BatchMode=yes jg-serv1 'rm -rf /usr/share/nginx/laic-frontend/dist/* && tar -C /usr/share/nginx/laic-frontend/dist -xzf - && cat /usr/share/nginx/laic-frontend/dist/index.html' |
||||
|
``` |
||||
|
|
||||
|
- [ ] **Step 4: Final commit for plan doc if not already committed with earlier tasks** |
||||
|
|
||||
|
```bash |
||||
|
git add docs/superpowers/plans/2026-09-03-live-playback-stabilize.md |
||||
|
git commit -m "docs: add live playback stabilize plan" |
||||
|
``` |
||||
|
|
||||
|
(If this plan is committed before execution, do this step first; then execute Tasks 1–3.) |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## Spec coverage |
||||
|
|
||||
|
| Spec item | Task | |
||||
|
|-----------|------| |
||||
|
| `lowLatencyMode: false` + wider load retries | Task 1 | |
||||
|
| Startup delays + 30s window | Task 1 | |
||||
|
| `recoverMediaError` once for media fatals | Task 1 | |
||||
|
| TLS/403/57006 / recoverable unchanged | Task 1–2 | |
||||
|
| `onPlayError` limited refreshPlayURL | Task 2 (verify) | |
||||
|
| No http→https rewrite / no backend | all (non-goals) | |
||||
|
| build + dock-1 acceptance | Task 3 | |
||||
|
|
||||
|
## Out of scope reminders |
||||
|
|
||||
|
- Backend lease `57006` root cause |
||||
|
- `vpull` HTTPS certificate |
||||
|
- Forcing https playUrl |
||||
Loading…
Reference in new issue