Track recording
Track recording lets you record participant audio as separate WebM files instead of one composite meeting recording. Use it when you need speaker-level control over what you store, process, or review.
With track recording, you can record specific participant tracks by passing user_ids, which is useful for content-sensitive or regulated workflows where recording every participant is unnecessary. If you do not provide user_ids, RealtimeKit will record all participant audio tracks as separate WebM files by default.
To pass user_ids for specific participant track recording, use the following minimum SDK versions:
- Web Core:
@cloudflare/realtimekitversion1.4.0or later - Web UI Kit:
@cloudflare/realtimekit-ui,@cloudflare/realtimekit-react-ui, or@cloudflare/realtimekit-angular-uiversion1.1.2or later - Android Core or iOS Core: version
2.0.0or later - Android UI Kit or iOS UI Kit: version
1.1.0or later
Track recording creates one file per recorded participant.
Track recording has the following requirements and limits:
| Limit | Description |
|---|---|
| Active meeting | The meeting must have an active live session. |
| Media kind | Only audio layers are recorded. |
| Participant selection | Pass up to 100 values in user_ids. |
| Storage | Files are uploaded to RealtimeKit's managed R2 bucket with zero-egress fees. |
| File retention | RealtimeKit bucket download URLs expire after seven days. |
To record separate audio tracks for specific participants, call POST /recordings/track with the meeting ID and the participant user_ids.
curl --request POST \ --url https://api.cloudflare.com/client/v4/accounts/<account_id>/realtime/kit/<app_id>/recordings/track \ --header 'Authorization: Bearer <api_token>' \ --header 'Content-Type: application/json' \ --data '{ "meeting_id": "97440c6a-140b-40a9-9499-b23fd7a3868a", "user_ids": ["user-123", "user-456"]}'RealtimeKit records current and future participants whose user_id matches the allowlist. Participants whose user_id is not listed are not recorded.
Omit user_ids to record separate audio tracks for all participants in the live meeting. RealtimeKit creates one WebM file for each recorded participant.
curl --request POST \ --url https://api.cloudflare.com/client/v4/accounts/<account_id>/realtime/kit/<app_id>/recordings/track \ --header 'Authorization: Bearer <api_token>' \ --header 'Content-Type: application/json' \ --data '{ "meeting_id": "97440c6a-140b-40a9-9499-b23fd7a3868a"}'The response includes a recording ID. Use this ID to stop or fetch the recording.
{ "success": true, "data": { "recording": { "id": "fff40c6a-140b-40a9-9499-b23fd7a3868a", "meeting_id": "97440c6a-140b-40a9-9499-b23fd7a3868a", "status": "INVOKED", "type": "TRACK", "output_file_name": "{{file_name_prefix}}_{{user_id}}_{{peer_id}}_{{stream_kind}}_{{media_kind}}_{{date_time}}.webm" } }}Use layers.default.file_name_prefix to prefix every generated track recording file.
{ "meeting_id": "97440c6a-140b-40a9-9499-b23fd7a3868a", "layers": { "default": { "media_kind": "audio", "file_name_prefix": "speaker" } }}If you omit layers, RealtimeKit uses default as the file name prefix.
Use the recording update endpoint to stop a track recording.
curl --request PUT \ --url https://api.cloudflare.com/client/v4/accounts/<account_id>/realtime/kit/<app_id>/recordings/<recording_id> \ --header 'Authorization: Bearer <api_token>' \ --header 'Content-Type: application/json' \ --data '{ "action": "stop"}'Track recording also stops when the meeting session ends.
After track recording stops, RealtimeKit uploads the per-participant WebM files and moves the recording to UPLOADED.
Track recording uses the same recording status lifecycle as composite recording. To monitor status, refer to Monitor Recording Status.
When the recording reaches UPLOADED, fetch the recording details or listen for the recording.statusUpdate webhook. For track recordings, download_url contains per-participant WebM file URLs grouped by layer.
{ "download_url": [ { "layer_name": "default", "download_urls": { "speaker_user-123_peer-456_peer_audio_1760000000000.webm": { "download_url": "https://example.com/presigned-url" } } } ]}File names use this format:
{{file_name_prefix}}_{{user_id}}_{{peer_id}}_{{stream_kind}}_{{media_kind}}_{{date_time}}.webmThe date_time value is the Unix timestamp in milliseconds when the file was generated.