This documentation is for reference only. We are no longer onboarding new customers to Programmable Video. Existing customers can continue to use the product until December 5, 2026.
We recommend migrating your application to the API provided by our preferred video partner, Zoom. We've prepared this migration guide to assist you in minimizing any service disruption.
There are two ways a Participant's video and audio tracks can be recorded in the cloud:
The Recording Rules can be used to specify which participants and tracks should be recorded or not and they provide a fine grained approach for creating Recordings. For example, rules can be defined to simply start or stop recording or they can be defined so that only one participant in a Group Room is recorded. In addition, rules can specify if just the audio tracks should be recorded or both audio and video ones.
The Recording Rules API is only available in Group Rooms.
The RecordingRules resource is a subresource of a Room instance resource. It represents the state of the recording rules for the specified Room.
For the sake of simplicity, we define the RecordingRules Resource URI as:
RECORDING_RULES_URI = https://video.twilio.com/v1/Rooms/{RoomNameOrSid}/RecordingRules
One list of rules can be specified using the Recording Rules URI per Room. It can be updated anytime during the life of the Room to include/exclude video/audio Tracks.
The SID of the Room resource for the Recording Rules
^RM[0-9a-fA-F]{32}$
Min length: 34
Max length: 34
A collection of Recording Rules that describe how to include or exclude matching tracks for recording
The date and time in GMT when the resource was created specified in ISO 8601 format.
Returns the current state of the recording rules of the specified Room.
Updates the recording rules of the specified Room. The following parameters are supported:
The SID of the Room resource where the recording rules to update apply.
application/x-www-form-urlencoded
A JSON-encoded array of recording rules.
For a deeper understanding on how recording rules work, see the Understanding Recording Rules section below.
This resource does not support PUT
or DELETE
.
Recording rules can be set at any time during the life of the Room. If the record_participants_on_connect flag is set to true during the Room creation then a default rule to record all video and audio tracks will be automatically set.
A recording rule instance has the following JSON structure:
{"type": rule_type, filter_name: filter_value, filter_name: filter_value, ...}
Where:
Field | Description |
---|---|
rule_type | An identifier specifying the type of rule. It must be one of the following:-include : includes the tracks that match the filters into the Recordings.-exclude : excludes the tracks that match the filters from the Recordings. |
filter_name and filter_value | The filter_name must be one of the following:-all : the filter affects all tracks. Accepts only one value: true (matches all tracks)-kind : matches tracks of a given type. Accepts video and audio as values.-publisher : matches all tracks published by the Participant with the identity (case sensitive) or SID specified as value-track : matches tracks with the name (case sensitive) or SID specified as value. A rule containing multiple filters matches the set of tracks that comply with all of them. In other words, filters combine in a rule through a logical AND. |
Based on this, recording rules are specified as a JSON array containing up to 20 rules. For example:
1Rules = [2{"type": "include", "all": true}, //rule_13{"type": "exclude", "kind": "video"}, //rule_24{"type": "include", "publisher": "Bob", "track": "screen"}, //rule_35{"type": "include", "track": "MTXXXXXXXXXXXXXXXXXXXXXXXXXXX"}, //rule_46...7rule_208]
Remember that valid recording rules comply with the following:
[]
) is not allowed.
"all"
filter must have a value of
true
. Notice that
this means
false
is not allowed.
“all”
filter cannot have any other filters.
"type"
field.
"kind"
filter is used, its value must be either
audio
or
video
.
kind
s or
publisher
s)
When invalid rules are specified, the current active rules will not be updated
and the POST
will be answered with an HTTP 400
error response like the following:
1{2"code": 53120,3"message": "Invalid Recording Rule(s)",4"more_info": "https://www.twilio.com/docs/errors/53120",5"status": 4006}
For example, the following requests are invalid:
1//Invalid because it's using an empty set2Rules = []
1//Invalid because it uses false as value of "all"2Rules = [3{"type":"include", "all": false}4]
1//Invalid because it specifies a non supported kind2Rules = [3{"type": "include", "all": true},4{"type": "exclude", "kind": "video"}5]
1//Invalid because it repeats the "kind" filter twice2Rules = [3{"type": "include", "kind": "audio", "kind": "video"},4]
1//Invalid because an "all" filter is not compatible with any other filter2Rules = [3{"type": "include", "all": "true", "kind": "audio"},4]
RecordingRules
are enforced by Twilio using three main principles:
We define the Set of Recording Tracks (SetRT) as the set of tracks a given Room should be recording at any time. The SetRT is computed by Twilio using Algebra of Sets based on the following algorithm:
include
rule we perform the union of the SetRT with the set of
tracks matching the rule filters.
exclude
rule we perform the set difference of the SetRT with
the set of tracks matching by the rule filters.
If the record_participants_on_connect is set on Room creation then the SetRT is initialized to:
{"type": "include", "all": true}
Let's illustrate this using an example. Imagine a Group Room with three participants named: Alice, Bob and Carl, who publish the tracks specified in the following table:
Alice (PTA) | Bob (PTB) | Carl (PTC) | |
---|---|---|---|
Audio Track | MTA_A alice-audio | MTB_A bob-audio | MTC_A carl-audio |
Video Track (cam) | MTA_C alice-cam | MTB_C bob-cam | MTC_C carl-cam |
Video Track (screen) | MTA_S screen | MTB_S screen |
Notice that, for the sake of simplicity, we have assumed the following conventions:
MT
followed by the participant initial and by a
letter identifying the track nature (
_A
for audio,
_C
for webcam, and
_S
for screenshare).
To record the audio and video tracks of all participants in a Room, POST
the following to the Room's RecordingRules resource:
1Rules = [2{"type": "include", "all": true}3]
Recording will start for all Participants connected to the Room. Any new Participants who join will also be recorded.
To stop the recording of all video and audio tracks of all participants in a Room, POST
the following to the Room's RecordingRules resource:
1Rules = [2{"type": "exclude", "all": true}3]
This will stop the Recordings for all tracks. Note that Recordings can be started again some time later by reposting with the "include", "all" rule. New Recording SIDs will be created each time a track Recording is started.
To restrict the recording to just the audio tracks of all participants in a Room, POST
the following to the Room's RecordingRules resource:
1Rules = [2{"type": "include", "kind": "audio"}3]
Video tracks of participants will not be recorded.
In this scenario we want to record the video and audio of Alice while also recording the audio tracks of the other participants.
To achieve this, POST
the following to the Room's RecordingRules resource:
1Rules = [2{"type": "include", "publisher": "Alice"},3{"type": "include", "kind": "audio"}4]
The video and audio tracks of Alice will be recorded and there will be an audio track Recording for any other Participant who joins the Room.
The Recording Rules API is stateless. This means that it has no memory of
rules. Every time a developer POST
s a set of new recording
rules, the previous rules are fully erased and replaced with new rules, which
are then enforced using the algorithm described in the section above.
When developers POST
recording rules to Twilio, those rules are enforced in
a dynamic way. That means that the algorithm does not only execute at POST
time,
but it is executed every time there is change in the Room's available tracks.
Hence, once the rules have been POST
ed, Twilio guarantees that they are enforced
at any time without requiring further developer intervention.
1// Download the helper library from https://www.twilio.com/docs/node/install2// Your Account Sid and Auth Token from twilio.com/console3// and set the environment variables. See http://twil.io/secure4const accountSid = process.env.TWILIO_ACCOUNT_SID;5const authToken = process.env.TWILIO_AUTH_TOKEN;6const client = require('twilio')(accountSid, authToken);78client.video.rooms('RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')9.recordingRules10.update({rules: [{"type": "include", "all": true}]})11.then(recording_rules => console.log(recording_rules.roomSid));
1{2"room_sid": "RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",3"date_created": "2015-07-30T20:00:00Z",4"date_updated": "2015-07-30T20:00:00Z",5"rules": [6{7"type": "include",8"all": true9}10]11}
1// Download the helper library from https://www.twilio.com/docs/node/install2// Your Account Sid and Auth Token from twilio.com/console3// and set the environment variables. See http://twil.io/secure4const accountSid = process.env.TWILIO_ACCOUNT_SID;5const authToken = process.env.TWILIO_AUTH_TOKEN;6const client = require('twilio')(accountSid, authToken);78client.video.rooms('RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')9.recordingRules10.update({rules: [{"type": "include", "kind": "audio"}]})11.then(recording_rules => console.log(recording_rules.roomSid));
1{2"room_sid": "RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",3"date_created": "2015-07-30T20:00:00Z",4"date_updated": "2015-07-30T20:00:00Z",5"rules": [6{7"type": "include",8"kind": "audio"9}10]11}
1// Download the helper library from https://www.twilio.com/docs/node/install2// Your Account Sid and Auth Token from twilio.com/console3// and set the environment variables. See http://twil.io/secure4const accountSid = process.env.TWILIO_ACCOUNT_SID;5const authToken = process.env.TWILIO_AUTH_TOKEN;6const client = require('twilio')(accountSid, authToken);78client.video.rooms('RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')9.recordingRules10.update({rules: [{"type": "exclude", "all": true}]})11.then(recording_rules => console.log(recording_rules.roomSid));
1{2"room_sid": "RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",3"date_created": "2015-07-30T20:00:00Z",4"date_updated": "2015-07-30T20:00:00Z",5"rules": [6{7"type": "exclude",8"all": true9}10]11}