Where a stream is played, and how its progress gets back.
laev grew up launching a player on the machine it runs on, which is the only thing a terminal can do. A web interface can do that too — the server and the browser are the same computer, for somebody running this at home — but the obvious thing for it to do is play the film in the page, and that is what it does unless told otherwise.
So there are three targets and one setting between them:
browser— the stream goes to a<video>in the page. The default anywhere but the terminal.mpv/vlc— the player on the machine, launched as the CLI launches it, for anyone who would rather watch in their own player.
What the browser gets back is a source, not a file. Most releases are h265
in Matroska, which no browser opens, so they are remuxed into HLS on the way
through — Laev.Remux stream-copies them with ffmpeg, which is lossless and
near-instant for anything already h264, and segments land on disk fast enough
that seeking works almost at once. Where a release is something a browser can
read already, the direct link is handed over instead, because remuxing what
does not need it costs time for nothing.
Real-Debrid's own transcoder is deliberately not used: it still answers, but the URLs it returns have no host in them and its media-info endpoint replies 503, so what it offers cannot be played. Remuxing locally is both working and ours.
Progress comes back through progress/3, which works out what was watched
and what was skipped the same way the mpv script and the VLC poller do —
except from the file rather than from memory, since a browser posting every
few seconds is a different request each time and remembers nothing.
Summary
Functions
The players this user could choose between.
What the page needs to play this stream.
How long this user has been watching the thing in front of them.
Which playlist to serve for a remux, asked when serving rather than when starting.
Record where the browser's player has got to.
Wait until there is enough on disk to start playing — :fast for the first
few segments, :complete for the whole thing.
Start playing, wherever this user's playback goes.
Any subtitle tracks pulled out of the release, as WebVTT next to the
segments — a browser needs them as separate files, which is the one thing a
<video> cannot take from the container itself.
Where playback should go for whoever is asking: :browser, :mpv or :vlc.
Functions
The players this user could choose between.
The browser is offered to a web interface and withheld from the terminal, which has no page to play anything in; a local player is offered only where it is actually installed, since a list of things that will not work is worse than a short list.
What the page needs to play this stream.
{:ok, %{kind: :hls | :direct, url:, resume_at:, …}}. HLS where the release
is not something a browser can read, which is most of them.
How long this user has been watching the thing in front of them.
Which playlist to serve for a remux, asked when serving rather than when starting.
ffmpeg decides between a single playlist and a master with one variant per audio track, and it decides it after it has looked at the file — so a name captured at the moment the remux was started is a guess, and was the wrong one for every release with more than one audio track.
Record where the browser's player has got to.
Stateless on purpose: a browser posts a position every few seconds and each post is its own request, so what was watched since last time is worked out from what is already written down rather than from anything held in memory. The rules are the ones every other player here follows — a position under half a minute is the beginning, past 85% is watched, and a jump is skipped rather than watched.
Wait until there is enough on disk to start playing — :fast for the first
few segments, :complete for the whole thing.
Start playing, wherever this user's playback goes.
For a local player this launches it and says so. For the browser it returns what the page needs to play the thing: a URL, how it should be read, where to start, and any subtitle laev fetched.
Any subtitle tracks pulled out of the release, as WebVTT next to the
segments — a browser needs them as separate files, which is the one thing a
<video> cannot take from the container itself.
Where playback should go for whoever is asking: :browser, :mpv or :vlc.