# Audio-Only

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

## Quickstart

<tabs groupId="examples">

<tabs-item value="js" label="JavaScript">

```js
// 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
```

</tabs-item>

<tabs-item value="py" label="Python">

```py
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
```

</tabs-item>

<tabs-item value="go" label="Golang">

```go
// 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
```

</tabs-item>

<tabs-item value="curl" label="cURL">

```bash
# 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"
```

</tabs-item>

</tabs>

Each type of recording can be used to do audio-only, here's an overview of the pros/cons:

| Method                                 | Output                                              | Best for                                          |
| -------------------------------------- | --------------------------------------------------- | ------------------------------------------------- |
| [Composite](#composite-audio)          | Single mixed audio file (all participants combined) | Ready-to-share podcasts, meeting recordings       |
| [Individual](#individual-audio-tracks) | Separate audio file per participant                 | Post-production editing, speaker isolation        |
| [Raw](#raw-audio)                      | Unprocessed RTP packets                             | Maximum flexibility, lowest cost, custom encoding |

<admonition type="info">
Each recording type requires specific settings to enable audio-only mode. See the sections below for configuration details.
</admonition>

## Composite audio

_This section covers audio-only configuration. For complete documentation, see the [Composite recording guide](/video/docs/api/recording/composite/)._

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.

<tabs groupId="examples">

<tabs-item value="js" label="JavaScript">

```js
// 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)
```

</tabs-item>

<tabs-item value="py" label="Python">

```py
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)
```

</tabs-item>

<tabs-item value="go" label="Golang">

```go
// 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)
```

</tabs-item>

</tabs>

**Output:** Single MP3 file

## Individual audio tracks

_This section covers audio-only configuration. For complete documentation, see the [Individual recording guide](/video/docs/api/recording/individual-track/)._

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.

<tabs groupId="examples">

<tabs-item value="js" label="JavaScript">

```js
// 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)
```

</tabs-item>

<tabs-item value="py" label="Python">

```py
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)
```

</tabs-item>

<tabs-item value="go" label="Golang">

```go
// 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)
```

</tabs-item>

</tabs>

**Output:** One MKV audio file per participant

## Raw audio

_This section covers audio extraction from raw recordings. For complete documentation, see the [Raw recording guide](/video/docs/api/recording/raw/)._

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.

<tabs groupId="examples">

<tabs-item value="js" label="JavaScript">

```js
// 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)
```

</tabs-item>

<tabs-item value="py" label="Python">

```py
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)
```

</tabs-item>

<tabs-item value="go" label="Golang">

```go
// 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)
```

</tabs-item>

<tabs-item value="curl" label="cURL">

```bash
# 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)
```

</tabs-item>

</tabs>

After the call, use the Stream CLI to extract audio:

```bash
# 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:

```bash
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

## Choosing the right option

| 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                          |


---

This page was last updated at 2026-06-23T15:36:57.748Z.

For the most recent version of this documentation, visit [https://getstream.io/video/docs/flutter/recording/audio-only/](https://getstream.io/video/docs/flutter/recording/audio-only/).