Skip to content

Instantly share code, notes, and snippets.

@ianfoo
Created May 15, 2026 04:35
Show Gist options
  • Select an option

  • Save ianfoo/97de7db62ef90d20f682fa6b0446a7fb to your computer and use it in GitHub Desktop.

Select an option

Save ianfoo/97de7db62ef90d20f682fa6b0446a7fb to your computer and use it in GitHub Desktop.
Working OBS + macOS (Sonoma) window capture and app audio setup

OBS macOS Recording Setup (Working Configuration)

Note

This setup and troubleshooting process was performed on macOS Sonoma.

Newer macOS releases and newer OBS versions may behave differently, especially around:

  • ScreenCaptureKit
  • per-application audio capture
  • Spaces/fullscreen handling
  • system audio routing

Some of the workarounds described here may no longer be necessary on newer versions.

This document describes a working OBS setup on macOS for:

  • recording a specific application window
  • microphone narration
  • low-volume background music
  • live monitoring of the resulting mix

This setup intentionally avoids:

  • system-wide desktop audio capture
  • recursive audio routing
  • duplicated mic capture
  • BlackHole-based system capture workflows
  • cross-Space window capture instability

Hardware / Environment

  • macOS Sonoma
  • OBS Studio
  • Blue Yeti microphone
  • Dual-monitor setup
  • Safari used for music playback (SomaFM)
  • Window capture source for tutorial/demo content

Final Working Topology

Video

Window Capture

Captures:

  • the tutorial/demo application window only

NOT:

  • the entire desktop
  • OBS itself

Important:

  • the captured window should NOT use native macOS fullscreen
  • keep the window in the same active Space while recording
  • moving the captured window between Spaces during capture caused instability

Audio Sources

1. Yeti Mic

Source type:

  • Audio Input Capture

Purpose:

  • narration

Monitoring:

  • OFF

Reason:

  • the Yeti already provides hardware monitoring
  • OBS mic monitoring caused echo/slapback

2. Safari Music Capture

Source type:

  • macOS Audio Capture
  • Method: Application Audio Capture
  • Application: Safari

Purpose:

  • background music only

Monitoring:

  • Monitor and Output

Reason:

  • isolates music from the rest of the system
  • avoids recursive system audio capture
  • avoids mic re-entry into desktop mix

OBS Monitoring

OBS Monitoring Device

Set to:

  • Yeti headphones OR
  • another physical headphone output

OBS monitoring was required to hear:

  • Safari music
  • post-fader levels
  • compressor ducking

Compressor / Ducking

A compressor filter was added to the Safari music source using:

  • sidechain/ducking from the microphone

Purpose:

  • automatically lower music volume while speaking

Critical Lessons Learned

1. Disable ALL Global Audio Devices

OBS Settings → Audio:

  • Desktop Audio: Disabled
  • Mic/Aux: Disabled
  • Everything else: Disabled

Reason:

  • duplicate audio paths caused echo/reverb
  • OBS silently accumulates overlapping capture paths

All audio sources should be explicitly added to scenes.


2. Avoid System-Wide Audio Capture

Using:

  • desktop/system audio capture
  • BlackHole system capture
  • Multi-Output Device capture

caused:

  • mic recursion
  • echo/reverb
  • unstable routing
  • difficult-to-debug audio graphs

Per-application audio capture is substantially cleaner.


3. Brave Browser Did NOT Work Reliably

OBS Application Audio Capture failed to capture audio from Brave.

Symptoms:

  • no OBS meter activity
  • no captured music

Safari worked immediately.

Likely cause:

  • Chromium/Brave interaction with macOS app audio capture APIs

Recommendation:

  • use Safari (or another native macOS app) for background music playback

4. Native macOS Fullscreen Is Cursed

Capturing windows that:

  • used native fullscreen
  • moved between Spaces
  • existed on different Spaces from OBS

caused:

  • automatic Space switching
  • focus stealing
  • "teleporting" back to another desktop
  • general Mission Control insanity

