fix(playout/web-ui): no-store on live HLS m3u8 so hls.js sees the live edge

Definitive root cause of the black preview, proven in-browser: the live
.m3u8 was served Cache-Control: no-cache, so the browser cached the
playlist and served a STALE copy to hls.js's reloads (cache:'default'
stuck at one MEDIA-SEQUENCE while cache:'reload' advanced). hls.js saw the
live playlist as never advancing -> "live playlist MISSED" forever ->
never established the timeline -> never loaded a fragment -> readyState 0
(black), even though the stream itself is clean and advancing server-side.

Fix: serve live HLS (/live and /media/live) with
"no-store, no-cache, must-revalidate" + Pragma no-cache so the browser
never caches the playlist and every reload fetches the fresh live edge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Zac Gaetano 2026-05-31 15:45:28 -04:00
parent 59551f28a5
commit 24d10fda5d

View file

@ -61,12 +61,19 @@ server {
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# Live HLS served from /live (bind-mounted capture live volume)
# Live HLS served from /live (bind-mounted capture live volume).
# no-store (not just no-cache): with "no-cache" the browser still caches the
# playlist and serves a STALE copy to hls.js's reloads, so hls.js sees the
# live playlist as never advancing ("MISSED" forever) and never plays the
# monitor stays black. no-store forbids caching entirely so every reload
# fetches the fresh live edge. Segments are short-lived; not caching them is
# fine for a live preview.
location /live/ {
alias /live/;
types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
add_header Cache-Control "no-cache";
add_header Access-Control-Allow-Origin *;
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Access-Control-Allow-Origin * always;
}
# Playout HLS preview CasparCG sidecar writes to the media volume under
@ -74,8 +81,9 @@ server {
location /media/live/ {
alias /media/live/;
types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
add_header Cache-Control "no-cache";
add_header Access-Control-Allow-Origin *;
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Access-Control-Allow-Origin * always;
}
# API proxy - forward to mam-api service