Skip to main content
The AudioSessionIos API is deprecated. For realtime transcription, use the new RealtimeTranscriber instead, which handles audio session management internally.This documentation is maintained for legacy code and understanding iOS audio session concepts.

Overview

The AudioSessionIos utility provides direct access to iOS AVAudioSession configuration. It allows you to control audio routing, mixing behavior, and recording permissions. Platform: iOS only (throws error on Android)

API Reference

Categories

Audio session categories define the audio behavior of your app.
AudioSessionIos.ts
export enum AudioSessionCategoryIos {
  Ambient = 'Ambient',
  SoloAmbient = 'SoloAmbient',
  Playback = 'Playback',
  Record = 'Record',
  PlayAndRecord = 'PlayAndRecord',
  MultiRoute = 'MultiRoute',
}
Ambient
category
Plays audio while respecting silent mode and allowing other audio to play simultaneously. Audio interrupts when screen locks.Use case: Background sounds, sound effects in games
SoloAmbient
category
Default category. Audio stops other apps’ audio, respects silent mode, interrupts on lock.Use case: Most apps that play audio
Playback
category
Audio continues even in silent mode and when screen locks. Stops other apps’ audio.Use case: Music players, podcast apps
Record
category
For recording audio. Silences other audio.Use case: Voice memo apps, audio recording
PlayAndRecord
category
Enables simultaneous recording and playback. Required for realtime transcription.Use case: VoIP apps, realtime transcription, video calls
MultiRoute
category
Routes audio to multiple outputs (e.g., headphones and speaker simultaneously).Use case: Specialized audio routing scenarios

Category Options

Modify category behavior with options:
AudioSessionIos.ts
export enum AudioSessionCategoryOptionIos {
  MixWithOthers = 'MixWithOthers',
  DuckOthers = 'DuckOthers',
  InterruptSpokenAudioAndMixWithOthers = 'InterruptSpokenAudioAndMixWithOthers',
  AllowBluetooth = 'AllowBluetooth',
  AllowBluetoothA2DP = 'AllowBluetoothA2DP',
  AllowAirPlay = 'AllowAirPlay',
  DefaultToSpeaker = 'DefaultToSpeaker',
}
MixWithOthers
option
Allow your audio to play simultaneously with other apps’ audio.Example: Background music in navigation app
DuckOthers
option
Lower volume of other apps’ audio while your audio plays.Example: Navigation voice prompts over music
InterruptSpokenAudioAndMixWithOthers
option
Pauses spoken audio (podcasts, audiobooks) but mixes with music.Example: Voice assistant interrupting podcast
AllowBluetooth
option
Enable Bluetooth input devices (for recording).Example: Recording with Bluetooth headset mic
AllowBluetoothA2DP
option
Enable Bluetooth A2DP output (for playback).Example: Play audio through Bluetooth speakers
AllowAirPlay
option
Enable AirPlay output routing.Example: Stream audio to AirPlay devices
DefaultToSpeaker
option
Route audio to speaker instead of receiver (for PlayAndRecord).Example: Speakerphone mode in VoIP

Modes

Modes optimize the audio session for specific use cases:
AudioSessionIos.ts
export enum AudioSessionModeIos {
  Default = 'Default',
  VoiceChat = 'VoiceChat',
  VideoChat = 'VideoChat',
  GameChat = 'GameChat',
  VideoRecording = 'VideoRecording',
  Measurement = 'Measurement',
  MoviePlayback = 'MoviePlayback',
  SpokenAudio = 'SpokenAudio',
}
Default
mode
Default mode, no special optimizations.
VoiceChat
mode
Optimized for voice chat (echo cancellation, voice processing).Use with: PlayAndRecord category
VideoChat
mode
Optimized for video calls.Use with: PlayAndRecord category
GameChat
mode
Optimized for in-game voice chat.Use with: PlayAndRecord category
VideoRecording
mode
Optimized for video recording (ambient sound capture).Use with: Record or PlayAndRecord
Measurement
mode
Disables audio processing for accurate measurements.Use with: Record category
MoviePlayback
mode
Optimized for movie/video playback.Use with: Playback category
SpokenAudio
mode
Optimized for spoken content (podcasts, audiobooks).Use with: Playback category