Recommendation:

  • use large/maximized windows
  • avoid native fullscreen during recording
  • keep captured windows stable while recording

5. Cross-Space Window Capture Was Unstable

OBS + macOS ScreenCaptureKit behaved poorly when:

  • OBS existed on one Space
  • captured window existed on another Space

Symptoms:

  • automatic Space switching
  • inability to remain on another desktop
  • forced focus restoration

Recommendation:

  • keep OBS and captured window within the same active Space set

Current Working Graph

Tutorial Window
  → OBS Window Capture

Safari (SomaFM)
  → OBS Application Audio Capture
    → Compressor/Ducking
      → OBS Monitoring
        → Headphones

Yeti Mic
  → OBS Audio Input Capture

OBS
  → Recording

Export / Backup

Exported:

  • OBS Scene Collection JSON

Recommendation:

  • duplicate working scene collections before experimentation
  • export scene collections periodically

Final Advice

Once the graph works:

  • stop changing topology
  • avoid adding redundant capture paths
  • avoid mixing system capture with app capture
  • avoid moving captured windows between Spaces

This setup is currently stable and usable.

{
"name": "Untitled",
"groups": [],
"scene_order": [
{
"name": "Scene"
}
],
"current_scene": "Scene",
"current_program_scene": "Scene",
"canvases": [],
"current_transition": "Fade",
"transition_duration": 300,
"transitions": [],
"quick_transitions": [
{
"name": "Cut",
"duration": 300,
"hotkeys": [],
"id": 1,
"fade_to_black": false
},
{
"name": "Fade",
"duration": 300,
"hotkeys": [],
"id": 2,
"fade_to_black": false
},
{
"name": "Fade",
"duration": 300,
"hotkeys": [],
"id": 3,
"fade_to_black": true
}
],
"saved_projectors": [],
"preview_locked": false,
"scaling_enabled": false,
"scaling_level": -7,
"scaling_off_x": 0.0,
"scaling_off_y": 0.0,
"virtual-camera": {
"type2": 3
},
"modules": {
"scripts-tool": [],
"output-timer": {
"streamTimerHours": 0,
"streamTimerMinutes": 0,
"streamTimerSeconds": 30,
"recordTimerHours": 0,
"recordTimerMinutes": 0,
"recordTimerSeconds": 30,
"autoStartStreamTimer": false,
"autoStartRecordTimer": false,
"pauseRecordTimer": true
},
"auto-scene-switcher": {
"interval": 300,
"non_matching_scene": "",
"switch_if_not_matching": false,
"active": false,
"switches": []
}
},
"resolution": {
"x": 1920,
"y": 1080
},
"version": 2,
"sources": [
{
"prev_ver": 536936450,
"name": "macOS Audio Capture",
"uuid": "4d4bdd1b-3204-4976-ba75-d9cb452e9a9a",
"id": "sck_audio_capture",
"versioned_id": "sck_audio_capture",
"settings": {
"type": 1,
"application": "com.apple.Safari"
},
"mixers": 255,
"sync": 0,
"flags": 0,
"volume": 0.3542580008506775,
"balance": 0.5,
"enabled": true,
"muted": false,
"push-to-mute": false,
"push-to-mute-delay": 0,
"push-to-talk": false,
"push-to-talk-delay": 0,
"hotkeys": {
"libobs.mute": [],
"libobs.unmute": [],
"libobs.push-to-mute": [],
"libobs.push-to-talk": []
},
"deinterlace_mode": 0,
"deinterlace_field_order": 0,
"monitoring_type": 2,
"private_settings": {}
},
{
"prev_ver": 536936450,
"name": "Scene",
"uuid": "8187e710-81b1-4c98-8981-f2c7789a474f",
"id": "scene",
"versioned_id": "scene",
"settings": {
"id_counter": 10,
"custom_size": false,
"items": [
{
"name": "Yeti Mic",
"source_uuid": "2df72666-04b2-4908-af6f-a48052b17df8",
"visible": true,
"locked": false,
"rot": 0.0,
"scale_ref": {
"x": 1920.0,
"y": 1080.0
},
"align": 5,
"bounds_type": 0,
"bounds_align": 0,
"bounds_crop": false,
"crop_left": 0,
"crop_top": 0,
"crop_right": 0,
"crop_bottom": 0,
"id": 1,
"group_item_backup": false,
"pos": {
"x": 0.0,
"y": 0.0
},
"pos_rel": {
"x": -1.7777777910232544,
"y": -1.0
},
"scale": {
"x": 1.0,
"y": 1.0
},
"scale_rel": {
"x": 1.0,
"y": 1.0
},
"bounds": {
"x": 0.0,
"y": 0.0
},
"bounds_rel": {
"x": 0.0,
"y": 0.0
},
"scale_filter": "disable",
"blend_method": "default",
"blend_type": "normal",
"show_transition": {
"duration": 0
},
"hide_transition": {
"duration": 0
},
"private_settings": {}
},
{
"name": "Window Capture",
"source_uuid": "46bb722f-6dfc-4951-a128-94e09420eb80",
"visible": true,
"locked": false,
"rot": 0.0,
"scale_ref": {
"x": 1920.0,
"y": 1080.0
},
"align": 5,
"bounds_type": 2,
"bounds_align": 0,
"bounds_crop": false,
"crop_left": 0,
"crop_top": 0,
"crop_right": 0,
"crop_bottom": 0,
"id": 8,
"group_item_backup": false,
"pos": {
"x": 0.0,
"y": 0.0
},
"pos_rel": {
"x": -1.7777777910232544,
"y": -1.0
},
"scale": {
"x": 1.0,
"y": 1.0
},
"scale_rel": {
"x": 1.0,
"y": 1.0
},
"bounds": {
"x": 1920.0,
"y": 1080.0
},
"bounds_rel": {
"x": 3.555555582046509,
"y": 2.0
},
"scale_filter": "disable",
"blend_method": "default",
"blend_type": "normal",
"show_transition": {
"duration": 300
},
"hide_transition": {
"duration": 300
},
"private_settings": {}
},
{
"name": "Webcam",
"source_uuid": "e4c5cbdd-1270-4a04-bedb-60a1185aa76d",
"visible": true,
"locked": false,
"rot": 0.0,
"scale_ref": {
"x": 1920.0,
"y": 1080.0
},
"align": 5,
"bounds_type": 0,
"bounds_align": 0,
"bounds_crop": false,
"crop_left": 0,
"crop_top": 0,
"crop_right": 0,
"crop_bottom": 0,
"id": 6,
"group_item_backup": false,
"pos": {
"x": 1504.0,
"y": 846.0
},
"pos_rel": {
"x": 1.0074074268341064,
"y": 0.5666667222976685
},
"scale": {
"x": 0.32499998807907104,
"y": 0.32499998807907104
},
"scale_rel": {
"x": 0.32499998807907104,
"y": 0.32499998807907104
},
"bounds": {
"x": 0.0,
"y": 0.0
},
"bounds_rel": {
"x": 0.0,
"y": 0.0
},
"scale_filter": "disable",
"blend_method": "default",
"blend_type": "normal",
"show_transition": {
"duration": 0
},
"hide_transition": {
"duration": 0
},
"private_settings": {}
},
{
"name": "macOS Audio Capture",
"source_uuid": "4d4bdd1b-3204-4976-ba75-d9cb452e9a9a",
"visible": true,
"locked": false,
"rot": 0.0,
"scale_ref": {
"x": 1920.0,
"y": 1080.0
},
"align": 5,
"bounds_type": 0,
"bounds_align": 0,
"bounds_crop": false,
"crop_left": 0,
"crop_top": 0,
"crop_right": 0,
"crop_bottom": 0,
"id": 10,
"group_item_backup": false,
"pos": {
"x": 0.0,
"y": 0.0
},
"pos_rel": {
"x": -1.7777777910232544,
"y": -1.0
},
"scale": {
"x": 1.0,
"y": 1.0
},
"scale_rel": {
"x": 1.0,
"y": 1.0
},
"bounds": {
"x": 0.0,
"y": 0.0
},
"bounds_rel": {
"x": 0.0,
"y": 0.0
},
"scale_filter": "disable",
"blend_method": "default",
"blend_type": "normal",
"show_transition": {
"duration": 300
},
"hide_transition": {
"duration": 300
},
"private_settings": {}
}
]
},
"mixers": 0,
"sync": 0,
"flags": 0,
"volume": 1.0,
"balance": 0.5,
"enabled": true,
"muted": false,
"push-to-mute": false,
"push-to-mute-delay": 0,
"push-to-talk": false,
"push-to-talk-delay": 0,
"hotkeys": {
"OBSBasic.SelectScene": [],
"libobs.show_scene_item.1": [],
"libobs.hide_scene_item.1": [],
"libobs.show_scene_item.8": [],
"libobs.hide_scene_item.8": [],
"libobs.show_scene_item.6": [],
"libobs.hide_scene_item.6": [],
"libobs.show_scene_item.10": [],
"libobs.hide_scene_item.10": []
},
"deinterlace_mode": 0,
"deinterlace_field_order": 0,
"monitoring_type": 0,
"canvas_uuid": "6c69626f-6273-4c00-9d88-c5136d61696e",
"private_settings": {}
},
{
"prev_ver": 536936450,
"name": "Webcam",
"uuid": "e4c5cbdd-1270-4a04-bedb-60a1185aa76d",
"id": "macos-avcapture",
"versioned_id": "macos-avcapture",
"settings": {
"device_name": "Lumina Camera - Plus",
"device": "F082684F-167F-40BE-8516-1725B75752BD"
},
"mixers": 255,
"sync": 0,
"flags": 0,
"volume": 1.0,
"balance": 0.5,
"enabled": true,
"muted": false,
"push-to-mute": false,
"push-to-mute-delay": 0,
"push-to-talk": false,
"push-to-talk-delay": 0,
"hotkeys": {
"libobs.mute": [],
"libobs.unmute": [],
"libobs.push-to-mute": [],
"libobs.push-to-talk": []
},
"deinterlace_mode": 0,
"deinterlace_field_order": 0,
"monitoring_type": 0,
"private_settings": {}
},
{
"prev_ver": 536936450,
"name": "Window Capture",
"uuid": "46bb722f-6dfc-4951-a128-94e09420eb80",
"id": "screen_capture",
"versioned_id": "screen_capture",
"settings": {
"type": 1,
"window": 59893
},
"mixers": 255,
"sync": 0,
"flags": 0,
"volume": 1.0,
"balance": 0.5,
"enabled": true,
"muted": false,
"push-to-mute": false,
"push-to-mute-delay": 0,
"push-to-talk": false,
"push-to-talk-delay": 0,
"hotkeys": {
"libobs.mute": [],
"libobs.unmute": [],
"libobs.push-to-mute": [],
"libobs.push-to-talk": []
},
"deinterlace_mode": 0,
"deinterlace_field_order": 0,
"monitoring_type": 0,
"private_settings": {}
},
{
"prev_ver": 536936450,
"name": "Yeti Mic",
"uuid": "2df72666-04b2-4908-af6f-a48052b17df8",
"id": "coreaudio_input_capture",
"versioned_id": "coreaudio_input_capture",
"settings": {
"device_id": "AppleUSBAudioEngine:Blue Microphones:Yeti Stereo Microphone:797_2019/03/11_49137:2"
},
"mixers": 255,
"sync": 0,
"flags": 0,
"volume": 1.0,
"balance": 0.5,
"enabled": true,
"muted": false,
"push-to-mute": false,
"push-to-mute-delay": 0,
"push-to-talk": false,
"push-to-talk-delay": 0,
"hotkeys": {
"libobs.mute": [],
"libobs.unmute": [],
"libobs.push-to-mute": [],
"libobs.push-to-talk": []
},
"deinterlace_mode": 0,
"deinterlace_field_order": 0,
"monitoring_type": 0,
"private_settings": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment