Skip to content
Console

Convert HLS to MP4

A segment sink writes HLS to object storage — a playlist plus .ts or .m4s segments — not a single MP4. To get a file you can drop into an editor or send to someone, remux the finalized playlist locally with ffmpeg.

H.264 + AAC (the recommended encoding for this sink) copies into MP4 without re-encoding.

Pick one, then confirm with ffmpeg -version.

macOS (Homebrew):

Terminal window
brew install ffmpeg

Windows (WinGet), or download a build from ffmpeg.org:

Terminal window
winget install ffmpeg

Debian / Ubuntu:

Terminal window
sudo apt update && sudo apt install ffmpeg

The playlist is live until the job stops. Finalize writes #EXT-X-ENDLIST and, if you used a sliding window, puts every segment back in. Convert after a terminal status — or a job.completed webhook — not while the job is still running. See Record a room.

-c copy remuxes. It does not transcode, so it is fast and does not change quality.

If the objects are public, or you have a signed URL that can also fetch the sibling segments:

Terminal window
ffmpeg -i "https://<bucket>/<pathPrefix>/index.m3u8" -c copy recording.mp4

filename defaults to index → index.m3u8. If you set filename in the sink config, use that basename instead.

If the bucket is private, download the whole prefix (playlist + segments) and remux on disk. Relative URIs in the playlist resolve next to the .m3u8:

Terminal window
aws s3 sync "s3://recordings/rooms/my-room/2026-08-19/" ./hls/
ffmpeg -i ./hls/index.m3u8 -c copy recording.mp4

The same idea works with gsutil -m rsync or az storage blob download-batch. You need the playlist and every seg_*.ts / seg_*.m4s it lists. fMP4 recordings also have init_*.mp4 — the playlist’s EXT-X-MAP points at them.

When asr is wired into the sink, the canonical {filename}.m3u8 is a master playlist:

ObjectRole
{filename}.m3u8Master (playable entry)
{filename}_media.m3u8Audio / video
{filename}_subs.m3u8 + {filename}_subs.vttWebVTT, uploaded on finalize

ffmpeg on the master usually picks the A/V variant. To mux the VTT into the MP4 as a text track:

Terminal window
ffmpeg -i ./hls/recording.m3u8 -i ./hls/recording_subs.vtt \
-c copy -c:s mov_text recording.mp4

Use {filename}_media.m3u8 if you only want audio and video.

A discontinuity (late audio or video, a codec change) or an unusual codec pair can make -c copy refuse the MP4 container. Re-encode only then — it is slower:

Terminal window
ffmpeg -i ./hls/index.m3u8 -c:v libx264 -c:a aac recording.mp4