files: seek anywhere in a re-encode; it restarts from there
A re-encode's playlist is now the whole film on a fixed 4 s grid. A segment that isn't on disk and isn't coming soon moves the encode there; runs stop short of segments already made, and gaps are filled after. Every run is cut the same way (-ss, -output_ts_offset start+10, frag_discont), so segments from different runs join. Repackaging keeps its growing playlist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ff1373e838
commit
450a9d3327
+27
-3
@@ -146,24 +146,48 @@ func (s *Server) playStop(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// playFile: GET /api/files/play/{id}/{file} — the playlist, the init segment, a segment.
|
||||
// A seekable stream's playlist is written whole, up front; a segment of it that isn't on disk
|
||||
// yet is waited for, or re-encoded from there if the encode isn't heading that way (a seek).
|
||||
func (s *Server) playFile(w http.ResponseWriter, r *http.Request) {
|
||||
st, ok := s.plays.Find(r.PathValue("id"))
|
||||
if !ok {
|
||||
jsonErr(w, 404, "no such stream")
|
||||
return
|
||||
}
|
||||
p, ok := st.File(r.PathValue("file"))
|
||||
name := r.PathValue("file")
|
||||
p, ok := st.File(name)
|
||||
if !ok {
|
||||
jsonErr(w, 404, "not a stream file")
|
||||
return
|
||||
}
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
if st.Seekable {
|
||||
if name == "index.m3u8" {
|
||||
w.Header().Set("Content-Type", "application/vnd.apple.mpegurl")
|
||||
_, _ = w.Write(st.Playlist())
|
||||
return
|
||||
}
|
||||
if i, isSeg := media.SegmentIndex(name); isSeg {
|
||||
sp, err := st.Segment(r.Context(), i)
|
||||
switch {
|
||||
case errors.Is(err, media.ErrNotInFilm):
|
||||
jsonErr(w, 404, err.Error())
|
||||
return
|
||||
case r.Context().Err() != nil:
|
||||
return // the player moved on
|
||||
case err != nil:
|
||||
jsonErr(w, 503, err.Error())
|
||||
return
|
||||
}
|
||||
p = sp
|
||||
}
|
||||
}
|
||||
switch filepath.Ext(p) {
|
||||
case ".m3u8":
|
||||
w.Header().Set("Content-Type", "application/vnd.apple.mpegurl")
|
||||
default:
|
||||
w.Header().Set("Content-Type", "video/mp4")
|
||||
}
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
http.ServeFile(w, r, p)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user