Audio-only recordings capture just the audio from your calls—no video. This is ideal for podcasts, voice calls, transcription, meeting minutes, and scenarios where video isn't needed or you want to reduce storage costs.
You can request audio-only recordings in three different formats:
Composite: Delivers one file with all audio from all participants mixed in
Individual: Delivers one audio file for each participant in the call
Raw: Delivers one zip containing audio-only packets and metadata that you use to process
JavaScript Python Golang cURL
// Option 1: Composite audio (single mixed MP3)
await call. update ({
settings_override: {
recording: { mode: "available" , audio_only: true },
},
});
// Triggers: call.recording_started → call.recording_stopped → call.recording_ready
await call. startRecording ( "composite" );
await call. stopRecording ( "composite" );
// Option 2: Individual audio (separate file per participant)
await call. update ({
settings_override: {
individual_recording: {
mode: "available" ,
output_types: [ "audio_only" , "screenshare_audio_only" ],
},
},
});
// Triggers: call.recording_started → call.recording_stopped → call.recording_ready (one per file)
await call. startRecording ( "individual" );
await call. stopRecording ( "individual" );
// Option 3: Raw audio (unprocessed, requires CLI post-processing)
await call. update ({
settings_override: {
raw_recording: { mode: "available" , audio_only: true },
},
});
// Triggers: call.recording_started → call.recording_stopped → call.recording_ready
await call. startRecording ( "raw" );
await call. stopRecording ( "raw" );
// List all recordings for this call
const response = await call. listRecordings ();
// Download using the URL from response.recordings or the call.recording_ready webhook payload
// response.recordings[0].url from getstream.models import CallSettingsRequest, RecordSettingsRequest, IndividualRecordingSettingsRequest, RawRecordingSettingsRequest
# Option 1: Composite audio (single mixed MP3)
call.update( settings_override = CallSettingsRequest(
recording = RecordSettingsRequest( mode = "available" , audio_only = True ),
))
# Triggers: call.recording_started → call.recording_stopped → call.recording_ready
call.start_recording( "composite" )
call.stop_recording( "composite" )
# Option 2: Individual audio (separate file per participant)
call.update( settings_override = CallSettingsRequest(
individual_recording = IndividualRecordingSettingsRequest(
mode = "available" ,
output_types = [ "audio_only" , "screenshare_audio_only" ],
),
))
# Triggers: call.recording_started → call.recording_stopped → call.recording_ready (one per file)
call.start_recording( "individual" )
call.stop_recording( "individual" )
# Option 3: Raw audio (unprocessed, requires CLI post-processing)
call.update( settings_override = CallSettingsRequest(
raw_recording = RawRecordingSettingsRequest( mode = "available" , audio_only = True ),
))
# Triggers: call.recording_started → call.recording_stopped → call.recording_ready
call.start_recording( "raw" )
call.stop_recording( "raw" )
# List all recordings for this call
response = call.list_recordings()
# Download using the URL from response.data.recordings or the call.recording_ready webhook payload
# response.data.recordings[0].url // Option 1: Composite audio (single mixed MP3)
call. Update (ctx, & getstream . UpdateCallRequest {
SettingsOverride: & getstream . CallSettingsRequest {
Recording: & getstream . RecordSettingsRequest {Mode: "available" , AudioOnly: getstream. PtrTo ( true )},
},
})
// Triggers: call.recording_started → call.recording_stopped → call.recording_ready
call. StartRecording (ctx, "composite" , & getstream . StartRecordingRequest {})
call. StopRecording (ctx, "composite" , & getstream . StopRecordingRequest {})
// Option 2: Individual audio (separate file per participant)
call. Update (ctx, & getstream . UpdateCallRequest {
SettingsOverride: & getstream . CallSettingsRequest {
IndividualRecording: & getstream . IndividualRecordingSettingsRequest {
Mode: "available" ,
OutputTypes: [] string { "audio_only" , "screenshare_audio_only" },
},
},
})
// Triggers: call.recording_started → call.recording_stopped → call.recording_ready (one per file)
call. StartRecording (ctx, "individual" , & getstream . StartRecordingRequest {})
call. StopRecording (ctx, "individual" , & getstream . StopRecordingRequest {})
// Option 3: Raw audio (unprocessed, requires CLI post-processing)
call. Update (ctx, & getstream . UpdateCallRequest {
SettingsOverride: & getstream . CallSettingsRequest {
RawRecording: & getstream . RawRecordingSettingsRequest {Mode: "available" , AudioOnly: getstream. PtrTo ( true )},
},
})
// Triggers: call.recording_started → call.recording_stopped → call.recording_ready
call. StartRecording (ctx, "raw" , & getstream . StartRecordingRequest {})
call. StopRecording (ctx, "raw" , & getstream . StopRecordingRequest {})
// List all recordings for this call
response, err := call. ListRecordings (ctx, & getstream . ListRecordingsRequest {})
// Download using the URL from response.Data.Recordings or the call.recording_ready webhook payload
// response.Data.Recordings[0].Url # Option 1: Composite audio (single mixed MP3)
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/${ CALL_TYPE }/${ 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}}}'
# Triggers: call.recording_started → call.recording_stopped → call.recording_ready
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${ CALL_TYPE }/${ CALL_ID }/recordings/composite/start?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 }/recordings/composite/stop?api_key=${ API_KEY }" \
-H "Authorization: ${ TOKEN }" -H "stream-auth-type: jwt"
# Option 2: Individual audio (separate file per participant)
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/${ CALL_TYPE }/${ CALL_ID }?api_key=${ API_KEY }" \
-H "Authorization: ${ TOKEN }" -H "stream-auth-type: jwt" -H "Content-Type: application/json" \
-d '{"settings_override": {"individual_recording": {"mode": "available", "output_types": ["audio_only", "screenshare_audio_only"]}}}'
# Triggers: call.recording_started → call.recording_stopped → call.recording_ready (one per file)
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${ CALL_TYPE }/${ CALL_ID }/recordings/individual/start?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 }/recordings/individual/stop?api_key=${ API_KEY }" \
-H "Authorization: ${ TOKEN }" -H "stream-auth-type: jwt"
# Option 3: Raw audio (unprocessed, requires CLI post-processing)
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/${ CALL_TYPE }/${ CALL_ID }?api_key=${ API_KEY }" \
-H "Authorization: ${ TOKEN }" -H "stream-auth-type: jwt" -H "Content-Type: application/json" \
-d '{"settings_override": {"raw_recording": {"mode": "available", "audio_only": true}}}'
# Triggers: call.recording_started → call.recording_stopped → call.recording_ready
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${ CALL_TYPE }/${ CALL_ID }/recordings/raw/start?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 }/recordings/raw/stop?api_key=${ API_KEY }" \
-H "Authorization: ${ TOKEN }" -H "stream-auth-type: jwt"
# List all recordings for this call
# Download using the URL from response.recordings or the call.recording_ready webhook payload
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"
Each type of recording can be used to do audio-only, here's an overview of the pros/cons:
Method Output Best for Composite Single mixed audio file (all participants combined) Ready-to-share podcasts, meeting recordings Individual Separate audio file per participant Post-production editing, speaker isolation Raw Unprocessed RTP packets Maximum flexibility, lowest cost, custom encoding
Each recording type requires specific settings to enable audio-only mode. See the sections below for configuration details.
This section covers audio-only configuration. For complete documentation, see the Composite recording guide .
Composite audio (also known as mixed audio) produces a single MP3 file with all participants mixed together. This is the simplest option—you get one ready-to-use file with no post-processing required.
Use cases: Meeting recordings, webinar audio, podcast distribution, simple transcription
How to enable: Set audio_only: true in your composite recording settings.
JavaScript Python Golang
// Enable audio-only composite recording
call. update ({
settings_override: {
recording: {
mode: "available" ,
audio_only: true ,
},
},
});
// Start recording
// Triggers webhook event: call.recording_started
call. startRecording ( "composite" );
// When stopped: call.recording_stopped
// When ready: call.recording_ready (contains recording URL) from getstream.models import CallSettingsRequest, RecordSettingsRequest
# Enable audio-only composite recording
call.update(
settings_override = CallSettingsRequest(
recording = RecordSettingsRequest(
mode = "available" ,
audio_only = True ,
),
),
)
# Start recording
# Triggers webhook event: call.recording_started
call.start_recording( "composite" )
# When stopped: call.recording_stopped
# When ready: call.recording_ready (contains recording URL) // Enable audio-only composite recording
call. Update (ctx, & getstream . UpdateCallRequest {
SettingsOverride: & getstream . CallSettingsRequest {
Recording: & getstream . RecordSettingsRequest {
Mode: "available" ,
AudioOnly: getstream. PtrTo ( true ),
},
},
})
// Start recording
// Triggers webhook event: call.recording_started
call. StartRecording (ctx, "composite" , & getstream . StartRecordingRequest {})
// When stopped: call.recording_stopped
// When ready: call.recording_ready (contains recording URL)
Output: Single MP3 file
This section covers audio-only configuration. For complete documentation, see the Individual recording guide .
Individual audio recording captures each participant's audio separately. This gives you isolated tracks per speaker, which is essential for professional post-production where you need to edit, mix, or process each participant independently.
Use cases: Podcast editing with per-speaker control, speaker diarization, noise reduction per participant, creating highlight clips
How to enable: Set output_types to include audio_only (and optionally screenshare_audio_only) in your individual recording settings.
JavaScript Python Golang
// Enable individual audio-only recording
call. update ({
settings_override: {
individual_recording: {
mode: "available" ,
output_types: [ "audio_only" , "screenshare_audio_only" ],
},
},
});
// Start recording
// Triggers webhook event: call.recording_started
call. startRecording ( "individual" );
// When stopped: call.recording_stopped
// When ready: call.recording_ready (one event per file, contains recording URL) from getstream.models import CallSettingsRequest, IndividualRecordingSettingsRequest
# Enable individual audio-only recording
call.update(
settings_override = CallSettingsRequest(
individual_recording = IndividualRecordingSettingsRequest(
mode = "available" ,
output_types = [ "audio_only" , "screenshare_audio_only" ],
),
),
)
# Start recording
# Triggers webhook event: call.recording_started
call.start_recording( "individual" )
# When stopped: call.recording_stopped
# When ready: call.recording_ready (one event per file, contains recording URL) // Enable individual audio-only recording
call. Update (ctx, & getstream . UpdateCallRequest {
SettingsOverride: & getstream . CallSettingsRequest {
IndividualRecording: & getstream . IndividualRecordingSettingsRequest {
Mode: "available" ,
OutputTypes: [] string { "audio_only" , "screenshare_audio_only" },
},
},
})
// Start recording
// Triggers webhook event: call.recording_started
call. StartRecording (ctx, "individual" , & getstream . StartRecordingRequest {})
// When stopped: call.recording_stopped
// When ready: call.recording_ready (one event per file, contains recording URL)
Output: One MKV audio file per participant
This section covers audio extraction from raw recordings. For complete documentation, see the Raw recording guide .
Raw recording captures unprocessed RTP audio packets, giving you maximum flexibility for custom post-processing. This is the most cost-effective option but requires using the Stream CLI to extract playable audio files.
Use cases: Cost-effective archival, custom encoding pipelines, compliance requirements, generating MP3 or other formats
How to enable: Enable raw recording with audio_only: true, then use the Stream CLI to extract and mix audio tracks.
JavaScript Python Golang cURL
// Enable raw recording with audio only
call. update ({
settings_override: {
raw_recording: {
mode: "available" ,
audio_only: true ,
},
},
});
// Start recording
// Triggers webhook event: call.recording_started
call. startRecording ( "raw" );
// When stopped: call.recording_stopped
// When ready: call.recording_ready (contains archive URL) from getstream.models import CallSettingsRequest, RawRecordingSettingsRequest
# Enable raw recording with audio only
call.update(
settings_override = CallSettingsRequest(
raw_recording = RawRecordingSettingsRequest(
mode = "available" ,
audio_only = True ,
),
),
)
# Start recording
# Triggers webhook event: call.recording_started
call.start_recording( "raw" )
# When stopped: call.recording_stopped
# When ready: call.recording_ready (contains archive URL) // Enable raw recording with audio only
call. Update (ctx, & getstream . UpdateCallRequest {
SettingsOverride: & getstream . CallSettingsRequest {
RawRecording: & getstream . RawRecordingSettingsRequest {
Mode: "available" ,
AudioOnly: getstream. PtrTo ( true ),
},
},
})
// Start recording
// Triggers webhook event: call.recording_started
call. StartRecording (ctx, "raw" , & getstream . StartRecordingRequest {})
// When stopped: call.recording_stopped
// When ready: call.recording_ready (contains archive URL) # Enable raw recording with audio only
curl -X PATCH "https://video.stream-io-api.com/api/v2/video/call/${ CALL_TYPE }/${ CALL_ID }?api_key=${ API_KEY }" \
-H "Authorization: ${ TOKEN }" \
-H "stream-auth-type: jwt" \
-H "Content-Type: application/json" \
-d '{
"settings_override": {
"raw_recording": {
"mode": "available",
"audio_only": true
}
}
}'
# Start recording
# Triggers webhook event: call.recording_started
curl -X POST "https://video.stream-io-api.com/api/v2/video/call/${ CALL_TYPE }/${ CALL_ID }/recordings/raw/start?api_key=${ API_KEY }" \
-H "Authorization: ${ TOKEN }" \
-H "stream-auth-type: jwt"
# When stopped: call.recording_stopped
# When ready: call.recording_ready (contains archive URL)
After the call, use the Stream CLI to extract audio:
# Extract individual audio tracks per participant (outputs MKV files)
stream-cli video raw-recording extract-audio --input-file recording.tar.gz --output ./audio
# Mix all participants into a single MP3 file
stream-cli video raw-recording mix-audio --input-file recording.tar.gz --output ./mixed
You can convert extracted MKV files to other formats using FFmpeg:
ffmpeg -i individual_audio.mkv -codec:a libmp3lame -qscale:a 2 output.mp3
Output:
extract-audio → MKV audio files per participant
mix-audio → Single MP3 file with all participants mixed
Use case Recommended Why Meeting recording for playback Composite audio Single file, ready to share Podcast with multiple hosts Individual audio Edit each speaker separately Transcription service Composite or Individual Composite for simplicity, Individual for speaker attribution Archival with future flexibility Raw audio Lowest cost, can generate any format later Custom MP3 encoding Raw audio Full control over encoding settings