Skip to content

System Audio Recording

System audio recording lets you capture exactly what users hear, which is useful for apps like meeting recorders.

RecordKit supports two ways to record system audio: Core Audio and ScreenCaptureKit. By default, the most appropriate backend is selected, which works well for most setups, but you can also explicitly choose the backend when needed.

Record All System Audio

Recording all system audio is the simplest setup:

swift
let recorder = RKRecorder([
    .systemAudio()
])
try await recorder.start()
ts
const recorder = await recordkit.createRecorder({
  items: [
    {
      type: 'systemAudio'
    }
  ]
})
await recorder.start()

Prerequisite

Add NSAudioCaptureUsageDescription to your app's Info.plist. Without it, Core Audio system-audio recordings will be silent.

Choose a Backend

  • OS support: all macOS versions supported by RecordKit (macOS 13+)
  • Best fit: maximum compatibility with automatic fallback

This setting will use Core Audio on macOS 14.2+ and ScreenCaptureKit on older macOS versions.

swift
let recorder = RKRecorder([
    .systemAudio(backend: .default) // You can also omit the backend to use default
])
ts
// Omit backend to use RecordKit's default backend selection
const recorder = await recordkit.createRecorder({
  items: [
    {
      type: 'systemAudio'
    }
  ]
})

Core Audio

Core Audio has a friendlier flow where the user can grant system audio recording permissions with one click. This also ensures the user the app can't also capture the screen. It is supported on macOS 14.2+.

swift
let recorder = RKRecorder([
    .systemAudio(backend: .coreAudio)
])
ts
const recorder = await recordkit.createRecorder({
  items: [
    {
      type: 'systemAudio',
      backend: 'coreAudio'
    }
  ]
})

ScreenCaptureKit

ScreenCaptureKit is available from macOS 12.3+. It uses Screen Recording permission, which the user needs to enable in System Settings. After enabling, the app must be restarted for it to take effect.

swift
let recorder = RKRecorder([
    .systemAudio(backend: .screenCaptureKit)
])
ts
const recorder = await recordkit.createRecorder({
  items: [
    {
      type: 'systemAudio',
      mode: 'exclude',
      backend: 'screenCaptureKit',
      excludeOptions: ['currentProcess']
    }
  ]
})

Permissions

Core Audio requires NSAudioCaptureUsageDescription in your app's Info.plist.

Use RecordKit's permission helpers to check and request the correct permission for your chosen backend:

swift
let backend: RKRecorder.SystemAudioBackend = .default

if !RKAuthorization.systemAudioRecording(backend: backend) {
    try await RKAuthorization.requestSystemAudioRecording(backend: backend)
}
ts
const backend = 'default' // 'default' | '_beta_coreAudio' | 'screenCaptureKit'

if (!(await recordkit.getSystemAudioRecordingAccess({ backend }))) {
  await recordkit.requestSystemAudioRecordingAccess({ backend })
}

TIP

On macOS 26+, Screen Recording permission also grants access to system audio via Core Audio. If your app is already granted this permission, you're already covered, but still include NSAudioCaptureUsageDescription in your Info.plist.

Recording Modes

Record Everything

Use systemAudio() to record all system audio.

swift
let recorder = RKRecorder([
    .systemAudio()
])
ts
const recorder = await recordkit.createRecorder({
  items: [
    {
      type: 'systemAudio',
      mode: 'exclude',
      excludeOptions: ['currentProcess']
    }
  ]
})

Excluding Specific Apps

Use exclude mode to remove apps you do not want in the mix, for example Apple Music or Spotify.

swift
let apps = RKRunningApplication.applications()
let excluded = apps
    .filter { $0.bundleIdentifier == "com.apple.Music" || $0.bundleIdentifier == "com.spotify.client" }
    .map(\.id)

var options: Set<RKRecorder.SystemAudioExcludeOptions> = [.currentProcess]
options.formUnion(excluded.map { .processID($0) })

let recorder = RKRecorder([
    .systemAudio(excluding: options)
])
ts
const apps = await recordkit.getRunningApplications()
const excludedProcessIDs = apps
  .filter((app) => app.bundle_identifier === 'com.apple.Music' || app.bundle_identifier === 'com.spotify.client')
  .map((app) => app.id)

const recorder = await recordkit.createRecorder({
  items: [
    {
      type: 'systemAudio',
      mode: 'exclude',
      excludeOptions: ['currentProcess'],
      excludedProcessIDs
    }
  ]
})

Record Specific Apps

Use include mode when you want audio from selected apps only, for example Zoom.

swift
let apps = RKRunningApplication.applications()
let zoomIDs = apps
    .filter { $0.bundleIdentifier == "us.zoom.xos" }
    .map(\.id)

let recorder = RKRecorder([
    .systemAudio(includedApplicationIDs: zoomIDs)
])
ts
const apps = await recordkit.getRunningApplications()
const zoomIDs = apps
  .filter((app) => app.bundle_identifier === 'us.zoom.xos')
  .map((app) => app.id)

const recorder = await recordkit.createRecorder({
  items: [
    {
      type: 'systemAudio',
      mode: 'include',
      includedApplicationIDs: zoomIDs
    }
  ]
})

TIP

Some apps output audio from background processes. For supported browsers such as Safari and Chrome, RecordKit handles this process routing automatically.

Questions? Feel free to contact us at [email protected]