# `Fmp4.RangeFile`
[🔗](https://github.com/alexdont/fmp4/blob/v0.1.0/lib/fmp4/range_file.ex#L2)

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

# `send`

```elixir
@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"`).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
