Four fixes, three of them found on a live meeting the same day. Two are the
kind you see rather than read about: the picture stops flashing, and joining
early no longer cancels itself.
Fixed
-
Participants flashed brighter for a single frame, at random, several times a minute across the whole grid — the long-standing "gamma flash". The engine asks the Zoom SDK for full-range colour and the plugin declares
VIDEO_RANGE_FULLon every frame it hands OBS, but the SDK does not always honour that request. Measured live by attaching to the video shared memory read-only from a third process and histogramming luma: 16 frames out of 15,203 arrived limited-range (16–235) instead, spread across 5 of 6 participants. Declared full but actually limited, such a frame renders with lifted blacks and crushed whites — a ~33 ms brightness pop landing somewhere on an 8-tile grid every 20–30 seconds.YUVRawDataI420::IsLimitedI420()reports this per frame and had never been called anywhere in the codebase. The engine now checks it and expands those frames to full range before they reach shared memory. This is also the cause of program output measuring washed out against mimoLive on 2026-08-11. Fixed by normalising pixels rather than forwarding the flag toobs_source_frame::full_range, because libobs keys async texture allocation on that field and rebuilds every texture when it changes — per-frame flipping would trade a one-frame pop for a texture-rebuild storm. The full-range path (the overwhelming majority of frames) is unchanged and does no extra copy. Verified live after the fix: zero limited-range frames reaching OBS. -
The join watchdog auto-left a Zoom waiting room while the host was still admitting us. Live: the plugin sat in a waiting room for 114 s, the two-minute watchdog counted that as "no join progress", auto-left at 120 s and marked the attempt Failed — and the host admitted the retry 49 s later. Joining early and waiting to be admitted is the normal broadcast workflow, so the watchdog was most likely to fire precisely when nothing was wrong, minutes before a show. Nothing in the codebase handled
MEETING_STATUS_IN_WAITING_ROOMor_WAITINGFORHOST; the engine now reports both as their own event on every status change. The window is held open while a legitimate wait is in progress rather than extended — no timeout is both safely longer than "a host taking their time" (no upper bound) and short enough to catch a wedge — so the full two minutes become available again the moment the wait ends, and a join that wedges after admission is still caught. -
The Companion module could not be loaded by Companion at all. Installing it into a real Companion (v5.0.3) surfaced three blockers, none visible from the source: a missing
companion/manifest.json(required since Companion v3); CommonJS output from a source tree already written for ESM, which made the bundler wrap the entrypoint so its default export came back as the namespace object and Companion's loader rejected it with "Module entrypoint did not return a valid constructor function"; and a module version that had to be bumped, because Companion refuses to overwrite a version already on disk and silently keeps the broken bundle. Now builds as ESM and reports "Module initialized successfully" with its variables resolving live on button faces.
Added
-
Companion: pick the output and the participant by name. Assigning someone to an output was effectively unusable from a Stream Deck — "OBS Source Name" was a free-text box and "Participant ID" a raw number, so putting Sarah on Participant 3 meant typing the source name exactly and knowing she was user 16788480. Both fields are dropdowns now, populated from the module's own live state; the spotlight and screen-share actions get the same output picker.
Participants are offered — and stored — by name. Zoom user ids are meeting-scoped: the same person rejoining, or next week's run of the same show, gets a new id, so a button holding a raw id silently points at nobody, and once ids get recycled it points at the wrong face on air. The id is resolved from the name against the live roster at press time; a name not in the meeting resolves to "unassigned" and logs a warning rather than guessing. Raw numeric ids still work, and buttons built before this change keep working. Verified live: a button storing only "Sarah Muller" moved Participant 3 from one participant to another, and still resolved correctly after a leave/rejoin.
Companion module
corevideo-obs-1.0.2.tgz is attached to this release. It requires Companion v5 or newer — earlier builds cap the module API at 1.12 and cannot load @companion-module/base 2.x at all. Install it via Companion's Import module package. If you are upgrading from an earlier copy, note that Companion will not overwrite a module version it already has on disk.
Install
Run CoreVideo-Setup-v0.1.44.exe, or unzip CoreVideo-Windows-x64-v0.1.44.zip over your OBS install. Close OBS first. Both the plugin DLL and zoom-runtime\ZoomObsEngine.exe must be updated together — this release changes both, and a DLL-only copy silently half-applies it.