Methods

getCurrentCategory

Get the current audio session category and options.
const current = await AudioSessionIos.getCurrentCategory()
console.log(current.category)  // 'PlayAndRecord'
console.log(current.options)   // ['AllowBluetooth', 'DefaultToSpeaker']
category
AudioSessionCategoryIos
Current audio session category
options
AudioSessionCategoryOptionIos[]
Array of active category options

getCurrentMode

Get the current audio session mode.
const mode = await AudioSessionIos.getCurrentMode()
console.log(mode)  // 'VoiceChat'
mode
AudioSessionModeIos
Current audio session mode

setCategory

Set audio session category and options.
await AudioSessionIos.setCategory(
  AudioSessionIos.Category.PlayAndRecord,
  [
    AudioSessionIos.CategoryOption.AllowBluetooth,
    AudioSessionIos.CategoryOption.DefaultToSpeaker,
  ]
)
category
AudioSessionCategoryIos
required
The audio session category to set
options
AudioSessionCategoryOptionIos[]
required
Array of category options (can be empty)

setMode

Set audio session mode.
await AudioSessionIos.setMode(AudioSessionIos.Mode.VoiceChat)
mode
AudioSessionModeIos
required
The audio session mode to set

setActive

Activate or deactivate the audio session.
// Activate session (required before recording/playback)
await AudioSessionIos.setActive(true)

// Deactivate session
await AudioSessionIos.setActive(false)
active
boolean
required
true to activate, false to deactivate

Common Configurations

import { AudioSessionIos } from 'whisper.rn'

// Configure for recording with speaker output
await AudioSessionIos.setCategory(
  AudioSessionIos.Category.PlayAndRecord,
  [AudioSessionIos.CategoryOption.DefaultToSpeaker]
)
await AudioSessionIos.setMode(AudioSessionIos.Mode.VoiceChat)
await AudioSessionIos.setActive(true)

// Start recording...

Voice Recording Only

await AudioSessionIos.setCategory(
  AudioSessionIos.Category.Record,
  []
)
await AudioSessionIos.setMode(AudioSessionIos.Mode.Default)
await AudioSessionIos.setActive(true)

Recording with Bluetooth

await AudioSessionIos.setCategory(
  AudioSessionIos.Category.PlayAndRecord,
  [
    AudioSessionIos.CategoryOption.AllowBluetooth,
    AudioSessionIos.CategoryOption.DefaultToSpeaker,
  ]
)
await AudioSessionIos.setMode(AudioSessionIos.Mode.VoiceChat)
await AudioSessionIos.setActive(true)

Background Recording

// Configure audio session
await AudioSessionIos.setCategory(
  AudioSessionIos.Category.Record,
  [AudioSessionIos.CategoryOption.MixWithOthers]
)
await AudioSessionIos.setMode(AudioSessionIos.Mode.Default)
await AudioSessionIos.setActive(true)

// Also enable background mode in Info.plist:
// UIBackgroundModes: ['audio']

State Management Pattern

Save and Restore

type AudioSessionState = {
  category: AudioSessionCategoryIos
  options: AudioSessionCategoryOptionIos[]
  mode: AudioSessionModeIos
}

// Save current state
const saveState = async (): Promise<AudioSessionState> => {
  const category = await AudioSessionIos.getCurrentCategory()
  const mode = await AudioSessionIos.getCurrentMode()
  
  return {
    category: category.category,
    options: category.options,
    mode,
  }
}

// Restore state
const restoreState = async (state: AudioSessionState) => {
  await AudioSessionIos.setCategory(state.category, state.options)
  await AudioSessionIos.setMode(state.mode)
}

// Usage
const previousState = await saveState()

// Configure for recording
await AudioSessionIos.setCategory(
  AudioSessionIos.Category.PlayAndRecord,
  [AudioSessionIos.CategoryOption.DefaultToSpeaker]
)

