Laev.Remux (laev v0.1.40)

Copy Markdown View Source

Local, on-the-fly HLS remuxer. Given a (range-seekable) source URL, ffmpeg stream-copies it into HLS segments on local disk — near-instant and lossless for h264/aac, hardware-encoding only when the codec isn't browser-playable.

Because segments are written faster than realtime and served from disk, the browser can seek anywhere the moment that part is segmented (seconds), which fixes the slow-seek problem of remote on-demand transcoders.

This is the public facade; Laev.Remux.Worker runs one ffmpeg per id.

Summary

Functions

Whether ffmpeg is available to remux at all.

Block until the remux is playable.

Temp directory holding this id's playlist and segments.

The playlist the browser should load: master.m3u8 for a multi-audio remux (switchable audio renditions), else the plain index.m3u8.

Start remuxing url into HLS. Returns {:ok, id}.

Stop a remux worker (kills ffmpeg, removes its temp dir). Safe on nil.

Path of the sub-track manifest the worker persists alongside the segments.

Embedded subtitle tracks discovered in the remuxed file (list of %{lang, file}).

Delete cached remux dirs older than the TTL (best-effort). Runs on each start/3 so old segments don't accumulate. Never touches a running remux.

Ids are 16 lowercase hex chars — validate before touching the filesystem.

Functions

available?()

Whether ffmpeg is available to remux at all.

await_ready(id, mode \\ :complete, timeout \\ 300_000)

Block until the remux is playable.

  • :complete (default) — wait for the finished VOD playlist (#EXT-X-ENDLIST). hls.js then loads a full VOD and plays from the start. Best for short content (an episode remuxes in ~20s); used so it never lands on a live edge.
  • :fast — wait for just the first few segments, then start (paired with hls.js startPosition: 0, which pins playback to the beginning). Good for movies, where a full remux would be a multi-minute wait.

dir(id)

Temp directory holding this id's playlist and segments.

entry_playlist(id)

The playlist the browser should load: master.m3u8 for a multi-audio remux (switchable audio renditions), else the plain index.m3u8.

start(url, filename \\ "", opts \\ [])

Start remuxing url into HLS. Returns {:ok, id}.

The id is derived from opts[:key] (a stable per-file identity, e.g. filename+size) so the same content always maps to the same folder. If a finished remux for that id is already on disk (fresh, #EXT-X-ENDLIST), it's reused instantly with no ffmpeg — so reloading a movie you'd remuxed before seeks anywhere immediately instead of re-remuxing from zero. A remux already running for that id is likewise reused rather than duplicated.

stop(id)

Stop a remux worker (kills ffmpeg, removes its temp dir). Safe on nil.

subs_manifest(id)

Path of the sub-track manifest the worker persists alongside the segments.

subtitles(id)

Embedded subtitle tracks discovered in the remuxed file (list of %{lang, file}).

sweep()

Delete cached remux dirs older than the TTL (best-effort). Runs on each start/3 so old segments don't accumulate. Never touches a running remux.

valid_id?(id)

Ids are 16 lowercase hex chars — validate before touching the filesystem.