6.7 KiB
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:
const STARTUP_RETRY_DELAYS_MS = [500, 1000, 2000, 4000]
const STARTUP_WINDOW_MS = 15_000
with:
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:
// 现网为普通 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:
// 播放中解码/媒体缓冲类 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→SecurityErrorfatalhttpCode === 403→ fatal- startup
404/MANIFEST_LOAD_ERROR→scheduleSameUrlRetrythen fatal
Do not call recoverMediaError for network/manifest fatals already handled above.
- Step 4: Static check
Run:
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 -
recoverMediaErrorpresent once -
Step 5: Commit
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:
- ignore
AbortError/NotAllowedError - ignore
recoverable === true 57006→rejoinAfterLeaseInvalid- TLS/403 →
markPlayFatal(no play-url refresh) HlsError(startup exhausted etc.) →markPlayFatal- else limited
refreshPlayURL({ fromRetry: true })up toPLAY_RETRY_MAX
- Step 2: If comments are misleading, rewrite the header comment only
Replace / add above onPlayError:
// 播放错误策略(稳播):
// - 启动 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)
git add src/composables/useMonitorLive.js
git commit -m "docs: clarify live onPlayError stabilize policy"
If unchanged:
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
npm run build
Expected: success (chunk size warnings OK).
- Step 2: Manual / API smoke checklist (dock-1)
Against deployed or local-proxied env:
- Open live on
dock-1→ may show「正在等待直播流就绪」briefly → picture appears (no instant fail on first 404). - Keep playing ~1–2 minutes → no frequent full black-flash reconnect loops.
- Stop dialog → Cancel still closes only (no
/stop). - 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)
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
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
57006root cause vpullHTTPS certificate- Forcing https playUrl