// ... record audio ...

// Restore
await restoreState(previousState)

React Hook

import { useEffect } from 'react'
import { AudioSessionIos } from 'whisper.rn'

function useAudioSession(
  category: AudioSessionCategoryIos,
  options: AudioSessionCategoryOptionIos[],
  mode?: AudioSessionModeIos
) {
  useEffect(() => {
    let previousState: any

    const setup = async () => {
      // Save current state
      const currentCategory = await AudioSessionIos.getCurrentCategory()
      const currentMode = await AudioSessionIos.getCurrentMode()
      previousState = {
        category: currentCategory.category,
        options: currentCategory.options,
        mode: currentMode,
      }

      // Set new configuration
      await AudioSessionIos.setCategory(category, options)
      if (mode) {
        await AudioSessionIos.setMode(mode)
      }
      await AudioSessionIos.setActive(true)
    }

    setup()

    return () => {
      // Restore on unmount
      if (previousState) {
        AudioSessionIos.setCategory(previousState.category, previousState.options)
        AudioSessionIos.setMode(previousState.mode)
        AudioSessionIos.setActive(false)
      }
    }
  }, [category, options, mode])
}

// Usage in component
function RecordingComponent() {
  useAudioSession(
    AudioSessionIos.Category.PlayAndRecord,
    [AudioSessionIos.CategoryOption.DefaultToSpeaker],
    AudioSessionIos.Mode.VoiceChat
  )

  return <View>...</View>
}

Migration to RealtimeTranscriber

Instead of managing audio session manually, use RealtimeTranscriber with automatic session management:

Before (Deprecated)

import { AudioSessionIos } from 'whisper.rn'

// Manual configuration
await AudioSessionIos.setCategory(
  AudioSessionIos.Category.PlayAndRecord,
  [AudioSessionIos.CategoryOption.DefaultToSpeaker]
)
await AudioSessionIos.setMode(AudioSessionIos.Mode.VoiceChat)
await AudioSessionIos.setActive(true)

// Start recording with old API
const { subscribe, stop } = await whisperContext.transcribeRealtime()
import { RealtimeTranscriber } from 'whisper.rn/src/realtime-transcription'
import { AudioPcmStreamAdapter } from 'whisper.rn/src/realtime-transcription/adapters'

const audioStream = new AudioPcmStreamAdapter()

const transcriber = new RealtimeTranscriber(
  {
    whisperContext,
    audioStream,
  },
  {
    audioSliceSec: 30,
    transcribeOptions: { language: 'en' },
  },
  {
    onTranscribe: (event) => {
      console.log('Result:', event.data?.result)
    },
  }
)

await transcriber.start()
// Audio session handled automatically

Permissions

Don’t forget to request microphone permissions:

Info.plist

<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone for voice transcription</string>

Runtime Permission

import { PermissionsAndroid, Platform } from 'react-native'

const requestMicrophonePermission = async () => {
  if (Platform.OS === 'android') {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.RECORD_AUDIO
    )
    return granted === PermissionsAndroid.RESULTS.GRANTED
  }
  return true // iOS handles via Info.plist
}

Troubleshooting

This API is iOS-only. For Android, audio session management is handled differently.Solution: Wrap calls in platform check:
if (Platform.OS === 'ios') {
  await AudioSessionIos.setCategory(...)
}
Check:
  • Microphone permission granted?
  • Audio session activated? (setActive(true))
  • Correct category? (Should be Record or PlayAndRecord)
  • Device not in silent mode? (Use Playback or PlayAndRecord to ignore silent mode)
Audio can be interrupted by:
  • Phone calls
  • Other apps taking audio focus
  • Lock screen (depending on category)
Solution: Use Playback or PlayAndRecord category to continue in background
Solution: Add AllowBluetooth option:
await AudioSessionIos.setCategory(
  AudioSessionIos.Category.PlayAndRecord,
  [AudioSessionIos.CategoryOption.AllowBluetooth]
)

Build docs developers (and LLMs) love