ZOOM RAW DATA AND BANDWIDTH LIMITS - READ BEFORE USE
CoreVideo uses the Zoom Meeting SDK raw data APIs. Raw data access is available through Meeting SDK apps; negotiated quality follows the signed-in Zoom account and app entitlements. Standard accounts are typically constrained by a 30 Mbps incoming video budget, while Enhanced Media / HBM can raise that envelope to roughly 100 Mbps. At about 4-6 Mbps per standard 1080p stream, several feeds can work without EM; with EM/HBM, plan around up to 16 standard 1080p feeds or about 8 high-bitrate/60 fps feeds before hitting the downlink budget.
Contact your Zoom account representative or visit Zoom Plans to verify production quality, bandwidth, and developer/app entitlements before deploying this plugin.
OBS Studio plugin for live Zoom meeting video, audio, screen share, and Zoom interpretation audio channel capture.
CoreVideo integrates the Zoom Meeting SDK into OBS - no screen capture or virtual camera required. The SDK runs in a dedicated ZoomObsEngine child process; the OBS plugin communicates with it through a ZoomEngineClient singleton over cross-platform IPC (named pipes on Windows, Unix sockets on macOS/Linux) with frame data delivered through named shared memory. A built-in dockable control panel manages joining, and a ZoomReconnectManager handles automatic recovery after crashes or disconnects.
Docs: Full Documentation & Architecture Diagrams -> Guide: Core Plugin Guide & Examples ->
- Raw video capture - I420 YUV, selectable 360p / 720p / 1080p resolution
- Hardware-accelerated video - optional FFmpeg I420->NV12 conversion via CUDA, VAAPI, VideoToolbox, or QSV (
-DCOREVIDEO_HW_ACCEL=ON) - Video loss mode - hold last frame or show black when a feed drops; shows color-bar placeholder before first frame
- Raw audio capture - 48 kHz PCM, mono or stereo, with per-participant audio isolation and mixer routing
- Auto ISO recording - record assigned participant/active-speaker/spotlight outputs to separate FFmpeg-encoded MP4 files with matching PCM WAV audio, plus optional main OBS program recording
- Assignment modes - each source independently follows: a fixed participant, the active speaker, a ZoomISO-style spotlight slot (1...N), or the active screen share
- Failover participant - configure a secondary participant that activates automatically when the primary leaves
- Active Speaker Director - configurable sensitivity + hold-time switching, manual take/release supersede, and a dedicated
CoreVideo Active SpeakerOBS source for clean speaker-follow output - Spotlight / ZoomISO - subscribe a source to spotlight slot N; engine resolves which participant is spotlighted
- Screen share capture - source subscribes to the active meeting screen-share feed
- Zoom interpretation audio channel capture - dedicated OBS source for existing Zoom interpretation audio channels
- Per-participant audio sources - standalone OBS audio source per meeting participant
- Webinar support - join Zoom Webinars using the dedicated SDK entry point (Webinar checkbox in control dock)
- Participant roster - live list with video, mute, talking, host, co-host, raised hand, spotlight slot, and screen-sharing state
- Control dock - dockable Qt panel with animated status dot, join/leave, token-type selector, recovery countdown, Active Speaker Director controls, and a routing section that opens the dedicated Output Manager; persists last meeting ID and display name across sessions
- Diagnostics dock - dockable OBS panel showing requested vs observed resolution, FPS, frame age, retry counts, and recent engine debug events for live troubleshooting
- Auto-reconnect - exponential back-off recovery after engine crash, network drop, or unexpected disconnect
- OBS hotkeys - per-source hotkeys to enable/disable active speaker mode
- TCP control API - JSON server on
127.0.0.1:19870for scripts and dashboards; includesoauth_callbackcommand for custom URL scheme forwarding - OSC control API - UDP OSC server on
127.0.0.1:19871for lighting consoles and broadcast hardware - Output profiles - save and load named participant-to-source mappings as JSON files
- Output manager dock - dockable OBS panel and API for viewing and reconfiguring all sources at runtime
- Broker-backed Meeting SDK authentication - published builds request a short-lived Meeting SDK JWT from the CoreVideo OAuth broker after Zoom sign-in; SDK secrets stay server-side
- Zoom OAuth PKCE - user-level OAuth 2.0 with PKCE (public client, no desktop secret) for attributed joins and Marketplace compliance; the broker start URL is baked in at build time;
corevideo://custom URL scheme with platform callback helpers (CoreVideoOAuthCallback.exe/.app); DPAPI token protection on Windows - Visible Zoom Meeting SDK window - the helper process uses Zoom's default Meeting SDK UI so operators can admit waiting-room participants, start self video/audio, and use normal in-meeting controls while OBS receives raw feeds
- SDK 5.17.x and 7.x - auto-detects flat and subfolder header layouts
- Hardened security - constant-time token comparison, validated IPC input, sanitised participant IDs, SIGPIPE handling
- Modern UI - CoreVideo stylesheet with dark theme, animated
CvStatusDot,CvBannerfirst-run notices, and button role variants (primary / danger) - Multi-platform - Windows (x64/arm64), macOS (universal arm64 + x86_64), Linux
| Dependency | Version | Notes |
|---|---|---|
| OBS Studio | 30+ | libobs + obs-frontend-api |
| CMake | 3.16+ | Build system |
| Qt | 6.x | Core + Network + Widgets |
| FFmpeg | Runtime executable | Required for auto ISO recording. Must be on PATH or supplied via ffmpeg_path. |
| Zoom Meeting SDK | 5.17.x / 7.x | Place in third_party/zoom-sdk/. Windows builds support the older flat header layout and the newer 7.x subfolder header layout. |
| C++ compiler | C++17 | MSVC 2022 / Clang 14+ / GCC 11+ |
| Zoom Developer Account | - | Marketplace app with Public Client OAuth + PKCE, Meeting SDK / Embed enabled, and server-side broker secrets for Meeting SDK JWT minting. |
-
Get the Zoom SDK - download from the Zoom Developer Portal and place it at
third_party/zoom-sdk/. CMake auto-detects x64/arm64/x86 sub-layouts on Windows. -
Configure & build
cmake -B build \ -DCMAKE_BUILD_TYPE=Release \ -DZOOM_SDK_DIR=third_party/zoom-sdk \ -DCMAKE_PREFIX_PATH="/path/to/obs-studio;/path/to/Qt6" cmake --build build --config ReleaseOn Windows, run CMake from a Visual Studio Developer PowerShell or use an explicit Visual Studio generator:
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 ` -DZOOM_SDK_DIR=third_party/zoom-sdk ` -DCMAKE_PREFIX_PATH="C:/path/to/obs-studio-build;C:/path/to/Qt/6.x/msvc2022_64" cmake --build build --config Release
To validate the Zoom SDK helper process before wiring up OBS and Qt, build only the engine:
cmake -S . -B build-engine -G "Visual Studio 17 2022" -A x64 ` -DCOREVIDEO_BUILD_PLUGIN=OFF ` -DZOOM_SDK_DIR=third_party/zoom-sdk cmake --build build-engine --config Release --target ZoomObsEngine
If MSBuild reports
Item has already been added. Key in dictionary: 'Path' Key being added: 'PATH', normalize the process environment before running CMake from PowerShell:Remove-Item Env:PATH -ErrorAction SilentlyContinue $env:Path = "C:\Program Files\CMake\bin;C:\Windows\System32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0"
A normal OBS installation under
C:\Program Files\obs-studiocontains the runtime binaries, not the development CMake packages. For the full plugin build,CMAKE_PREFIX_PATHmust include an OBS build/install tree that containsLibObsConfig.cmakeandobs-frontend-apiConfig.cmake, plus a matching Qt 6 MSVC package.Windows builds must ship Qt's TLS backend plugins (
obs-plugins/64bit/plugins/tls/) for OAuth HTTPS requests to succeed. -
Install into OBS
cmake --install build --prefix "/path/to/obs-studio" -
Configure local settings - published builds already contain the CoreVideo broker URL and do not require end users to enter Zoom app credentials. Open OBS -> Tools -> Zoom Plugin Settings to sign in with Zoom, configure the local control-server token/ports, and manage reconnect behavior. Developer-only builds can still use local credential overrides when the embedded broker identity is blank.
GitHub Actions can validate the Windows build without the restricted Zoom
runtime, but public client releases must include zoom-runtime\sdk.dll and the
other Zoom SDK runtime DLLs. If ZOOM_SDK_WINDOWS_URL is not configured as a
GitHub repository secret, CI skips publishing a GitHub Release instead of
shipping an incomplete package.
For fast local releases from a machine that already has the Zoom runtime, use:
.\scripts\release-local.ps1 -Version v0.1.6 -UploadWhen NSIS is installed, the release script also creates and uploads
CoreVideo-Setup-vX.Y.Z.exe. This is the recommended end-user installer: it
detects a standard OBS Studio install path, requires OBS to be closed, installs
the plugin/runtime files, and registers an uninstaller in Windows Apps &
Features. The ZIP remains available for manual or advanced installs. Pass
-SkipInstaller if you only want the ZIP package.
If an FFmpeg shared development tree exists at C:\ffmpeg, local releases
automatically enable hardware I420->NV12 conversion and bundle the FFmpeg DLLs
beside the OBS plugin. Pass -DisableFfmpegHwAccel to force a CPU-only build.
Useful options:
.\scripts\release-local.ps1 -Version v0.1.6 -Install -ObsInstallPath "C:\Program Files\obs-studio"
.\scripts\release-local.ps1 -Version v0.1.6 -BuildPath build-nmake -UploadThe script builds, installs into a staging folder, verifies
obs-zoom-plugin.dll, ZoomObsEngine.exe, and zoom-runtime\sdk.dll, creates a
ZIP under dist/, optionally creates the NSIS setup EXE, and optionally uploads
both assets to the matching GitHub Release.
Use the OBS smoke test when validating Sidecar/OBS scene graph behavior on a machine with OBS running and obs-websocket enabled. The script connects directly to obs-websocket v5, creates a deterministic CoreVideo test scene, links participant sources through nested slot scenes, switches OBS to the test scene, and audits that the expected scenes, inputs, and scene items are present.
.\scripts\obs-scene-smoke-test.ps1If obs-websocket has a password, pass it explicitly or use the environment:
$env:OBS_WEBSOCKET_PASSWORD = "your-websocket-password"
.\scripts\obs-scene-smoke-test.ps1 -ParticipantCount 8To verify an already-created scene graph without creating or modifying sources:
.\scripts\obs-scene-smoke-test.ps1 -AuditOnly -SceneName "CoreVideo Smoke Test"-
Set up OAuth (for Marketplace / external-account joins) - publishers configure the Cloudflare broker and bake
-DZOOM_EMBED_OAUTH_AUTHORIZATION_URL=https://corevideo.iamfatness.us/oauth/startinto the build. End users just open the Settings dialog and click Sign in with Zoom. Seedocs/ZOOM_MARKETPLACE_OAUTH.mdfor the full walkthrough. -
Join once, then assign outputs - use the CoreVideo dock or the TCP/OSC control APIs to join the meeting once per OBS session. Then add Zoom Participant, Zoom Participant Audio, Zoom Share, or Zoom Interpretation Audio sources and assign them to participants or dynamic roles.
CoreVideo uses user-level OAuth 2.0 with PKCE through the CoreVideo HTTPS broker for attributed meeting joins and Zoom App Marketplace compliance. Published builds do not ship OAuth or Meeting SDK secrets in the OBS plugin. The broker performs the Zoom token exchange with Public Client OAuth, validates the signed-in user token, and mints a short-lived Meeting SDK JWT server-side for the helper process.
Pass the broker identity at CMake configure time:
cmake -B build \
-DZOOM_EMBED_OAUTH_AUTHORIZATION_URL=https://corevideo.iamfatness.us/oauth/start \
-DZOOM_EMBED_MEETING_SDK_PUBLIC_APP_KEY=<optional_legacy_public_app_key> ...
These values are compiled into the plugin and used for every install of that build. There is no UI for entering production credentials, and embedded values override stale global.ini entries. The public app key is kept only as a legacy/fallback path; current production builds prefer the broker-minted Meeting SDK JWT.
- In Tools -> Zoom Plugin Settings, click Authorize with Zoom (no IDs to enter). The plugin registers the
corevideo://URL scheme automatically on first use. - The browser opens at
https://corevideo.iamfatness.us/oauth/start; the broker generates the PKCE verifier/challenge and redirects to Zoom. - Zoom redirects to
https://corevideo.iamfatness.us/oauth/callback; the broker returns a short-lived broker token tocorevideo://oauth/callback. CoreVideoOAuthCallback.exe(Windows) orCoreVideoOAuthCallback.app(macOS) forwards the URL to the plugin via the TCP control server (oauth_callbackcommand).- The plugin verifies state, redeems the broker token over HTTPS, and persists access + refresh tokens. On Windows, tokens are DPAPI-protected before storage.
- Before each meeting join, CoreVideo refreshes the token if needed and asks the broker for a short-lived Meeting SDK JWT. The broker validates the OAuth access token against Zoom before minting the SDK JWT. The Zoom helper process initializes the SDK with that JWT, then joins without passing a ZAK.
See docs/ZOOM_MARKETPLACE_OAUTH.md for the full setup guide and security notes.
# Meeting status
echo '{"cmd":"status"}' | nc 127.0.0.1 19870
# List participants with video/mute/talking state
echo '{"cmd":"list_participants"}' | nc 127.0.0.1 19870
# Reassign source to participant at runtime
echo '{"cmd":"assign_output","source":"Zoom Participant 1","participant_id":123,"isolate_audio":true,"audio_channels":"stereo"}' | nc 127.0.0.1 19870
# Forward OAuth callback URL from custom scheme helper
echo '{"cmd":"oauth_callback","url":"corevideo://oauth/callback?broker_token=...&state=..."}' | nc 127.0.0.1 19870Commands: help, status, list_participants, list_outputs, assign_output, assign_output_ex, recover_stale_outputs, upgrade_low_quality_outputs, join, leave, oauth_callback, iso_recording_start, iso_recording_stop, iso_recording_status, speaker_director_status, speaker_director_configure, speaker_director_take, speaker_director_release.
Use OBS -> Tools -> Zoom ISO Recorder for the operator UI. The dock provides an output-folder picker, FFmpeg path/test controls, a program-recording toggle, Start/Stop buttons, and a live table of active ISO sessions and file paths.
# Start ISO recording. record_program=true also starts OBS program recording.
echo '{"cmd":"iso_recording_start","output_dir":"C:/Recordings/CoreVideo","ffmpeg_path":"ffmpeg","record_program":true}' | nc 127.0.0.1 19870
# Inspect active ISO sessions and output file paths.
echo '{"cmd":"iso_recording_status"}' | nc 127.0.0.1 19870
# Stop ISO recording.
echo '{"cmd":"iso_recording_stop"}' | nc 127.0.0.1 19870Each active source segment writes one *.mp4 video file and one matching *.wav PCM audio file. A new segment starts when the resolved participant or source resolution changes.
| Address | Type tags | Action |
|---|---|---|
/zoom/status |
- | Reply: meeting state + active speaker |
/zoom/list_participants |
- | Reply: one /zoom/participant per user |
/zoom/list_outputs |
- | Reply: one /zoom/output per source |
/zoom/recover_stale_outputs |
[,i] |
Retry stale video outputs; optional 1 forces cooldown bypass |
/zoom/upgrade_low_quality_outputs |
[,i] |
Retry outputs below requested resolution; skips feeds already at 1080p |
/zoom/join |
,sss |
meeting_id, passcode, display_name |
/zoom/leave |
- | Leave meeting |
/zoom/assign_output |
,si[i] |
source, participant_id, [active_speaker] |
/zoom/assign_output/active_speaker |
,s |
source |
/zoom/isolate_audio |
,si |
source, 0|1 |
/zoom/iso/start |
[,s] |
optional output directory |
/zoom/iso/stop |
- | Stop ISO recording |
CoreVideo has two active-speaker workflows:
- Set a normal Zoom Participant source to Active Speaker assignment mode when that source should follow the directed speaker.
- Add the dedicated CoreVideo Active Speaker source when you want a single speaker-follow OBS source. It uses a two-slot handoff internally: the current participant stays visible while the next participant warms on a hidden slot, then the source cuts only after a valid frame is available.
The Active Speaker Director in the Zoom Control dock decides which participant is directed. It tracks the raw Zoom speaker, candidate speaker, directed speaker, last directed speaker, and any manual supersede.
Two independent timers prevent rapid camera cuts:
| Parameter | Default | Description |
|---|---|---|
Sensitivity (speaker_sensitivity_ms) |
500 ms | New speaker must hold the floor continuously for this long before the switch fires. A different speaker speaking resets the clock. |
Hold (speaker_hold_ms) |
2 000 ms | After any switch, no further switch occurs for at least this long. |
The effective delay before each switch is max(hold_remaining, sensitivity_remaining). If the delay is zero the switch fires immediately; otherwise a background thread sleeps for the delay and re-evaluates on the OBS UI thread.
- Liveness flag - a
shared_ptr<atomic<bool>>captured in every in-flight lambda ensures deferred callbacks bail safely if the source is destroyed before the timer fires. - Supersede logic - a new candidate replaces the pending one, restarting the sensitivity clock. Stale callbacks silently discard themselves.
- Final verification - before committing a switch the code re-checks that the candidate is still the active speaker, so no switch fires for someone who stopped talking during the hold window.
- UI-thread commitment - all state mutations run on the OBS UI thread via
obs_queue_task, preventing data races with the properties panel.
When Isolate Audio is also enabled, every speaker switch sends an updated subscribe command to the engine with the new participant ID and isolate_audio=true, so the audio track always follows the same participant as the video.
# Inspect directed/raw/candidate/last/manual speaker state.
echo '{"cmd":"speaker_director_status"}' | nc 127.0.0.1 19870
# Update director timing.
echo '{"cmd":"speaker_director_configure","sensitivity_ms":650,"hold_ms":2500}' | nc 127.0.0.1 19870
# Manually take a participant until released.
echo '{"cmd":"speaker_director_take","participant_id":123456}' | nc 127.0.0.1 19870
# Return to automatic speaker direction.
echo '{"cmd":"speaker_director_release"}' | nc 127.0.0.1 19870Named profiles save the full source-to-participant mapping to JSON files under:
obs-studio/plugin_config/obs-zoom-plugin/profiles/<name>.json
Use the Zoom Output Manager dock, or OBS -> Tools -> Zoom Output Manager to focus it, to save, load, and delete profiles interactively. Code can call ZoomOutputProfile::save() / load() / list() / remove() directly.
OBS Studio
`-- obs-zoom-plugin (no Zoom SDK dependency)
|-- ZoomDock - dockable Qt panel: animated CvStatusDot, join/leave,
| token-type selector, recovery countdown,
| Active Speaker Director controls, routing actions;
| CvBanner first-run credentials notice; persists last
| meeting ID + display name
|-- ZoomOAuthManager - broker-backed OAuth 2.0 PKCE: begin_authorization,
| handle_redirect_url, register_url_scheme,
| refresh_access_token_blocking, fetch_sdk_jwt_blocking;
| DPAPI token storage on Windows
|-- ZoomEngineClient * - IPC singleton: launches engine, owns pipes/sockets,
| tracks roster/speaker, dispatches frame callbacks,
| subscribe_spotlight / subscribe_screenshare
|-- ZoomReconnectManager - exponential back-off recovery after crash/disconnect;
| stores session credentials for re-join
|-- ZoomSource - per-source: reads I420+PCM from ShmRegion,
| AssignmentMode (Participant/ActiveSpeaker/Spotlight/ScreenShare),
| failover_participant_id, HwVideoPipeline, OBS hotkeys
|-- HwVideoPipeline - optional FFmpeg I420->NV12 (CUDA/VAAPI/VideoToolbox/QSV)
|-- ZoomAudioRouter - SDK audio fan-out to all registered sinks
|-- SpeakerDirector - directed active speaker state, debounce,
| manual take/release, clean source handoff
|-- ZoomOutputManager - central source registry for runtime reconfiguration
|-- ZoomOutputProfile - named JSON profile persistence
|-- ZoomControlServer - TCP JSON API on port 19870 (hardened token auth);
| oauth_callback command for URL scheme forwarding
|-- ZoomOscServer - UDP OSC API on port 19871
|-- cv-style.h / cv-widgets - CoreVideo stylesheet, CvStatusDot, CvBanner
`-- zoom-types.h - MeetingState, AssignmentMode, MeetingKind,
RecoveryReason, ParticipantInfo, ZoomJoinAuthTokens...
ZoomObsEngine (separate child process - owns ALL Zoom SDK access)
|-- Zoom SDK 5.17+/7.x (auth, meeting+webinar join, participant/spotlight tracking,
| raw video/audio capture)
`-- Communicates with plugin via:
|-- JSON over named pipes (Windows) or Unix sockets (macOS/Linux)
| Plugin->Engine: init - join(kind) - leave - subscribe - subscribe_spotlight
| subscribe_screenshare - unsubscribe - quit
| Engine->Plugin: ready - auth_ok - auth_fail - joined - left - frame - audio
| participants(+spotlight_index/is_sharing_screen) - active_speaker - error
`-- Named shared memory (ZoomObsPlugin_<uuid>) for I420 video + PCM audio frames
CoreVideoOAuthCallback (thin helper binary - ships beside the plugin)
|-- Windows: CoreVideoOAuthCallback.exe - intercepts corevideo:// URI via registry;
| reads control-server port from OBS global config; POSTs oauth_callback command
`-- macOS: CoreVideoOAuthCallback.app - registered with Launch Services for corevideo://;
same forwarding behaviour
See the full documentation for all architecture diagrams including the ZoomEngineClient deep-dive, OAuth PKCE flow, assignment mode flows, auto-reconnect, hardware video acceleration, TCP + OSC API references, output profile format, and full IPC protocol reference.
CoreVideo/
|-- CMakeLists.txt
|-- buildspec/
| |-- macos.cmake
| `-- windows.cmake
|-- cmake/
| `-- CoreVideoOAuthCallback-Info.plist.in # macOS OAuth helper bundle plist
|-- data/locale/en-US.ini
|-- docs/ # GitHub Pages documentation
| |-- index.html
| |-- ZOOM_MARKETPLACE_OAUTH.md # OAuth setup guide
| `-- policies/ # Security & privacy policy documents
|-- engine/src/ # ZoomObsEngine (owns ALL SDK access)
| |-- main.cpp # IPC loop, SDK auth/join/webinar, spotlight tracking
| |-- engine-video.cpp/h # IZoomSDKRenderer -> named shared memory (I420)
| `-- engine-audio.cpp/h # SDK audio -> named shared memory (PCM)
`-- src/ # OBS plugin (no SDK linkage)
|-- plugin-main.cpp # Module load/unload, dock, Tools menu, SIGPIPE
|-- zoom-source.* # Participant source: ShmRegion, AssignmentMode,
| # HwVideoPipeline, failover, hotkeys, placeholder
|-- zoom-engine-client.* # IPC singleton: engine launch, spotlight/screenshare,
| # monitor thread, deferred join, roster callbacks
|-- zoom-oauth.* # Broker PKCE: ZoomOAuthManager, SDK JWT fetch,
| # register_url_scheme, token refresh + DPAPI storage
|-- oauth-callback-helper.cpp # Windows: CoreVideoOAuthCallback.exe entry point
|-- oauth-callback-helper-macos.mm # macOS: CoreVideoOAuthCallback.app entry point
|-- zoom-dock.* # Qt dockable join/leave/recovery control panel;
| # CvStatusDot, CvBanner, token-type selector
|-- zoom-reconnect.* # Auto-reconnect with exponential back-off
|-- zoom-types.h # MeetingState, AssignmentMode, MeetingKind,
| # RecoveryReason, ParticipantInfo, ZoomJoinAuthTokens...
|-- cv-style.h # CoreVideo QSS stylesheet (dark theme, button roles)
|-- cv-widgets.* # CvStatusDot (animated dot), CvBanner (notice strip)
|-- hw-video-pipeline.* # FFmpeg I420->NV12 (CUDA/VAAPI/VideoToolbox/QSV)
|-- zoom-audio-delegate.* # Mixed/isolated SDK audio -> OBS
|-- zoom-audio-router.* # Central SDK audio fan-out
|-- zoom-auth.* # SDK JWT auth + observable auth state
|-- zoom-meeting.* # Meeting state machine
|-- zoom-participants.* # Roster, active speaker, spotlight callbacks
|-- zoom-participant-audio-source.* # Per-participant audio OBS source
|-- zoom-interpretation-audio-source.* # Language interpretation OBS source
|-- zoom-video-delegate.* # Video frames, resolution, loss mode, preview
|-- zoom-share-delegate.* # Screen share frames -> OBS
|-- zoom-output-manager.* # Source registry + runtime reconfiguration
|-- zoom-output-profile.* # Named JSON profile persistence
|-- zoom-output-dialog.* # Qt Output Manager dock widget
|-- zoom-diagnostics-dialog.* # Qt Diagnostics dock widget
|-- zoom-control-server.* # TCP JSON API (port 19870) + oauth_callback command
|-- zoom-osc-server.* # UDP OSC API (port 19871)
|-- zoom-settings.* # Broker URL, OAuth tokens, local ports + reconnect persistence
|-- zoom-settings-dialog.* # Qt Settings dialog with Zoom sign-in + local settings
|-- zoom-credentials.h.in # Embedded SDK credentials (CMake-generated)
|-- obs-zoom-version.h.in # Plugin version (CMake-generated)
|-- engine-ipc.h # IPC constants + cross-platform helpers
`-- obs-utils.* # OBS helper functions
See SECURITY.md for the vulnerability disclosure policy.
See LICENSE for details.