Skip to main content

Variable: AudioSessionPresets

const AudioSessionPresets: {
music: {
android: {
contentType: "music";
focusGain: "gain";
usage: "media";
willPauseWhenDucked: false;
};
ios: {
category: "playback";
categoryOptions: never[];
mode: "defaultMode";
routeSharingPolicy: "longFormAudio";
};
};
speech: {
android: {
contentType: "speech";
focusGain: "gain";
usage: "media";
willPauseWhenDucked: true;
};
ios: {
category: "playback";
categoryOptions: never[];
mode: "spokenAudio";
routeSharingPolicy: "longFormAudio";
};
};
};

Defined in: packages/audio-session/src/presets.ts:53

Ready-made AudioSessionConfigs.

The two presets exist to encode the duck-vs-pause distinction, which is the only decision most apps ever have to make:

  • music — long-form media. Lets the system duck us automatically when a notification or navigation prompt cuts in (Android 8+ does this without ever calling us back), which is the right behaviour for music.
  • speech — podcasts / audiobooks / anything spoken. Ducked speech is unintelligible, so we opt out of automatic ducking (setWillPauseWhenDucked(true)) and ask to be told instead, and we tag the content as speech on both platforms (CONTENT_TYPE_SPEECH, AVAudioSession.Mode.spokenAudio). Android's own docs single this case out: "automatic ducking is not performed when the user is listening to speech content" and "if you want your app to pause when asked to duck […] call setWillPauseWhenDucked(true)" (https://developer.android.com/media/optimize/audio-focus).

NOTE: neither preset sets interruptSpokenAudioAndMixWithOthers. Apple reserves that option for apps whose "audio is occasional and spoken, such as in a turn-by-turn navigation app" — a podcast player is the app being interrupted, not the one interrupting.

Type Declaration

music

music: {
android: {
contentType: "music";
focusGain: "gain";
usage: "media";
willPauseWhenDucked: false;
};
ios: {
category: "playback";
categoryOptions: never[];
mode: "defaultMode";
routeSharingPolicy: "longFormAudio";
};
};

music.android

android: {
contentType: "music";
focusGain: "gain";
usage: "media";
willPauseWhenDucked: false;
};

music.android.contentType

contentType: "music" = 'music';

music.android.focusGain

focusGain: "gain" = 'gain';

music.android.usage

usage: "media" = 'media';

music.android.willPauseWhenDucked

willPauseWhenDucked: false = false;

music.ios

ios: {
category: "playback";
categoryOptions: never[];
mode: "defaultMode";
routeSharingPolicy: "longFormAudio";
};

music.ios.category

category: "playback" = 'playback';

music.ios.categoryOptions

categoryOptions: never[] = [];

music.ios.mode

mode: "defaultMode" = 'defaultMode';

music.ios.routeSharingPolicy

routeSharingPolicy: "longFormAudio" = 'longFormAudio';

speech

speech: {
android: {
contentType: "speech";
focusGain: "gain";
usage: "media";
willPauseWhenDucked: true;
};
ios: {
category: "playback";
categoryOptions: never[];
mode: "spokenAudio";
routeSharingPolicy: "longFormAudio";
};
};

speech.android

android: {
contentType: "speech";
focusGain: "gain";
usage: "media";
willPauseWhenDucked: true;
};

speech.android.contentType

contentType: "speech" = 'speech';

speech.android.focusGain

focusGain: "gain" = 'gain';

speech.android.usage

usage: "media" = 'media';

speech.android.willPauseWhenDucked

willPauseWhenDucked: true = true;

speech.ios

ios: {
category: "playback";
categoryOptions: never[];
mode: "spokenAudio";
routeSharingPolicy: "longFormAudio";
};

speech.ios.category

category: "playback" = 'playback';

speech.ios.categoryOptions

categoryOptions: never[] = [];

speech.ios.mode

mode: "spokenAudio" = 'spokenAudio';

speech.ios.routeSharingPolicy

routeSharingPolicy: "longFormAudio" = 'longFormAudio';