// starts recording
call.startRecording();
// stops the recording for the call
call.stopRecording();
Recording calls
Calls can be recorded for later use. Calls recording can be started/stopped via API calls or configured to start automatically when the first user joins the call. Call recording is done by Stream server-side and later stored on AWS S3. There is no charge for storage of recordings. You can also configure your Stream application to have files stored on your own S3 bucket.
By default, calls will be recorded as mp4 video files. You can configure recording to only capture the audio.
Note: by default, recordings contain all tracks mixed in a single file. You can follow the discussion here if you are interested in different ways to record calls.
Start and stop call recording
# starts recording
call.start_recording()
# stops the recording for the call
call.stop_recording()
// starts recording
call.StartRecording(ctx, &getstream.StartRecordingRequest{})
// stops the recording for the call
call.StopRecording(ctx, &getstream.StopRecordingRequest{})
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}/start_recording?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt"
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}/stop_recording?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt"
List call recording
This endpoint returns the list of recordings for a call. When using Stream S3 as storage (default) all links are signed and expire after 2-weeks.
call.listRecordings();
call.list_recordings()
call.ListRecordings(ctx, &getstream.ListRecordingsRequest{})
curl "https://video.stream-io-api.com/api/v2/video/call/${CALL_TYPE}/${CALL_ID}/recordings?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt"
Delete call recording
This endpoint allows to delete call recording. Please note that recordings will be deleted only if they are stored on Stream side (default).
An error will be returned if the recording doesn’t exist.
call.deleteRecording({ session: "<session id>", filename: "<filename>" });
call.delete_recording(sessionID, filename)
call.DeleteRecording(ctx, "session_id", "filename", &getstream.DeleteRecordingRequest{})
curl -X DELETE "https://video.stream-io-api.com/video/call/${CALL_TYPE}/${CALL_ID}/${SESSION_ID}/recordings/${FILENAME}?api_key=${API_KEY}" \
-H "Authorization: ${JWT_TOKEN}" \
-H "stream-auth-type: jwt"
Events
These events are sent to users connected to the call and your webhook/SQS:
call.recording_started
when the call recording has startedcall.recording_stopped
when the call recording has stoppedcall.recording_ready
when the recording is available for downloadcall.recording_failed
when recording fails for any reason
User Permissions
The following permissions are checked when users interact with the call recording API.
StartRecording
required to start the recordingStopRecording
required to stop the recordingListRecordings
required to retrieve the list of recordingsDeleteRecording
required to delete an existing recording (including its files if stored using Stream S3 storage)
Enabling / Disabling call recording
Recording can be configured from the Dashboard (see call type screen) or directly via the API. It is also possible to change the recording settings for a call and override the default settings coming from the its call type.
// Disable on call level
call.update({
settings_override: {
recording: {
mode: "disabled",
},
},
});
// Disable on call type level
client.video.updateCallType({
name: "<call type name>",
settings: {
recording: {
mode: "disabled",
},
},
});
// Enable
call.update({
settings_override: {
recording: {
mode: "available",
},
},
});
// Other settings
call.update({
settings_override: {
recording: {
mode: "available",
audio_only: false,
quality: "1080p",
},
},
});
from getstream.models import RecordSettingsRequest
# Disable on call level
call.update(
settings_override=CallSettingsRequest(
recording=RecordSettingsRequest(
mode='disabled',
),
),
)
# Disable on call type level
call_type_name = 'default'
client.video.update_call_type(call_type_name,
settings=CallSettingsRequest(
recording=RecordSettingsRequest(
mode='disabled',
),
),
)
# Automatically record calls
client.video.update_call_type(call_type_name,
settings=CallSettingsRequest(
recording=RecordSettingsRequest(
mode="auto-on",
quality="720p",
),
),
)
# Enable recording feature for a specific call
call.update(
settings_override=CallSettingsRequest(
recording=RecordSettingsRequest(
mode="available",
),
),
)
# Other settings
call.update(
settings_override=CallSettingsRequest(
recording=RecordSettingsRequest(
mode="available",
quality="1080p",
),
),
)
// Disable on call level
call.Update(ctx, &getstream.UpdateCallRequest{
SettingsOverride: &getstream.CallSettingsRequest{
Recording: &getstream.RecordSettingsRequest{
Mode: "disabled",
},
},
})
// Disable on call type level
call_type_name := "default"
client.Video().UpdateCallType(ctx, call_type_name, &getstream.UpdateCallTypeRequest{
Settings: &getstream.CallSettingsRequest{
Recording: &getstream.RecordSettingsRequest{
Mode: "disabled",
},
},
})
// Automatically record calls
client.Video().UpdateCallType(ctx, call_type_name, &getstream.UpdateCallTypeRequest{
Settings: &getstream.CallSettingsRequest{
Recording: &getstream.RecordSettingsRequest{
Mode: "auto-on",
Quality: getstream.PtrTo("720p"),
},
},
})
// Enable recording feature for a specific call
call.Update(ctx, &getstream.UpdateCallRequest{
SettingsOverride: &getstream.CallSettingsRequest{
Recording: &getstream.RecordSettingsRequest{
Mode: "available",
},
},
})
// Other settings
call.Update(ctx, &getstream.UpdateCallRequest{
SettingsOverride: &getstream.CallSettingsRequest{
Recording: &getstream.RecordSettingsRequest{
Mode: "available",
Quality: getstream.PtrTo("1080p"),
},
},
})
# Disable on call level
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/default/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings_override": {
"recording": {
"mode": "disabled"
}
}
}'
# Enable on call level
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/default/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings_override": {
"recording": {
"mode": "available"
}
}
}'
# Other settings
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/default/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings_override": {
"recording": {
"mode": "available",
"audio_only": false,
"quality": "1080p"
}
}
}'
# Enable/disable on call type level
curl -X PUT "https://video.stream-io-api.com/api/v2/video/calltypes/${CALL_TYPE_NAME}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"recording": {
"mode": "disabled"
}
}
}'
Audio only recording
You can configure your calls to only record the audio tracks and exclude the video. You can do this from the dashboard (Call Types sections) or set it for individual calls.
// Enable
call.update({
settings_override: {
recording: {
mode: "available",
audio_only: true,
},
},
});
# Set recording only for audio
call.update(
settings_override=CallSettingsRequest(
recording=RecordSettingsRequest(
mode='available',
audio_only=True
),
),
)
// Set recording only for audio
call.Update(ctx, &getstream.UpdateCallRequest{
SettingsOverride: &getstream.CallSettingsRequest{
Recording: &getstream.RecordSettingsRequest{
Mode: "available",
AudioOnly: getstream.PtrTo(true),
},
},
})
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/default/${CALL_ID}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings_override": {
"recording": {
"mode": "available",
"audio_only": true
}
}
}'
Recording layouts
Recording can be customized in several ways:
- You can pick one of the built-in layouts and pass some options to it
- You can further customize the style of the call by providing your own CSS file
- You can use your own recording application
There are three available layouts you can use for your calls: "single_participant"
, "grid"
and "spotlight"
Single Participant
This layout shows only one participant video at a time, other video tracks are hidden.
The visible video is selected based on this priority:
- Participant is pinned
- Participant is screen-sharing
- Participant is the dominant speaker
- Participant has a video track
Grid
This layout shows a configurable number of tracks in an equally sized grid.
Spotlight
This layout shows a video in a spotlight and the rest of the participants in a separate list or grid.
Layout options
Each layout has a number of options that you can configure. Here is an example:
const layoutOptions = {
"logo.image_url":
"https://theme.zdassets.com/theme_assets/9442057/efc3820e436f9150bc8cf34267fff4df052a1f9c.png",
"logo.horizontal_position": "center",
"title.text": "Building Stream Video Q&A",
"title.horizontal_position": "center",
"title.color": "black",
"participant_label.border_radius": "0px",
"participant.border_radius": "0px",
"layout.spotlight.participants_bar_position": "top",
"layout.background_color": "#f2f2f2",
"participant.placeholder_background_color": "#1f1f1f",
"layout.single-participant.padding_inline": "20%",
"participant_label.background_color": "transparent",
};
client.video.updateCallType({
name: callTypeName,
settings: {
recording: {
mode: "available",
audio_only: false,
quality: "1080p",
layout: {
name: "spotlight",
options: layoutOptions,
},
},
},
});
from getstream.models import CallSettingsRequest, LayoutSettingsRequest, RecordSettingsRequest
layout_options = {
"logo.image_url": "https://theme.zdassets.com/theme_assets/9442057/efc3820e436f9150bc8cf34267fff4df052a1f9c.png",
"logo.horizontal_position": "center",
"title.text": "Building Stream Video Q&A",
"title.horizontal_position": "center",
"title.color": "black",
"participant_label.border_radius": "0px",
"participant.border_radius": "0px",
"layout.spotlight.participants_bar_position": "top",
"layout.background_color": "#f2f2f2",
"participant.placeholder_background_color": "#1f1f1f",
"layout.single-participant.padding_inline": "20%",
"participant_label.background_color": "transparent",
}
client.video.update_call_type(
"default",
settings=CallSettingsRequest(
recording=RecordSettingsRequest(
mode="available",
audio_only=False,
quality="1080p",
layout=LayoutSettingsRequest(
name="spotlight",
options=layout_options,
),
),
),
)
layoutOptions := map[string]any{
"logo.image_url": "https://theme.zdassets.com/theme_assets/9442057/efc3820e436f9150bc8cf34267fff4df052a1f9c.png",
"logo.horizontal_position": "center",
"title.text": "Building Stream Video Q&A",
"title.horizontal_position": "center",
"title.color": "black",
"participant_label.border_radius": "0px",
"participant.border_radius": "0px",
"layout.spotlight.participants_bar_position": "top",
"layout.background_color": "#f2f2f2",
"participant.placeholder_background_color": "#1f1f1f",
"layout.single-participant.padding_inline": "20%",
"participant_label.background_color": "transparent",
}
client.Video().UpdateCallType(ctx, "callTypeName", &getstream.UpdateCallTypeRequest{
Settings: &getstream.CallSettingsRequest{
Recording: &getstream.RecordSettingsRequest{
Mode: "available",
AudioOnly: getstream.PtrTo(false),
Quality: getstream.PtrTo("1080p"),
Layout: &getstream.LayoutSettingsRequest{
Name: "spotlight",
Options: &layoutOptions,
},
},
},
})
curl -X PUT "https://video.stream-io-api.com/api/v2/video/calltypes/${CALL_TYPE_NAME}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"recording": {
"mode": "available",
"audio_only": false,
"quality": "1080p",
"layout": {
"name": "spotlight",
"options": {
"logo.image_url": "https://theme.zdassets.com/theme_assets/9442057/efc3820e436f9150bc8cf34267fff4df052a1f9c.png",
"logo.horizontal_position": "center",
"title.text": "Building Stream Video Q&A",
"title.horizontal_position": "center",
"title.color": "black",
"participant_label.border_radius": "0px",
"participant.border_radius": "0px",
"layout.spotlight.participants_bar_position": "top",
"layout.background_color": "#f2f2f2",
"participant.placeholder_background_color": "#1f1f1f",
"layout.single-participant.padding_inline": "20%",
"participant_label.background_color": "transparent"
}
}
}
}
}'
Here you can find the complete list of options available to each layout.
Single Participant
Option | Type | Default | Allowed Values | Description |
---|---|---|---|---|
video.background_color | color | #000000 | The background color | |
video.screenshare_scale_mode | string | fit | [fit fill] | How source video is displayed inside a box when aspect ratio does not match. ‘fill’ crops the video to fill the entire box, ‘fit’ ensures the video fits inside the box by padding necessary padding |
participant.label_horizontal_position | string | left | [center left right] | horizontal position for the participant label |
participant.video_border_radius | number | 1.2 | The corner radius used for the participant video border | |
logo.horizontal_position | string | center | [center left right] | horizontal position of the logo |
participant.label_display | boolean | true | Show the participant label | |
participant.label_text_color | color | #000000 | Text color of the participant label | |
participant.label_background_color | color | #00000000 | Background color of the participant label | |
participant.label_border_radius | number | 1.2 | The corner radius used for the label border | |
logo.vertical_position | string | top | [top bottom center] | vertical position of the logo |
participant.label_display_border | boolean | true | Render label border | |
participant.label_vertical_position | string | bottom | [top bottom center] | vertical position for the participant label |
participant.video_highlight_border_color | color | #7CFC00 | The color used for highlighted participants video border | |
participant.video_border_rounded | boolean | true | Render the participant video border rounded | |
participant.video_border_width | boolean | true | The stroke width used to render a participant border | |
participant.placeholder_background_color | color | #000000 | Sets the background color for video placeholder tile | |
video.scale_mode | string | fill | [fit fill] | How source video is displayed inside a box when aspect ratio does not match. ‘fill’ crops the video to fill the entire box, ‘fit’ ensures the video fits inside the box by padding necessary padding |
logo.image_url | string | add a logo image to the video layout | ||
participant.label_border_color | color | #CCCCCC | Label border color | |
participant.label_border_rounded | boolean | true | Render the label border rounded | |
participant.video_border_color | color | #CCCCCC | The color used for the participant video border | |
participant.aspect_ratio | string | "9/16", "4/3", "1/1", ... | The aspect ratio of the participant |
Spotlight
Option | Type | Default | Allowed Values | Description |
---|---|---|---|---|
participant.video_border_width | boolean | true | The stroke width used to render a participant border | |
grid.position | string | bottom | [top bottom left right] | position of the grid in relation to the spotlight |
participant.label_display_border | boolean | true | Render label border | |
participant.label_horizontal_position | string | left | [center left right] | horizontal position for the participant label |
participant.video_border_color | color | #CCCCCC | The color used for the participant video border | |
grid.columns | number | 5 | how many column to use in grid mode | |
video.background_color | color | #000000 | The background color | |
logo.horizontal_position | string | center | [center left right] | horizontal position of the logo |
participant.label_border_color | color | #CCCCCC | Label border color | |
participant.label_background_color | color | #00000000 | Background color of the participant label | |
grid.cell_padding | size | 10 | padding between cells | |
screenshare_layout | string | spotlight | [grid spotlight single-participant] | The layout to use when entering screenshare mode |
grid.size_percentage | number | 20 | The percentage of the screen the grid should take up | |
participant.label_border_radius | number | 1.2 | The corner radius used for the label border | |
participant.video_highlight_border_color | color | #7CFC00 | The color used for highlighted participants video border | |
participant.placeholder_background_color | color | #000000 | Sets the background color for video placeholder tile | |
participant.video_border_radius | number | 1.2 | The corner radius used for the participant video border | |
participant.label_display | boolean | true | Show the participant label | |
participant.label_border_rounded | boolean | true | Render the label border rounded | |
participant.video_border_rounded | boolean | true | Render the participant video border rounded | |
grid.rows | number | 1 | how many rows to use in grid mode | |
grid.margin | size | 10 | the margin between grid and spotlight | |
video.scale_mode | string | fill | [fit fill] | How source video is displayed inside a box when aspect ratio does not match. ‘fill’ crops the video to fill the entire box, ‘fit’ ensures the video fits inside the box by padding necessary padding |
logo.image_url | string | add a logo image to the video layout | ||
logo.vertical_position | string | top | [top bottom center] | vertical position of the logo |
video.screenshare_scale_mode | string | fit | [fit fill] | How source video is displayed inside a box when aspect ratio does not match. ‘fill’ crops the video to fill the entire box, ‘fit’ ensures the video fits inside the box by padding necessary padding |
participant.label_text_color | color | #000000 | Text color of the participant label | |
participant.label_vertical_position | string | bottom | [top bottom center] | vertical position for the participant label |
participant.aspect_ratio | string | "9/16", "4/3", "1/1", ... | The aspect ratio of the participant |
Grid
Option | Type | Default | Allowed Values | Description |
---|---|---|---|---|
logo.image_url | string | “ | add a logo image to the video layout | |
logo.vertical_position | string | top | [top bottom center] | vertical position of the logo |
participant.label_horizontal_position | string | left | [center left right] | horizontal position for the participant label |
participant.placeholder_background_color | color | #000000 | Sets the background color for video placeholder tile | |
video.scale_mode | string | fill | [fit fill] | How source video is displayed inside a box when the aspect ratio does not match. ‘fill’ crops the video to fill the entire box, ‘fit’ ensures the video fits inside the box by padding necessary padding |
logo.horizontal_position | string | center | [center left right] | horizontal position of the logo |
participant.video_border_rounded | boolean | true | Render the participant video border rounded | |
participant.label_display_border | boolean | true | Render label border | |
participant.label_border_color | color | #CCCCCC | Label border color | |
grid.cell_padding | size | 10 | padding between cells | |
video.screenshare_scale_mode | string | fit | [fit fill] | How source video is displayed inside a box when the aspect ratio does not match. ‘fill’ crops the video to fill the entire box, ‘fit’ ensures the video fits inside the box by padding necessary padding |
video.background_color | color | #000000 | The background color | |
participant.label_border_radius | number | 1.2 | The corner radius used for the label border | |
grid.size_percentage | number | 90 | The percentage of the screen the grid should take up | |
grid.margin | size | 10 | the margin between grid and spotlight | |
grid.columns | number | 5 | how many column to use in grid mode | |
participant.label_vertical_position | string | bottom | [top bottom center] | vertical position for the participant label |
participant.label_display | boolean | true | Show the participant label | |
participant.video_border_color | color | #CCCCCC | The color used for the participant video border | |
participant.video_border_width | boolean | true | The stroke width used to render a participant border | |
screenshare_layout | string | spotlight | [grid spotlight single-participant] | The layout to use when entering screen share mode |
participant.label_text_color | color | #000000 | Text color of the participant label | |
participant.label_background_color | color | #00000000 | Background color of the participant label | |
participant.label_border_rounded | boolean | true | Render the label border rounded | |
participant.video_border_radius | number | 1.2 | The corner radius used for the participant video border | |
participant.video_highlight_border_color | color | #7CFC00 | The color used for highlighted participants video border | |
grid.rows | number | 4 | how many rows to use in grid mode | |
participant.aspect_ratio | string | "9/16", "4/3", "1/1", ... | The aspect ratio of the participant |
Recording resolution and portrait mode
Calls can be recorded in different resolutions and modes (landscape and portrait). On the dashboard, you can configure the default settings for all calls of a specific call type.
While this can be configured from the dashboard, you can also set it for individual calls:
client.video.updateCallType({
name: callTypeName,
settings: {
recording: {
mode: "available",
quality: "portrait-1080x1920",
},
},
});
from getstream.models import CallSettingsRequest, RecordSettingsRequest
client.video.update_call_type(
"default",
settings=CallSettingsRequest(
recording=RecordSettingsRequest(
mode="available",
quality="portrait-1080x1920",
),
),
)
curl -X PUT "https://video.stream-io-api.com/api/v2/video/calltypes/${CALL_TYPE_NAME}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"recording": {
"mode": "available",
"quality": "portrait-1080x1920"
}
}
}'
Custom recording styling using external CSS
You can customize how recorded calls look by providing an external CSS file. The CSS file needs to be publicly available and ideally hosted on a CDN to ensure the best performance. The best way to find the right CSS setup is by running the layout app directly. The application is publicly available on Github here and contains instructions on how to be used.
client.video.updateCallType({
name: callTypeName,
settings: {
recording: {
mode: "available",
audio_only: false,
quality: "1080p",
layout: {
name: "spotlight",
external_css_url: "https://path/to/custom.css",
},
},
},
});
from getstream.models import CallSettingsRequest, LayoutSettingsRequest, RecordSettingsRequest
client.video.update_call_type(
"default",
settings=CallSettingsRequest(
recording=RecordSettingsRequest(
mode="available",
audio_only=False,
quality="1080p",
layout=LayoutSettingsRequest(
name="spotlight",
external_css_url="https://path/to/custom.css",
),
),
),
)
client.Video().UpdateCallType(ctx, "callTypeName", &getstream.UpdateCallTypeRequest{
Settings: &getstream.CallSettingsRequest{
Recording: &getstream.RecordSettingsRequest{
Mode: "available",
AudioOnly: getstream.PtrTo(false),
Quality: getstream.PtrTo("1080p"),
Layout: &getstream.LayoutSettingsRequest{
Name: "spotlight",
ExternalCssUrl: getstream.PtrTo("https://path/to/custom.css"),
},
},
},
})
curl -X PUT "https://video.stream-io-api.com/api/v2/video/calltypes/${CALL_TYPE_NAME}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"recording": {
"mode": "available",
"audio_only": false,
"quality": "1080p",
"layout": {
"name": "spotlight",
"external_css_url": "https://path/to/custom.css"
}
}
}
}'
Advanced - record calls using a custom web application
If needed, you can use your own custom application to record a call. This is the most flexible and complex approach to record calls, make sure to reach out to our customer support before going with this approach.
The layout app used to record calls is available on GitHub and is a good starting point. The repository also includes information on how to build your own.
client.video.updateCallType({
name: callTypeName,
settings: {
recording: {
mode: "available",
audio_only: false,
quality: "1080p",
layout: {
name: "custom",
external_app_url: "https://path/to/layout/app",
},
},
},
});
from getstream.models import CallSettingsRequest, LayoutSettingsRequest, RecordSettingsRequest
client.video.update_call_type(
"default",
settings=CallSettingsRequest(
recording=RecordSettingsRequest(
mode="available",
audio_only=False,
quality="1080p",
layout=LayoutSettingsRequest(
name="custom",
external_app_url="https://path/to/layout/app",
),
),
),
)
client.Video().UpdateCallType(ctx, "callTypeName", &getstream.UpdateCallTypeRequest{
Settings: &getstream.CallSettingsRequest{
Recording: &getstream.RecordSettingsRequest{
Mode: "available",
AudioOnly: getstream.PtrTo(false),
Quality: getstream.PtrTo("1080p"),
Layout: &getstream.LayoutSettingsRequest{
Name: "custom",
ExternalAppUrl: getstream.PtrTo("https://path/to/layout/app"),
},
},
},
})
curl -X PUT "https://video.stream-io-api.com/api/v2/video/calltypes/${CALL_TYPE_NAME}?api_key=${API_KEY}" \
-H "Authorization: ${TOKEN}" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"recording": {
"mode": "available",
"audio_only": false,
"quality": "1080p",
"layout": {
"name": "custom",
"external_app_url": "https://path/to/layout/app"
}
}
}
}'
Client-side recording
Unfortunately, there is no direct support for client-side recording at the moment. Call recording at the moment is done by Stream server-side. If client-side recording is important for you please make sure to follow the conversation here.
- Start and stop call recording
- List call recording
- Delete call recording
- Events
- User Permissions
- Enabling / Disabling call recording
- Audio only recording
- Recording layouts
- Layout options
- Recording resolution and portrait mode
- Custom recording styling using external CSS
- Advanced - record calls using a custom web application
- Client-side recording