Relationships
#4686 @swamp/video/obs: add the brand stage to an existing OBS scene, with the webcam ring and mask optional
Opened by skunk-ape · 11/12/2026
Problem
#4104 shipped the brand's OBS studio look. video-brand stage renders backdrop.png, camera-ring.webm (a looping neon ring around the webcam, VP9 with alpha) and camera-mask.png (a circular webcam mask), plus a stage resource with the screen, camera and ring rectangles on a 1920x1080 stage. Nothing puts them into OBS. #4105 would, but only in its managed mode, which builds a new scene. Its adopt mode uses an existing scene as-is, and the presenter's existing "Product Demo" profile runs under adopt. So, as #4105 is written, that profile never gets the brand look.
OBS records the screen and webcam composited, so the look has to be in the scene before recording. It can't be added afterwards.
Proposed change
The smallest step towards #4105, in @swamp/video/obs (private, depends on @swamp/video and @swamp/video/brand): one method that adds the brand stage to an existing OBS scene over obs-websocket v5.
- Inputs: the scene name, which existing sources are the screen capture and the webcam, the
stageresource fromvideo-brand stage, and the websocket password from a vault. - What it adds: the backdrop behind everything, the screen source placed at the
screenrectangle, the circle mask on the webcam (as a filter), the webcam at thecamerarectangle, and the ring as a looping media source at theringrectangle. Positions are scaled to the scene's canvas when it isn't 1920x1080. - The ring and mask are optional. It isn't settled whether we want the decorated webcam, so:
- an input chooses what's added:
ring(default on) andmask(default on); - the ring is its own scene item, named consistently, so it can be shown or hidden in OBS (or with a hotkey) while recording, without re-running anything;
- a re-run with
ringoff removes the ring item it added.
- an input chooses what's added:
- Safe on someone's real scene. Every item it adds is named with a fixed prefix. A re-run replaces its own items and changes nothing else. A
removemethod takes them all out again, putting the screen and webcam sources back where they were (save their transforms before changing them). With--dry-run(or an equivalent input) it prints what it would change. - It checks the OBS version and websocket, and refuses with a clear message when a named source isn't in the scene.
- Leave out the rest of #4105 (detect, recording control, markers, managed mode, the
recordworkflow). Name the shared pieces so #4105 can build on them: the websocket client, vault lookup and stage placement.
Done when
- On an existing scene, the method adds the backdrop, places the screen, and masks and places the webcam with the ring looping around it. A screenshot or short recording shows it.
- With
ringoff, the webcam is masked and placed with no ring. Withmaskoff as well, it's a plain rectangle at thecameraposition. - The ring can be toggled in OBS during a recording, and the recording shows the change.
- A re-run changes nothing new.
removerestores the scene to how it was. Neither touches items it didn't add. - Unit tests cover placement scaling and the request list against a fake websocket. A manual check is done against a real OBS.
- The README describes setup for an existing profile.
Out of scope
The rest of #4105, changes to how the brand renders, and per-person hardware detection.
Open
No activity in this phase yet.
system commented 11/12/2026, 7:46:11 PM
Classified automatically when this issue was filed.
- Source: Extensions
If you feel this classification is incorrect, add a ripple to tell us so.
Sign in to post a ripple.