Fmp4.RangeFile (fmp4 v0.1.0)

Copy Markdown View Source

Serves a file to a video element with HTTP range requests, including a file that is still being written. Any file: a fragmented MP4 a playlist from Fmp4.playlist/3 points at, a plain MP4, a Matroska release.

A browser plays a plain MP4 by asking for byte ranges (Safari starts with bytes=0-1 to learn the size), so a file has to answer 206 with Content-Range. A file still growing (growing?: true) has no total yet: its ranges are answered with * for the total, a piece at a time so the browser asks again as it fills, and a request past what exists so far waits for the writer to catch up before giving up with 416.

def media(conn, %{"name" => name}) do
  Fmp4.RangeFile.send(conn, path(name), "video/mp4", growing?: not finished?(name))
end

Summary

Functions

Sends the file, answering the request's Range header. Options

Functions

send(conn, path, content_type, opts \\ [])

@spec send(Plug.Conn.t(), Path.t(), String.t(), keyword()) :: Plug.Conn.t()

Sends the file, answering the request's Range header. Options:

  • growing? — the file is still being written (default false). Sets cache-control: no-store, answers at most :chunk bytes per range, and waits up to :wait ms for bytes not written yet.
  • chunk — bytes per answered range while growing (default 1 MiB).
  • wait — ms to wait for a growing file to reach the range asked for (default 20 000), checked every :poll ms (default 200).
  • cache_control — the header for a finished file (default "private, max-age=3600").