1. Architecture Overview
OBS Studio is a cross-platform video production application written in C and C++ (C17/C++17). It provides real-time video compositing, audio mixing, encoding, and output to streaming services or local files. The architecture separates a portable core library (libobs) from platform-specific frontends, plugins, and rendering backends, enabling modular development and broad platform support.
System Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ OBS Studio Frontend │
│ (Qt6 GUI — frontend/) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐│
│ │ Widgets │ │ Settings │ │ Dialogs │ │ Wizards │ │ Docks ││
│ │(OBSBasic)│ │(Profiles)│ │(Filters) │ │(AutoConf)│ │(Mixer, ││
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ Stats) ││
│ │ │ │ │ └────┬─────┘│
│ ┌────┴────────────┴────────────┴────────────┴────────────┴─────┐│
│ │ Frontend API (frontend/api/) ││
│ └──────────────────────────┬────────────────────────────────────┘│
└─────────────────────────────┼────────────────────────────────────┘
│
┌─────────────────────────────┼────────────────────────────────────┐
│ libobs (Core) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Scenes │ │ Sources │ │ Encoders │ │ Outputs │ │
│ │& Sources │ │& Filters │ │(H264/AV1)│ │(RTMP/FLV)│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ ┌────┴────────────┴────────────┴────────────┴───────────────┐ │
│ │ Core Services │ │
│ │ Video Rendering │ Audio Mixing │ Hotkeys │ Properties │ │
│ └────┬─────────────┴──────────────┴─────────┴───────────┬───┘ │
│ │ │ │
│ ┌────┴─────┐ ┌───────────┐ ┌────────────┐ ┌────────┴────┐ │
│ │ Graphics │ │ Media I/O │ │ Callbacks │ │ Util │ │
│ │ (gs_*) │ │(audio/vid)│ │ (signals) │ │(threading, │ │
│ └────┬─────┘ └───────────┘ └────────────┘ │ bmem, dstr) │ │
│ │ └─────────────┘ │
└───────┼─────────────────────────────────────────────────────────┘
│
┌───────┼─────────────────────────────────────┐
│ Graphics Backends (one per platform) │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ D3D11 │ │ OpenGL │ │ Metal │ │
│ │(Windows) │ │(All) │ │(macOS ARM64) │ │
│ └──────────┘ └──────────┘ └──────────────┘ │
└──────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Plugins │
│ Video Capture: win-capture, mac-capture, linux-capture, ... │
│ Audio Capture: win-wasapi, linux-pulseaudio, coreaudio, ... │
│ Encoders: obs-x264, obs-nvenc, obs-qsv11, obs-ffmpeg, ... │
│ Outputs: obs-outputs (RTMP/FLV), obs-webrtc (WHIP) │
│ Sources: image-source, obs-browser (CEF), vlc-video, ... │
│ Filters: obs-filters (chroma, color, noise, delay, ...) │
│ Transitions: obs-transitions (cut, fade, swipe, stinger, ...) │
│ Services: rtmp-services (200+ streaming platforms) │
│ Other: obs-vst, obs-websocket, obs-scripting │
└─────────────────────────────────────────────────────────────────┘
Component Inventory
| Component | Path | Role |
|---|---|---|
| libobs | libobs/ |
Core library: scene graph, source management, audio/video pipeline, encoding, output, hotkeys, properties, signals, configuration |
| libobs-d3d11 | libobs-d3d11/ |
Direct3D 11 graphics backend (Windows) |
| libobs-opengl | libobs-opengl/ |
OpenGL graphics backend (all platforms) |
| libobs-metal | libobs-metal/ |
Metal graphics backend (macOS Apple Silicon) |
| libobs-winrt | libobs-winrt/ |
Windows Runtime helpers (WinRT capture, window enumeration) |
| Frontend | frontend/ |
Qt6 GUI application: main window, settings, dialogs, docks, wizards, updater, OAuth, plugin management |
| Frontend API | frontend/api/ |
C API for frontend plugins to interact with the main window |
| Plugins | plugins/ |
Modular input/output/encoder/filter/transition/service plugins |
| Shared Libraries | shared/ |
Reusable components: scripting engine, media playback, properties view, IPC, BPM detection |
| Build System | cmake/ |
CMake modules, finders, platform-specific build logic |
| Tests | test/ |
Unit and integration tests (cmocka-based) |
| Documentation | docs/sphinx/ |
Sphinx-based API documentation (C domain) |
Technology Stack
| Layer | Technology |
|---|---|
| Language | C17, C++17, Objective-C/C++ (macOS), Swift (macOS camera extension) |
| GUI Framework | Qt6 (Widgets, SVG) |
| Build System | CMake 3.28+ with presets |
| Graphics APIs | Direct3D 11, OpenGL 3.3+, Metal |
| Media Framework | FFmpeg (libavcodec, libavutil, libavformat) |
| JSON | jansson |
| HTTP | libcurl |
| TLS | mbedTLS (RTMP), platform TLS |
| Testing | cmocka |
| Scripting | LuaJIT, Python 3 (via SWIG bindings) |
| Browser Integration | Chromium Embedded Framework (CEF) |
| Real-time Comms | libdatachannel (WebRTC/WHIP) |
| Audio Processing | RNNoise (ML noise suppression), Speex (DSP noise suppression) |
| Hashing | BLAKE2b (updater file verification) |
Data Flow: Streaming Pipeline
Sources (capture) → Scene Compositor → Video Encoder → Output (RTMP/WHIP)
↘ ↗
Audio Sources → Audio Mixer → Audio Encoder
- Capture: Platform-specific plugins grab video frames (display, window, camera) and audio samples (WASAPI, PulseAudio, CoreAudio)
- Composition:
libobscomposites sources into scenes using the selected graphics backend with GPU-accelerated rendering - Filtering: Source and audio filters (chroma key, color correction, noise suppression) process frames/samples in real-time
- Encoding: Hardware (NVENC, AMF, QSV, VideoToolbox) or software (x264, FFmpeg) encoders compress video and audio
- Output: Encoded data is muxed (FLV, MKV, MP4) and sent to a streaming service via RTMP/RTMPS or written to disk
Note
The audio subsystem automatically synchronizes audio to video frames. Audio delay filters exist but are rarely needed because the core pipeline handles A/V sync internally.
2. System Requirements
Build Requirements
| Requirement | Version | Notes |
|---|---|---|
| CMake | 3.28+ | Build system generator |
| C Compiler | C17 support | GCC 11+, Clang 14+, MSVC 19.30+ |
| C++ Compiler | C++17 support | Same as above |
| Qt6 | 6.x (Base, SVG) | Pre-built binaries available via obs-deps |
| FFmpeg | Latest stable | avcodec, avutil, avformat |
| jansson | Any recent | JSON parsing |
| libcurl | Any recent | HTTP client |
| Python 3 | 3.x (optional) | For scripting support |
| SWIG | Any recent (optional) | Script binding generation |
| LuaJIT | 2.x (optional) | Lua scripting support |
Platform-Specific Build Dependencies
Windows:
- Visual Studio 2022 (v17)
- Windows SDK 10.0.22621.0
- Pre-built obs-deps (Qt6, FFmpeg, and other dependencies — auto-downloaded by CMake)
macOS:
- Xcode with Swift 5.0 support
- macOS deployment target: 12.0 (general), 13.0 (camera extension)
- Signing identity for camera extension system extension
Linux:
- Ninja build system
- X11, PipeWire, PulseAudio development headers
- v4l2 development headers
- Additional: librist, srt, nlohmann-json, websocketpp, asio, fdk-aac
Runtime Requirements
| Component | Windows | macOS | Linux |
|---|---|---|---|
| GPU Driver | DirectX 10.1+ | Metal or OpenGL | Mesa with OpenGL 3.3+ |
| NVENC | NVIDIA driver 470+ | N/A | NVIDIA driver 470+ |
| QSV | Intel driver with MediaSDK | N/A | Intel Media Driver |
| AMF | AMD driver 21.5+ | N/A | AMD driver with AMF SDK |
| Virtual Camera | Built-in DirectShow filter | System Extension (CoreMediaIO) | v4l2loopback kernel module |
| Browser Source | CEF included | CEF included | CEF included |
| VLC Source | VLC 3.x installed | VLC 3.x installed | libvlc installed |
Important
The macOS virtual camera uses a System Extension (not a kernel extension). This requires the application to be properly signed and the user to approve the extension in System Settings → Privacy & Security. The camera extension requires macOS 13.0+ and UUIDs configured at build time (
VIRTUALCAM_DEVICE_UUID,VIRTUALCAM_SOURCE_UUID,VIRTUALCAM_SINK_UUID).
3. Configuration Reference
Configuration File Structure
OBS uses INI-format configuration files organized hierarchically:
| File | Scope | Format | Purpose |
|---|---|---|---|
global.ini |
Application | INI | Renderer, language, update settings, log retention |
user.ini |
User | INI | UI layout, preview state, dock arrangement |
basic/profiles/{name}/basic.ini |
Profile | INI | Video, audio, output, streaming, hotkeys |
basic/profiles/{name}/service.json |
Profile | JSON | Streaming service configuration |
basic/scenes/{name}.json |
Scene Collection | JSON | Scene graph, sources, transforms, filters |
plugin_config/ |
User | Various | Per-plugin configuration storage |
plugin_manager/ |
User | JSON | Plugin manager state and settings |
Global Configuration (global.ini)
| Section | Key | Type | Default | Description |
|---|---|---|---|---|
General |
MaxLogs |
uint | 10 |
Maximum number of log files to retain |
General |
InfoIncrement |
int | -1 |
Info display increment counter |
General |
ProcessPriority |
string | Normal |
OS process priority (Normal, AboveNormal, High) |
General |
EnableAutoUpdates |
bool | true |
Enable automatic update checks |
General |
BrowserHWAccel |
bool | true |
Hardware acceleration for browser sources (Windows/macOS/Linux) |
Video |
Renderer |
string | Direct3D 11 (Win) / OpenGL (other) |
Graphics rendering backend |
Audio |
DisableAudioDucking |
bool | true (Windows) |
Prevent Windows from reducing OBS audio when other apps use audio |
Video |
DisableOSXVSync |
bool | true (macOS) |
Disable macOS VSync |
Video |
ResetOSXVSyncOnExit |
bool | true (macOS) |
Restore VSync state on exit |
Locations |
Configuration |
string | Platform default | Base path for configuration files |
Locations |
SceneCollections |
string | Platform default | Path for scene collection storage |
Locations |
Profiles |
string | Platform default | Path for profile storage |
Locations |
PluginManagerSettings |
string | Platform default | Path for plugin manager data |
User Configuration (user.ini)
| Section | Key | Type | Default | Description |
|---|---|---|---|---|
General |
ConfirmOnExit |
bool | true |
Show confirmation dialog on exit |
General |
HotkeyFocusType |
string | NeverDisableHotkeys |
Hotkey behavior when OBS is unfocused |
BasicWindow |
PreviewEnabled |
bool | true |
Show the preview canvas |
BasicWindow |
PreviewProgramMode |
bool | false |
Enable Studio Mode by default |
BasicWindow |
SceneDuplicationMode |
bool | true |
Allow scene duplication |
BasicWindow |
SwapScenesMode |
bool | true |
Enable scene swapping |
BasicWindow |
SnappingEnabled |
bool | true |
Enable source snapping |
BasicWindow |
ScreenSnapping |
bool | true |
Snap to screen edges |
BasicWindow |
SourceSnapping |
bool | true |
Snap to other sources |
BasicWindow |
CenterSnapping |
bool | false |
Snap to center lines |
BasicWindow |
SnapDistance |
double | 10.0 |
Snap distance in pixels |
BasicWindow |
SpacingHelpersEnabled |
bool | true |
Show spacing guides |
BasicWindow |
RecordWhenStreaming |
bool | false |
Auto-record when streaming starts |
BasicWindow |
KeepRecordingWhenStreamStops |
bool | false |
Continue recording after stream stops |
BasicWindow |
SysTrayEnabled |
bool | true |
Show system tray icon |
BasicWindow |
SysTrayWhenStarted |
bool | false |
Minimize to tray on launch |
BasicWindow |
SaveProjectors |
bool | false |
Persist projector windows across sessions |
BasicWindow |
ShowTransitions |
bool | true |
Show transition controls |
BasicWindow |
ShowListboxToolbars |
bool | true |
Show toolbars on source/scene lists |
BasicWindow |
ShowStatusBar |
bool | true |
Show bottom status bar |
BasicWindow |
ShowSourceIcons |
bool | true |
Show source type icons in list |
BasicWindow |
ShowContextToolbars |
bool | true |
Show source-specific toolbars |
BasicWindow |
StudioModeLabels |
bool | true |
Show Preview/Program labels in Studio Mode |
BasicWindow |
SideDocks |
bool | true |
Use side dock layout |
BasicWindow |
VerticalVolumeControl |
bool | true |
Vertical audio mixer layout |
BasicWindow |
MultiviewMouseSwitch |
bool | true |
Switch scenes by clicking in multiview |
BasicWindow |
MultiviewDrawNames |
bool | true |
Draw scene names in multiview |
BasicWindow |
MultiviewDrawAreas |
bool | true |
Draw safe areas in multiview |
BasicWindow |
MediaControlsCountdownTimer |
bool | true |
Show countdown timer on media sources |
BasicWindow |
MixerShowInactive |
bool | false |
Show inactive audio sources in mixer |
BasicWindow |
MixerKeepInactiveLast |
bool | false |
Sort inactive sources to bottom |
BasicWindow |
MixerShowHidden |
bool | false |
Show hidden audio sources |
BasicWindow |
MixerKeepHiddenLast |
bool | false |
Sort hidden sources to bottom |
Appearance |
FontScale |
int | 10 |
UI font scale factor |
Appearance |
Density |
int | 1 |
UI element density |
Profile Configuration (basic.ini)
| Section | Key | Type | Description |
|---|---|---|---|
Video |
BaseCX / BaseCY |
uint | Base (canvas) resolution |
Video |
OutputCX / OutputCY |
uint | Output (scaled) resolution |
Video |
FPSType |
int | FPS mode (0=common, 1=integer, 2=fractional) |
Video |
FPSCommon |
string | Common FPS value (e.g., "30", "60") |
SimpleOutput |
VBitrate |
int | Video bitrate (Kbps) |
SimpleOutput |
ABitrate |
int | Audio bitrate (Kbps) |
SimpleOutput |
StreamEncoder |
string | Encoder for streaming |
SimpleOutput |
RecEncoder |
string | Encoder for recording |
SimpleOutput |
RecFormat |
string | Recording container format |
SimpleOutput |
RecFilePath |
string | Recording output directory |
Audio |
SampleRate |
int | Sample rate (44100 or 48000) |
Audio |
ChannelSetup |
string | Channel layout (Mono, Stereo, etc.) |
Audio |
MeterDecayRate |
double | Audio meter decay speed |
Audio |
PeakMeterType |
uint | 0=Sample Peak, 1=True Peak |
Stream1 |
EnableMultitrackVideo |
bool | Enable multitrack video for supported services |
Important
Resolution values must be between 32 and 16384 pixels in both dimensions. Values outside this range are rejected by the settings validation logic.
Streaming Service Configuration (service.json)
{
"type": "rtmp_common",
"settings": {
"service": "Twitch",
"server": "auto",
"key": "live_xxxxxxxxxxxxxxxxxxxx",
"protocol": "RTMPS"
}
}
| Field | Type | Description |
|---|---|---|
type |
string | Service type: rtmp_common (built-in services), rtmp_custom (custom RTMP server), whip_custom (WebRTC WHIP) |
settings.service |
string | Service name from the built-in database |
settings.server |
string | Ingest server URL or auto |
settings.key |
string | Stream key |
settings.protocol |
string | Protocol: RTMP, RTMPS, or auto-detected |
CMake Build Configuration
OBS uses CMake presets defined in CMakePresets.json:
| Preset | Platform | Generator | Description |
|---|---|---|---|
macos |
macOS | Xcode | Default macOS build (single architecture) |
ubuntu |
Linux | Ninja | Ubuntu debug build |
windows-x64 |
Windows | Visual Studio 17 2022 | Default Windows x64 build |
windows-arm64 |
Windows | Visual Studio 17 2022 | Windows ARM64 build |
Environment variables for streaming service OAuth:
| Variable | Purpose |
|---|---|
TWITCH_CLIENTID |
Twitch OAuth client ID |
TWITCH_HASH |
Twitch client ID hash |
YOUTUBE_CLIENTID |
YouTube OAuth client ID |
YOUTUBE_CLIENTID_HASH |
YouTube client ID hash |
YOUTUBE_SECRET |
YouTube OAuth secret |
YOUTUBE_SECRET_HASH |
YouTube secret hash |
RESTREAM_CLIENTID |
Restream OAuth client ID |
RESTREAM_HASH |
Restream client ID hash |
CODESIGN_IDENT |
macOS code signing identity |
CODESIGN_TEAM |
macOS code signing team |
GPU_PRIORITY_VAL |
Windows GPU scheduling priority |
Note
OAuth credentials are only needed for builds that enable first-party Twitch, YouTube, or Restream integration. Community or custom builds can omit these variables — the services remain usable with manual stream key entry.
CMake Feature Flags
| Flag | Type | Default | Description |
|---|---|---|---|
ENABLE_AJA |
bool | true (x64 only) |
AJA capture card support |
ENABLE_BROWSER |
bool | true |
Browser source (CEF) support |
ENABLE_DECKLINK |
bool | Platform-dependent | Blackmagic Decklink support |
ENABLE_JACK |
bool | false |
JACK audio support |
ENABLE_SNDIO |
bool | false |
sndio audio support |
ENABLE_LIBFDK |
bool | false |
FDK AAC encoder |
ENABLE_SCRIPTING |
bool | true |
Lua/Python scripting support |
ENABLE_VLC |
bool | true (Ubuntu) |
VLC video source |
ENABLE_VST |
bool | true |
VST plugin hosting |
ENABLE_WAYLAND |
bool | true (Ubuntu) |
Wayland capture support |
ENABLE_WEBRTC |
bool | false (Ubuntu) |
WebRTC WHIP output |
ENABLE_FFMPEG_MUX_DEBUG |
bool | false |
Debug logging for FFmpeg muxer |
ENABLE_HEVC |
bool | true |
HEVC/H.265 codec support |
4. Deployment & Scaling
Windows Deployment
The official Windows release is built using the windows-x64 (or windows-arm64) CMake preset with Visual Studio 2022:
cmake --preset windows-x64
cmake --build --preset windows-x64
Pre-built dependencies (Qt6, FFmpeg, CEF) are automatically downloaded from the obs-deps GitHub releases during the CMake configuration step. The build produces:
obs64.exe— main application binaryobs-plugins/— plugin DLLsdata/— themes, locale files, shader effects, service definitionsobs-ffmpeg-mux.exe— separate FFmpeg muxer processobs-amf-test.exe— AMD AMF capability testobs-nvenc-test.exe— NVENC capability testobs-qsv-test.exe— QSV capability testinject-helper64.exe/inject-helper32.exe— Game Capture injection helpersget-graphics-offsets64.exe/get-graphics-offsets32.exe— D3D hook offset calculators
Warning
The Game Capture system injects a DLL into target processes to intercept DirectX/OpenGL/Vulkan rendering. The
inject-helperandget-graphics-offsetsexecutables must match the target process architecture (32-bit or 64-bit). Anti-cheat software may interfere with this injection.
macOS Deployment
The macOS build produces an .app bundle suitable for DMG distribution:
- The virtual camera requires a properly signed System Extension (
com.obsproject.obs-studio.mac-camera-extension) - The DAL plugin (
obs-mac-virtualcam) provides legacy virtual camera support as a universal binary (x86_64 + arm64) - The app requires entitlements for camera, microphone, and screen capture access
- Auto-update is handled by the Sparkle 2 framework (version 2.6.4), with update feeds per-architecture from
obsproject.com/osx_update/
Linux Deployment
Linux builds target Ubuntu 22.04+ with system-provided dependencies:
cmake --preset ubuntu
cmake --build build_ubuntu
Distribution-specific packaging:
- PPA: Official Ubuntu PPA at
ppa:obsproject/obs-studio - Flatpak: Available on Flathub as
com.obsproject.Studio - FreeBSD: Available in ports as
obs-studio
Portable Mode
Launch with --portable to store all configuration alongside the executable. This is useful for USB installations or environments where user directory access is restricted.
5. Operations
Logging
OBS writes detailed logs to obs-studio/logs/ in the configuration directory. Logs include:
- System information (OS, CPU, GPU, RAM, driver versions)
- Loaded plugins and their versions
- Encoder initialization (success/failure with error codes)
- Audio/video device enumeration
- Streaming connection events (connect, disconnect, dropped frames)
- All
blog()output at LOG_INFO, LOG_WARNING, and LOG_ERROR levels
Log retention is controlled by MaxLogs in global.ini (default: 10).
Log upload: Users can upload logs via Help → Log Files → Upload Current/Last Log File. Logs are uploaded and a shareable URL is provided. The OBS online analyzer at obsproject.com/tools/analyzer parses uploaded logs for common issues.
Tip
When diagnosing user issues, always request the OBS log file. It contains encoder initialization results, rendering pipeline status, dropped frame counts, and any errors that occurred during the session.
Auto-Update System
Windows: OBS includes a built-in updater (frontend/updater/) that:
- Downloads update manifests from
obsproject.com - Verifies file integrity using BLAKE2b hashes
- Applies differential updates
- Requires elevation for file replacement
macOS: Updates are delivered via the Sparkle framework, checking obsproject.com/osx_update/updates_{arch}_v2.xml for the appropriate architecture.
Linux: Updates are managed by the distribution's package manager (apt, flatpak).
Crash Handling
When OBS detects an unclean shutdown (crash or forced termination), the next launch presents a dialog offering:
- Safe Mode — launches with all third-party plugins disabled
- Normal Launch — launches normally
- Send Crash Report — uploads the crash log (with user consent, privacy notice displayed)
Crash logs are stored in obs-studio/crashes/ (Windows only). The crash handler reports the last crash log file path for analysis.
Safe Mode
Safe Mode (--safe-mode) disables all third-party plugins, allowing users to recover from plugin-caused crashes or instability. When Safe Mode is active:
- Only bundled OBS plugins are loaded
- Third-party plugin directories are skipped
- A warning indicator is shown in the UI
Profile and Scene Collection Management
Profiles and scene collections are stored as files in the configuration directory:
obs-studio/
├── basic/
│ ├── profiles/
│ │ ├── Untitled/
│ │ │ ├── basic.ini
│ │ │ └── service.json
│ │ └── Streaming/
│ │ ├── basic.ini
│ │ └── service.json
│ └── scenes/
│ ├── Untitled.json
│ └── Gaming.json
└── plugin_config/
└── obs-browser/
Tip
Back up the entire
obs-studio/basic/directory to preserve all profiles and scene collections. This includes service configurations (stream keys), output settings, and complete scene graphs.
Monitoring and Diagnostics
Status bar indicators:
| Indicator | Meaning |
|---|---|
| CPU % | Encoding CPU usage (0% for hardware encoders) |
| FPS | Current rendering frame rate |
| Dropped frames | Frames dropped due to network congestion |
| Bitrate | Current output bitrate (Kbps) |
| Recording time | Elapsed recording duration |
| Streaming time | Elapsed streaming duration |
Stats dock (View → Stats): Provides detailed real-time metrics including:
- Frames missed due to rendering lag
- Frames skipped due to encoding lag
- Network dropped frames
- Memory usage
- Disk write speed
6. Performance
Encoder Performance Comparison
| Encoder | Plugin | Type | CPU Impact | GPU Impact | Quality/Bitrate Ratio |
|---|---|---|---|---|---|
| x264 | obs-x264 |
Software | High | None | Excellent |
| NVENC H.264/HEVC/AV1 | obs-nvenc |
Hardware | Minimal | Low-Moderate | Very Good (Turing+) |
| AMD AMF H.264/HEVC/AV1 | obs-ffmpeg |
Hardware | Minimal | Low-Moderate | Good |
| Intel QSV H.264/HEVC | obs-qsv11 |
Hardware | Minimal | Low-Moderate | Good |
| Apple VideoToolbox | mac-videotoolbox |
Hardware | Minimal | Low | Good |
| FFmpeg VAAPI | obs-ffmpeg |
Hardware | Minimal | Low-Moderate | Good |
GPU Scheduling (Windows)
OBS sets GPU priority via the GPU_PRIORITY_VAL build variable. The application exports NvOptimusEnablement = 1 and AmdPowerXpressRequestHighPerformance = 1 to request the discrete GPU on hybrid GPU systems (laptops with integrated + dedicated GPUs).
Resolution Scaling
The downscale filter choice affects both performance and visual quality:
| Filter | Quality | Performance Cost |
|---|---|---|
| Bilinear | Lowest (soft) | Fastest |
| Bicubic | Medium (balanced) | Moderate |
| Lanczos | Highest (sharp) | Highest |
Audio Performance
Audio processing uses SSE-optimized paths for peak metering. True peak measurement implements 5x oversampling using Whittaker-Shannon interpolation with SSE intrinsics for efficient SIMD computation.
Note
The audio processing pipeline requires 16-byte aligned sample buffers for SSE peak metering. If a buffer is not aligned, OBS falls back to setting peak to 1.0 (full scale) and logs a warning.
7. Security
Process Injection (Game Capture)
The Windows Game Capture system injects a shared library (graphics-hook64.dll / graphics-hook32.dll) into target processes to intercept Direct3D and OpenGL rendering calls. This is:
- Architecturally necessary for capturing fullscreen exclusive games
- Potentially flagged by anti-virus and anti-cheat software
- Privilege-scoped — the inject helper runs at the same privilege level as the target process
The get-graphics-offsets helper calculates memory offsets for D3D8, D3D9, D3D10, D3D11, D3D12, and Vulkan/DXGI hooks by creating temporary rendering contexts and reading function pointer tables.
Stream Key Security
Stream keys are stored in plaintext in service.json within the user's profile directory. The files inherit OS-level user permissions. There is no application-level encryption of credentials.
Caution
Stream keys stored in profile files (
service.json) are in plaintext. Ensure the configuration directory has appropriate file system permissions. Never share profile backups without removing stream keys. If a key is compromised, regenerate it immediately in the streaming service's dashboard.
OAuth Integration
OBS supports OAuth authentication for Twitch, YouTube, and Restream. The OAuth flow:
- Opens a browser window to the service's authorization page
- Receives an authorization code via localhost callback
- Exchanges the code for access/refresh tokens
- Stores tokens in the frontend's OAuth storage
OAuth client IDs and secrets are compiled into the binary from environment variables at build time. Community builds may use different client IDs.
Update Verification
The Windows updater verifies downloaded files using BLAKE2b hashes before applying updates. The update manifest is fetched over HTTPS from obsproject.com.
Browser Source Isolation
Browser sources run in CEF (Chromium Embedded Framework) processes. Hardware acceleration for browser sources is controlled by the BrowserHWAccel setting. Browser sources have access to:
- Network (to load web content)
- GPU (for rendering)
- Local storage (within the browser source's profile)
Browser sources do NOT have access to the local filesystem beyond their configured URLs.
Virtual Camera GUID (Windows)
The Windows virtual camera registers a DirectShow filter with GUID A3FCE0F5-3493-419F-958A-ABA1250EC20B. This is compiled into the binary and shared across all OBS installations of the same build.
8. Developer Internals
Repository Structure
obs-studio/
├── CMakePresets.json # Build presets for all platforms
├── .cirrus.yml # FreeBSD CI configuration
├── libobs/ # Core library
│ ├── obs.h / obs.c # Main API entry points
│ ├── obs-source.h / .c # Source management
│ ├── obs-scene.h / .c # Scene graph
│ ├── obs-encoder.h / .c # Encoder abstraction
│ ├── obs-output.h / .c # Output abstraction
│ ├── obs-service.h / .c # Service abstraction
│ ├── obs-audio.c # Audio pipeline
│ ├── obs-video.c # Video rendering pipeline
│ ├── obs-audio-controls.c # Fader and volume meter API
│ ├── obs-hotkey.h / .c # Global hotkey system
│ ├── obs-properties.h / .c # Dynamic property system
│ ├── callback/ # Signal/callback infrastructure
│ ├── graphics/ # Graphics abstraction layer (gs_*)
│ ├── media-io/ # Audio/video I/O abstractions
│ └── util/ # Utilities (threading, memory, strings, config, platform)
├── libobs-d3d11/ # Direct3D 11 graphics implementation
├── libobs-opengl/ # OpenGL graphics implementation
├── libobs-metal/ # Metal graphics implementation
├── libobs-winrt/ # Windows Runtime helpers
├── frontend/ # Qt6 GUI application
│ ├── OBSApp.cpp / .hpp # Application entry, global config, crash handling
│ ├── widgets/ # Main window (OBSBasic), projectors, audio mixer
│ ├── settings/ # Settings dialog implementation
│ ├── dialogs/ # Modal dialogs (filters, properties, logs)
│ ├── wizards/ # Auto-configuration wizard
│ ├── docks/ # Dockable panels (stats, YouTube)
│ ├── components/ # Reusable UI components (sliders, labels, checkboxes)
│ ├── oauth/ # OAuth integration (Twitch, YouTube, Restream)
│ ├── updater/ # Windows auto-updater (BLAKE2b verification)
│ ├── importer/ # Profile importer (XSplit, OBS Classic)
│ ├── plugin-manager/ # Third-party plugin management
│ ├── api/ # Frontend API for plugins
│ ├── forms/ # Qt UI form files (.ui)
│ ├── data/ # Themes, locale files, licenses
│ └── utility/ # Helpers (crash handler, FFmpeg codecs, audio encoders)
├── plugins/ # Plugin modules
│ ├── obs-filters/ # Audio/video filters (chroma key, color correction, noise, delay)
│ ├── obs-transitions/ # Scene transitions (cut, fade, swipe, slide, stinger, luma wipe)
│ ├── obs-outputs/ # RTMP/FLV output, recording output
│ ├── obs-webrtc/ # WebRTC WHIP output
│ ├── obs-ffmpeg/ # FFmpeg-based encoders, sources, muxer
│ ├── obs-x264/ # x264 H.264 software encoder
│ ├── obs-nvenc/ # NVIDIA NVENC hardware encoder
│ ├── obs-qsv11/ # Intel QSV hardware encoder
│ ├── obs-browser/ # CEF browser source (submodule)
│ ├── obs-websocket/ # WebSocket remote control API (submodule)
│ ├── obs-vst/ # VST audio plugin hosting
│ ├── obs-libfdk/ # FDK AAC encoder
│ ├── rtmp-services/ # Streaming service database
│ ├── image-source/ # Image and color sources
│ ├── vlc-video/ # VLC media source
│ ├── text-freetype2/ # FreeType 2 text rendering
│ ├── nv-filters/ # NVIDIA AI filters (noise removal, background removal)
│ ├── win-capture/ # Windows display/window/game capture
│ ├── win-dshow/ # DirectShow video capture (webcams)
│ ├── win-wasapi/ # Windows Audio Session API capture
│ ├── mac-capture/ # macOS screen/window capture
│ ├── mac-avcapture/ # macOS AVFoundation camera capture
│ ├── mac-videotoolbox/ # macOS VideoToolbox hardware encoder
│ ├── mac-virtualcam/ # macOS virtual camera (System Extension + DAL plugin)
│ ├── mac-syphon/ # macOS Syphon inter-app video sharing
│ ├── coreaudio-encoder/ # macOS CoreAudio AAC encoder
│ ├── linux-capture/ # Linux X11/Wayland screen capture
│ ├── linux-pipewire/ # PipeWire video/audio capture
│ ├── linux-pulseaudio/ # PulseAudio audio capture
│ ├── linux-v4l2/ # Video4Linux2 camera capture
│ ├── linux-alsa/ # ALSA audio capture
│ ├── linux-jack/ # JACK audio capture
│ ├── oss-audio/ # OSS audio capture (FreeBSD)
│ ├── sndio/ # sndio audio capture (OpenBSD/FreeBSD)
│ ├── decklink/ # Blackmagic Decklink capture card
│ └── aja/ # AJA capture card
├── shared/ # Shared components
│ ├── obs-scripting/ # Lua/Python scripting engine (SWIG bindings)
│ ├── media-playback/ # Media file playback engine
│ ├── properties-view/ # Qt properties view widget
│ ├── ipc-util/ # Inter-process communication utilities
│ ├── obs-hook-config/ # Game capture hook configuration
│ ├── obs-inject-library/ # DLL injection utilities (Windows)
│ ├── obs-shared-memory-queue/ # Shared memory queue for virtual camera
│ ├── obs-tiny-nv12-scale/ # NV12 frame scaler
│ ├── bpm/ # Beat-per-minute detection
│ ├── happy-eyeballs/ # Happy Eyeballs (RFC 8305) connection algorithm
│ ├── file-updater/ # File download and update utilities
│ ├── opts-parser/ # Command-line options parser
│ └── qt/ # Shared Qt widgets (Idian UI framework, sliders, wrappers)
├── cmake/ # CMake modules and finders
├── test/ # Test suites
├── docs/ # Sphinx API documentation
├── build-aux/ # Build helpers (Steam integration, formatting)
└── additional_install_files/ # Platform-specific redistributable files
Plugin Architecture
OBS plugins use a C module interface defined in obs-module.h. Every plugin must implement:
OBS_DECLARE_MODULE() // Module declaration macro
OBS_MODULE_USE_DEFAULT_LOCALE("name", "en-US") // Locale setup
bool obs_module_load(void) {
// Register sources, outputs, encoders, services
obs_register_source(&my_source_info);
return true;
}
const char *obs_module_description(void) {
return "Plugin description";
}
Plugin types are registered via obs_source_info structs with function pointers for lifecycle (create, destroy, update), rendering (video_render, filter_video, filter_audio), and properties:
struct obs_source_info my_source = {
.id = "my_source",
.type = OBS_SOURCE_TYPE_INPUT, // INPUT, FILTER, or TRANSITION
.output_flags = OBS_SOURCE_VIDEO,
.get_name = my_get_name,
.create = my_create,
.destroy = my_destroy,
.update = my_update,
.video_render = my_render,
.get_properties = my_properties,
};
Note
Plugins that are submodules (e.g.,
obs-browser,obs-websocket) are not included in the main source tree. They are cloned separately duringgit clone --recursiveand built as part of the CMake configuration.
Core Library (libobs) Deep Dive
Scene Graph: OBS uses a tree-based scene graph where scenes contain scene items (source references with transforms). Sources can be shared across scenes via reference counting.
Signal System (libobs/callback/): A publish/subscribe signal system used throughout OBS for event notification. Sources emit signals like source_create, source_remove, source_rename, source_activate, source_audio_activate, etc. The frontend subscribes to these signals to update the UI.
Properties System (obs-properties.h): A dynamic property description system that plugins use to declare their configurable parameters. The frontend renders these as Qt widgets automatically. Property types include:
OBS_PROPERTY_BOOL,OBS_PROPERTY_INT,OBS_PROPERTY_FLOATOBS_PROPERTY_TEXT,OBS_PROPERTY_PATH,OBS_PROPERTY_LISTOBS_PROPERTY_COLOR,OBS_PROPERTY_FONTOBS_PROPERTY_BUTTON,OBS_PROPERTY_GROUP
Memory Management: OBS uses its own memory allocator (bmem.h) with bmalloc(), bfree(), bstrdup(), etc. All OBS API objects use reference counting for ownership management.
Threading: util/threading.h wraps pthreads on all platforms (including Windows via w32-pthreads). Mutexes, condition variables, and atomic operations are used throughout for thread safety.
Configuration: util/config-file.h provides INI-format configuration with typed getters/setters (config_get_int, config_set_string, config_set_default_bool).
Graphics Abstraction Layer
The graphics layer (libobs/graphics/) provides a platform-independent API (gs_* functions) for:
- Texture creation and manipulation
- Shader effects (HLSL on D3D11, GLSL on OpenGL, MSL on Metal)
- Vertex buffers, stencil buffers, blend states
- Render targets and swap chains
Three backends implement this API:
- libobs-d3d11: Full Direct3D 11 implementation with compute shader support
- libobs-opengl: OpenGL 3.3+ implementation with platform-specific context management (WGL, GLX, EGL, CGL)
- libobs-metal: Apple Metal implementation (35 files, 346K chars — the newest and largest backend, targeting Apple Silicon)
Audio Pipeline Internals
The audio pipeline in libobs/ processes audio at the source level with per-source filters, then mixes all sources to the master output. Key features:
- Fader curves: Three fader types — Cubic, IEC (broadcast standard), Logarithmic — implemented in
obs-audio-controls.c - Volume metering: Both Sample Peak and True Peak (ITU-R BS.1770-4) metering with SSE-optimized processing
- Audio filters: Applied in the filter chain attached to each source, processed in order (top-to-bottom in the UI)
- Multi-track output: Up to 6 audio tracks, with per-source track assignment via bitfield
Filter Plugin Reference
The obs-filters plugin provides built-in audio/video filters:
| Filter | Type | ID | Key Settings |
|---|---|---|---|
| Async Delay | Video | async_delay_filter |
delay_ms (0–20000 ms) |
| Chroma Key | Video | chroma_key_filter |
key_color_type, similarity, smoothness, spill, opacity, contrast, brightness, gamma |
| Color Correction | Video | color_filter |
color, contrast, brightness, gamma, opacity |
| Color Key | Video | color_key_filter |
Key color, similarity, smoothness |
| Crop/Pad | Video | crop_filter |
Left, right, top, bottom crop values |
| Image Mask/Blend | Video | mask_filter |
Mask image path, blend type |
| LUT | Video | clut_filter |
LUT file path, amount |
| Render Delay | Video | gpu_delay |
Delay in frames |
| Scaling/Aspect Ratio | Video | scale_filter |
Resolution, sampling method |
| Scroll | Video | scroll_filter |
Horizontal/vertical speed |
| Sharpen | Video | sharpness_filter |
Sharpness amount |
| Compressor | Audio | compressor_filter |
Ratio, threshold, attack, release, output gain |
| Expander/Gate | Audio | expander_filter |
Ratio, threshold, attack, release |
| Gain | Audio | gain_filter |
Gain in dB |
| Limiter | Audio | limiter_filter |
Threshold, release |
| Noise Gate | Audio | noise_gate_filter |
Close/open threshold, attack, hold, release |
| Noise Suppression | Audio | noise_suppress_filter |
Method (RNNoise or Speex), suppression level |
Transition Plugin Reference
The obs-transitions plugin registers these transitions:
| Transition | ID | Description |
|---|---|---|
| Cut | cut_transition |
Instant switch, zero-duration |
| Fade | fade_transition |
Opacity crossfade |
| Swipe | swipe_transition |
Directional wipe |
| Slide | slide_transition |
Sliding movement |
| Stinger | stinger_transition |
Custom video overlay animation |
| Fade to Color | fade_to_color_transition |
Fades through a solid color |
| Luma Wipe | luma_wipe_transition |
Grayscale image-based wipe pattern |
Output and Streaming Internals
The obs-outputs plugin implements:
- RTMP output: FLV muxing with enhanced RTMP support (Y2023 spec) for AV1 and HEVC codecs, including multitrack video
- FLV muxing: Full FLV container implementation with extended header support for non-H.264 codecs
- File recording: Direct file output with multiple container format support
The obs-webrtc plugin implements:
- WHIP output: WebRTC-HTTP Ingestion Protocol for ultra-low-latency streaming
- DTLS/SRTP: Encrypted media transport
- ICE: Interactive Connectivity Establishment for NAT traversal
- Video fragment size: Configurable up to 1470 bytes (default: 1200 for broad network compatibility)
RTMP Services Database
The rtmp-services plugin loads streaming service definitions from services.json, which contains:
- Service name and display information
- Server lists with URLs and region names
- Recommended settings (resolution, FPS, codecs)
- Protocol information (RTMP, RTMPS)
- Supported video and audio codecs
- Whether the service supports additional audio tracks
Service-specific modules handle platform quirks: twitch.h (ingest refresh), nimotv.h, showroom.h, dacast.h, amazon-ivs.h (auto-ingest discovery).
The services database version is tracked independently (version: 285 at current commit) and can be updated without an OBS release via the auto-update mechanism.
Scripting Engine
The shared/obs-scripting/ module provides:
- Lua scripting: Via LuaJIT with direct C FFI bindings
- Python scripting: Via SWIG-generated Python bindings
- Script callbacks: Scripts can register for OBS signals, create sources, add frontend callbacks
- Script hot-reload: Scripts can be added/removed at runtime via Tools → Scripts
The scripting engine uses a constant string cache (cstrcache.cpp) to avoid string allocation overhead for frequently-used strings in the scripting bridge.
Tip
When developing scripts, use Lua for performance-sensitive tasks (LuaJIT is significantly faster than CPython) and Python when you need access to the broader Python ecosystem (numpy, requests, etc.).
Code Patterns and Conventions
Naming conventions:
- C API functions:
obs_prefix (e.g.,obs_source_create,obs_output_start) - Graphics functions:
gs_prefix (e.g.,gs_texture_create,gs_effect_get_param_by_name) - Internal functions:
staticwith descriptive snake_case names - C++ classes: PascalCase (e.g.,
OBSBasic,AudioMixer,VolumeControl) - Qt signals/slots: camelCase
- Macros: UPPER_SNAKE_CASE
Error handling:
blog()for logging at LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG levels- Functions return
boolorNULLon failure - Encoder initialization failures use
obs_encoder_set_last_error()for user-visible error messages
Memory patterns:
bmalloc()/bfree()for heap allocations (tracked allocator)bzalloc()for zero-initialized allocationsbstrdup()for string duplication- RAII wrappers in C++ (
OBSDataAutoRelease,OBSSourceAutoRelease)
Build pattern:
- Each plugin is a CMake
add_library(MODULE)target - Plugins use
OBS_DECLARE_MODULE()andobs_module_load()entry points - Platform-specific source files use CMake generator expressions:
$<$<PLATFORM_ID:Windows>:win-file.cpp> - Qt MOC files are included directly:
#include "moc_ClassName.cpp"
Testing
OBS uses the cmocka testing framework. Test infrastructure is in test/:
test/cmocka/— cmocka library and header filestest/test-input/— test input plugin for synthetic video/audio generationtest/win/— Windows-specific test utilities- Platform-specific test executables:
obs-amf-test,obs-nvenc-test,obs-qsv-test— runtime capability detection for hardware encoders
The test input plugin generates synthetic video and audio data for testing the rendering and encoding pipeline without requiring actual capture devices.
Warning
The hardware encoder test executables (
obs-amf-test,obs-nvenc-test,obs-qsv-test) are spawned as separate processes during startup to detect encoder capabilities. If they crash (due to driver issues), the main OBS process is not affected. These tests run with a timeout to prevent hanging.
Building and Development Workflow
Quick start for contributors:
# Clone with submodules
git clone --recursive https://github.com/obsproject/obs-studio.git
cd obs-studio
# Configure (pick your platform preset)
cmake --preset windows-x64 # Windows
cmake --preset ubuntu # Linux
cmake --preset macos # macOS
# Build
cmake --build build_x64 --config RelWithDebInfo # Windows
cmake --build build_ubuntu # Linux
# Run
./build_x64/RelWithDebInfo/bin/64bit/obs64.exe # Windows
./build_ubuntu/bin/64bit/obs # Linux
Code formatting:
The project uses clang-format for C/C++ formatting. A Python formatting manifest tool is provided at build-aux/format-manifest.py:
python build-aux/format-manifest.py manifest_file --check # Check for needed changes
python build-aux/format-manifest.py manifest_file # Apply formatting
Note
The
format-manifest.pytool accepts--loglevel(default:WARNING) for controlling log verbosity during format checks.
Potential Improvements
Based on source analysis:
-
Metal renderer parity: The Metal backend (
libobs-metal/) is the newest graphics backend (35 files, 346K chars) and is under active development. TheRendererdefault for Apple Silicon is currentlyOpenGLwith a TODO comment indicating Metal will become the default once it reaches production quality. -
Enhanced RTMP multitrack: The FLV muxer supports the Y2023 enhanced RTMP specification including multitrack video (
MULTITRACKTYPE_MANY_TRACKS), but adoption depends on ingest server support. -
ARM64 Windows: ARM64 Windows builds exist but disable AJA support, scripting, and VST plugins. These features could be enabled as ARM64 toolchains and dependencies mature.
-
Sphinx documentation: The embedded Sphinx docs at
docs/sphinx/reference version 27.2.0 (copyright 2017-2022), indicating they have not been updated alongside the main source. The C API documentation would benefit from synchronization with the current API surface. -
v4l2loopback virtual camera: Linux virtual camera requires the separate
v4l2loopbackkernel module. Stopping and restarting the virtual camera can leave the module in an inconsistent state (issue #12506), requiring a manual module reload.
9. Integration Points
obs-websocket
The bundled obs-websocket plugin provides a WebSocket server for external control of OBS Studio. Third-party applications (Stream Deck, Touch Portal, custom scripts) connect via WebSocket to:
- Switch scenes
- Start/stop streaming and recording
- Control sources (visibility, transforms, filters)
- Read system status (CPU, memory, streaming stats)
- Trigger transitions and hotkeys
The WebSocket API uses JSON-RPC-style messages over WebSocket connections.
Warning
When controlling audio sources via WebSocket's
RemoveInputcommand, audio sources may not be fully destroyed on OBS 32.0.3+. This is tracked as issue #12919. The Audio Mixer UI may also desync from the actual state when controlled via WebSocket (issue #13246).
Frontend API
The Frontend API (frontend/api/) exposes a C interface for frontend plugins to interact with the main OBS window:
obs_frontend_get_current_scene()— get the current sceneobs_frontend_set_current_scene()— switch scenesobs_frontend_streaming_active()— check streaming stateobs_frontend_add_event_callback()— subscribe to frontend events
Frontend plugins are loaded as shared libraries and linked against OBS::frontend-api.
Streaming Service Integration
OAuth-enabled services (Twitch, YouTube, Restream) integrate via:
- OAuth flow: Browser-based authorization with localhost callback
- Service-specific UI: Dedicated docks (e.g., YouTubeAppDock) for platform features
- Ingest refresh: Services like Twitch and Amazon IVS periodically refresh their server lists via proc handler calls
Profile Import/Export
The importer system (frontend/importer/, frontend/importers/) supports importing profiles from:
- XSplit Broadcaster
- OBS Classic (pre-Studio versions)
- Streamlabs OBS
Import translates external configuration formats to OBS Studio's profile structure.
Plugin Manager
The plugin manager (frontend/plugin-manager/) provides:
- Discovery and installation of third-party plugins
- Plugin enable/disable management
- Plugin settings storage in
plugin_manager/under the configuration directory
Happy Eyeballs Connection Algorithm
The shared/happy-eyeballs/ module implements RFC 8305 (Happy Eyeballs v2) for optimal TCP connection establishment. This is used by the RTMP output to select the fastest connection path when a service has both IPv4 and IPv6 endpoints, reducing connection latency.
BPM Detection
The shared/bpm/ module provides beat-per-minute detection for audio sources, enabling beat-synchronized visual effects and transitions.