Record a room (grid layout)
Record every participant in an RTC room to S3 as HLS. A segment sink takes a single composed stream, so an RTC room has to pass through video_mixer and audio_mixer first — connecting a room directly is rejected at submit time.
1. Prepare credentials
Section titled “1. Prepare credentials”You need two things:
- A subscribe token for the room. See LiveKit token docs.
- A bucket plus a key pair that can write to it. Any S3-compatible endpoint works via
endpointandforcePathStyle; GCS and Azure are also supported — see Storage config.
2. Submit the job
Section titled “2. Submit the job”curl -X POST "https://api.avflow.dev/v1/jobs" \ -H "Authorization: Bearer ${AVFLOW_API_KEY}" \ -H "Content-Type: application/json" \ -d @public/examples/02-room-grid-recording.jsonOr inline:
{ "name": "room-grid-recording", "sources": [{ "name": "room_src", "type": "livekit", "config": { "serverUrl": "wss://your-project.livekit.cloud", "token": "<subscribe-token>" } }], "nodes": [{ "name": "mix_video", "type": "video_mixer", "inputs": ["room_src"], "config": { "canvas": { "width": 1280, "height": 720, "fps": 30 }, "layout": { "mode": "grid", "grid": { "maxColumns": 3, "gap": 4 } } } }, { "name": "mix_audio", "type": "audio_mixer", "inputs": ["room_src"] }], "sinks": [{ "name": "segment_out", "type": "segment", "inputs": ["mix_video", "mix_audio"], "config": { "storageType": "s3", "storageConfig": { "bucket": "recordings", "region": "us-east-1", "accessKeyId": "<key-id>", "secretAccessKey": "<secret>", "pathPrefix": "rooms/{roomName}/{date}/", "filename": "{roomName}_{timestamp}" }, "segmentDurationSec": 6, "encoding": { "videoCodec": "h264", "audioCodec": "aac" } } }], "policies": { "maxDurationSec": 14400, "idleTimeoutSec": 120 }}encoding is optional: omitted codecs default to H.264 + AAC. Drop a media type with select.mediaTypes if the sink should not receive it.
3. Monitor
Section titled “3. Monitor”curl "https://api.avflow.dev/v1/jobs/room-grid-recording" \ -H "Authorization: Bearer ${AVFLOW_API_KEY}"Wait for status: "running". Segments start appearing under your pathPrefix within a few segment durations. {roomName}, {date}, and {timestamp} are expanded at write time — see Path templates.
4. Stop
Section titled “4. Stop”curl -X DELETE "https://api.avflow.dev/v1/jobs/room-grid-recording" \ -H "Authorization: Bearer ${AVFLOW_API_KEY}"Stopping matters for more than billing: the playlist is finalized on stop. Until then you have a live playlist and the segments written so far. If your application processes the recording afterwards, wait for a terminal status — or a webhook — rather than reading the playlist while the job runs.
policies.maxDurationSec above caps the recording at four hours as a safety net, and idleTimeoutSec ends the job two minutes after the room goes quiet, so an abandoned meeting stops billing on its own.
5. Convert to MP4
Section titled “5. Convert to MP4”The sink writes HLS. To get a single MP4 on your laptop, remux the finalized playlist with ffmpeg:
ffmpeg -i ./hls/index.m3u8 -c copy recording.mp4Install ffmpeg, when to wait for #EXT-X-ENDLIST, private-bucket download, and captions are in Convert HLS to MP4.
Variations
Section titled “Variations”Follow the speaker instead of a grid. Change the layout to speaker mode with an ordered mainPriority:
{ "mode": "speaker", "speaker": { "mainPriority": ["screen_share", "active_speaker"], "mainRatio": 0.76 }}A screen share takes the main region, otherwise the loudest participant holds it. Listing active_speaker requires an audio_mixer in the job — loudness is measured there — which this pipeline already has.
Add a transcript. Wire an asr node into the sink and you get a WebVTT subtitle rendition beside the video, uploaded on finalize. segment is the only sink that can carry captions without a video track. See the meeting recording use case for a complete job that also turns the transcript into notes.
Keep a rolling window instead of the whole session. Set maxPlaylistEntries for a live sliding-window playlist. The finalized VOD playlist includes every segment regardless.
See Cost examples.