Skip to content

requesthandler: Add Canvas support#1314

Merged
RytoEX merged 1 commit intoobsproject:masterfrom
exeldro:canvas
Feb 25, 2026
Merged

requesthandler: Add Canvas support#1314
RytoEX merged 1 commit intoobsproject:masterfrom
exeldro:canvas

Conversation

@exeldro
Copy link
Contributor

@exeldro exeldro commented Aug 31, 2025

Description

Add Canvas support

Motivation and Context

Scenes in not the main canvas are now not accessible

How Has This Been Tested?

using different obs-websocket clients, calling the new GetCanvasList and calling the other scene call with and without a canvas
Tested OS(s): Windows 11

Types of changes

  • New request/event (non-breaking)

Checklist:

  • I have read the Contributing Guidelines.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • My code is not on master or a release/* branch.
  • The code has been tested.
  • I have included updates to all appropriate documentation.

@RytoEX RytoEX requested review from PatTheMav and tt2468 September 8, 2025 20:05
@PatTheMav
Copy link
Member

Canvases (at least per their original concept) are a data structure to allow OBS Studio as well as plugins to generate and access "outputs" that exist in the application. I'd be interested to learn what the use case for a websocket-based client would be to get direct access to this internal data object?

Conceptually a remote control client (what websockets is made for) should not futz around with canvases - it can interact with OBS (which then uses canvases to achieve the required result) or possibly with a plugin (which again might use a canvas to do so), but the fact that canvases exist is not something an external API should even know about.

@pwnyy
Copy link

pwnyy commented Oct 1, 2025

Canvases (at least per their original concept) are a data structure to allow OBS Studio as well as plugins to generate and access "outputs" that exist in the application. I'd be interested to learn what the use case for a websocket-based client would be to get direct access to this internal data object?

Conceptually a remote control client (what websockets is made for) should not futz around with canvases - it can interact with OBS (which then uses canvases to achieve the required result) or possibly with a plugin (which again might use a canvas to do so), but the fact that canvases exist is not something an external API should even know about.

Adding canvas support seems rather important for applications that are communicating over the websocket server, to control and alter scenes, sources and filters on a different canvas. This would be especially true for those people that, for example were previously using a plugin to have a vertical "canvas" and with a third-party application that uses the websocket client alter/create/remove these scenes, sources or filters.

Currently this is not really possible anymore, as the plugin also switched over to the canvas system.

I can potentially see why you don't want the whole canvas object exposed, however a way to differentiate canvases with what scenes or sources are on which canvas and to be able to directly target these things is something that still should be considered. Same as maybe an optional parameter to target a specific canvas, if not set it will use the main canvas, to target things.
Being able to get a list of scenes and their sources etc. in each canvas would be needed in that regard as well, which at the very least this PR would provide

Maybe I'm misunderstanding why it wouldn't be a good idea tho.

@nyewkey
Copy link

nyewkey commented Oct 4, 2025

Canvases (at least per their original concept) are a data structure to allow OBS Studio as well as plugins to generate and access "outputs" that exist in the application. I'd be interested to learn what the use case for a websocket-based client would be to get direct access to this internal data object?

Conceptually a remote control client (what websockets is made for) should not futz around with canvases - it can interact with OBS (which then uses canvases to achieve the required result) or possibly with a plugin (which again might use a canvas to do so), but the fact that canvases exist is not something an external API should even know about.

This change unintentionally breaks workflows for thousands of users relying on tools like Streamer.bot, MixItUp and the Aitum Vertical plugin.

Without Canvas support, external apps can no longer detect or control sources/scenes in vertical canvases; which were fully functional prior to 32.x.

Re-enabling access (even just via an optional canvas parameter) would restore compatibility without exposing internal structures unnecessarily.

This regression effectively breaks compatibility with popular automations and streaming workflows that depend on OBS websocket control.

@PatTheMav
Copy link
Member

PatTheMav commented Oct 6, 2025

Maybe I'm misunderstanding why it wouldn't be a good idea tho.

Because canvases as we designed them are black boxes that have no context or meaning to anyone but the creator of a canvas.

OBS Studio knows what its canvases "are" (which one is the main video output, which one is the virtual camera, which one might be OBS Studio's built-in vertical output, whenever the app might get one). Likewise Aitum knows what their canvases "are", their meaning and usage.

But OBS Studio has no clue what those canvases "mean" and it keeps its hands off them: Only Aitum interacts with its canvases, only OBS Studio interacts with its canvases, anything that has no clue about canvases is implicitly interpreted to target the "main" canvas.

Canvases in that sense are designed and implemented to be a data management object for some part of the program to create and manage an output.

Anything beyond that has no contextual information to work with them: Given multiple canvases with vertical resolution, how would another plugin (or websocket client) "know" which one is Aitum's and which one is OBS Studio's? Or the one by yet another plugin (even the multi-track code just picks canvases based on output resolution, not by creator)?

At best you could hope that each creator has used a meaningful human-readable name that allows users to distinguish them, but there is zero concern for that in the design of canvases right now. We need to stop exposing libobs internals that were not designed nor made for public use just because they are "there".

@PatTheMav
Copy link
Member

Small addendum: The main problem is one of disambiguating canvases just based on names, which can potentially be done by a change in libobs itself that would require no further changes to API consumers. It's not great, but a good-enough compromise and would just be a necessary change in libobs before this PR could potentially be merged as-is.

@jdudetv
Copy link
Contributor

jdudetv commented Nov 3, 2025

bumping as this would be such a great feature with stuff like the Aitum Stream Suite adding unlimited canvas generation. Being able to get information about those items would be extremely helpful.

@LinuxMainframe
Copy link

Bumping as I have encountered a loss in functionality post 32.x, and had to roll back to 29.x

Copy link
Member

@Warchamp7 Warchamp7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have very mixed feelings about adding optional canvasName/canvasUuid parameters to a bunch of existing methods simply for handling Scene and Group sources when doing requests by object names rather than UUIDs, but I'm not sure there is a better short term solution.

What is the behaviour of these changes if a request is made for a Source such as GetSourceFilterList when canvasName/canvasUuid are provided but not needed? Is it completely ignored, or is there an unnecessary lookup/validation still?

If the lookup always happens no matter what, what happens when sourceUuid is provided and is enough to get the relevant object (Ex. Not a Scene or Group source) but an unnecessary canvasName/canvasUuid is still provided which is incorrect for that source? Does it serve as an additional way to ensure the correct source and cause an error due to the mismatch or is it ignored?

@Warchamp7
Copy link
Member

This change unintentionally breaks workflows for thousands of users relying on tools like Streamer.bot, MixItUp and the Aitum Vertical plugin.

Can you explain how this affects Streamer.bot and MixItUp specifically? Or do you mean their functionality that worked with Aitum Vertical?

@protected22
Copy link

protected22 commented Nov 9, 2025

This change unintentionally breaks workflows for thousands of users relying on tools like Streamer.bot, MixItUp and the Aitum Vertical plugin.

Can you explain how this affects Streamer.bot and MixItUp specifically? Or do you mean their functionality that worked with Aitum Vertical?

This is with more external program's (Touchportal, Streamdeck, Streaminterakt etc) when the person uses the Aitum Vertical plugin in OBS. All external program's don't recognise vertical scenes anymore since OBS version 32 and Aitum Vertical 1.6.0. So all integrations or actions which you can set up in those program's lost all functionality since.

@Warchamp7
Copy link
Member

This change unintentionally breaks workflows for thousands of users relying on tools like Streamer.bot, MixItUp and the Aitum Vertical plugin.

Can you explain how this affects Streamer.bot and MixItUp specifically? Or do you mean their functionality that worked with Aitum Vertical?

This is with more external program's (Touchportal, Streamdeck, Streaminterakt etc) when the person uses the Aitum Vertical plugin in OBS. All external program's don't recognise vertical scenes anymore since OBS version 32 and Aitum Vertical 1.6.0. So all integrations or actions which you can set up in those program's lost all functionality since.

Yes this is because before the Aitum plugin was doing some very unsupported stuff by creating normal sources for a fake vertical canvas it had 'cheated' and merely hiding them from the UI. It was all very messy and we added Canvases as a first-party feature to smooth that out.

While this is a regression for users, it is a side effect of Aitum (Very graciously) switching over to using canvases instead of sticking to hacking them in.

While we want to restore this functionality to folks, we also want to make sure we do it properly and avoid creating any future headaches for us down the line.

@stevo-ko
Copy link

Yes this is because before the Aitum plugin was doing some very unsupported stuff by creating normal sources for a fake vertical canvas it had 'cheated' and merely hiding them from the UI. It was all very messy and we added Canvases as a first-party feature to smooth that out.

While this is a regression for users, it is a side effect of Aitum (Very graciously) switching over to using canvases instead of sticking to hacking them in.

While we want to restore this functionality to folks, we also want to make sure we do it properly and avoid creating any future headaches for us down the line.

I just wanted to add some context about how this actually affects the user experience.

Right now, it's probably only Aitum — but if more plugins start using their own canvas, the problem will grow.

For example, in streamer.bot you can connect to OBS to modify scenes, trigger transitions, and so on.
But when a plugin like Aitum uses its own canvas, all scenes that exist only inside that canvas are completely inaccessible to external programs.
We can't edit them, we can't reference them — we can't even see that those scenes exist if they aren’t part of OBS’s main canvas.

So many of the Users that are using Aitum switched back to the older version of OBS and are staying there cause of that regression.

@saschagehlich
Copy link

Just want to note that this not only affects Aitum Vertical, but many other platforms that previously supported enabling / disabling vertical scenes through websocket.

@huds601
Copy link

huds601 commented Feb 18, 2026

Not going to lie, as an alpha and now beta tester for vertical on Twitch, lack of websocket support for the vertical canvas since Aitum switched to the first-party canvas feature has been excrutiatingly painful to deal with.

Following the developments here and seeing ZERO progress in almost SIX months has been even more frustrating to watch, especially knowing there is a solution offered (albeit maybe not perfect, but a solution nevertheless) yet arguments continue over the specifics of implementation that, frankly, really don't matter compared to the COMPLETE LOSS OF FUNCTIONALITY.

There is a clear need for multiple canvas support in obs-websocket for the growing number of vertical streamers. We are in danger of Twitch releasing vertical to all and there still won't be proper support in obs-websocket.

I'm now having to look at asking a developer to code a custom script for Firebot to hook into Aitum's vendor requests. This is likely going to be a stop-gap at best offering minimal support for some of my overlay automation. Worse still, I'm going to end up putting in tens of hours of work updating my automation knowing I'm going to have to eventually redo all of of it when something eventually ships on the websocket side.

Can you please at least ship SOMETHING to support the growing number of vertical streamers controlling scenes/sources via 3rd party bots using obs-websocket, and worry about the minutia and possible future use-cases later?!

@dennisrijsdijk
Copy link

dennisrijsdijk commented Feb 20, 2026

@Warchamp7 has requested testing in discord, here are my findings so far:

I can't get any scene or source related events to fire from alternate canvases. @tt2468 had some comments about this in discord

When trying to set the program scene on another canvas, it shows that scene on the main canvas instead.

Request: '{"op":6,"d":{"requestId":"58","requestType":"SetCurrentProgramScene","requestData":{"canvasUuid":"485c4343-2a4f-43d3-a10d-61196dc7da26","sceneName":"Scene"}}}'

2026-02-20.22-11-10.mp4

Nitpick: I don't see an explicit way to know which canvas is the OBS default canvas in GetCanvasList (this is the canvas I would like to present to the user by default when creating new actions)

My use case for knowing which canvas is OBS' default canvas is to pre-fill it in the dropdown, rather than having my own default value, alongside the OBS main canvas. I realize I could implicitly grab it by the name "Main" or using the first canvas returned by array, but unless either of those are recommended as official solutions, I think having an explicit way to do it would be best.

Unsure at the moment if there's more, I need to step away from this for a bit.

@exeldro
Copy link
Contributor Author

exeldro commented Feb 20, 2026

Added flags to GetCanvasList to allow detecting the kind of canvas
Added canvas events

@dennisrijsdijk
Copy link

dennisrijsdijk commented Feb 21, 2026

Can confirm the GetCanvasList change gives me what I need, thanks!

I've also been able to get events working, though I ran into a couple that didn't behave as I'd expect.

Events not firing on alt-canvases

SceneNameChanged

SceneTransitionStarted
CurrentProgramSceneChanged
SceneTransitionEnded
These don't seem to fire because there appears to be no scene transitions in Aitum Stream Suite's Vertical Canvas.

Events without canvasName/canvasUuid

SceneItemCreated
SceneItemRemoved
SceneItemListReindexed

SceneItemEnableStateChanged

SceneTransitionStarted
CurrentProgramSceneChanged
SceneTransitionEnded

This is not an exhaustive list of events as I don't subscribe to all events available through the websocket.

@dennisrijsdijk
Copy link

dennisrijsdijk commented Feb 21, 2026

I missed CurrentProgramSceneChanged in my previous comments, it's also not firing on an alternate canvas. Though there should probably be an explicitly new event for scene changes on canvases (including main)

The issue with SetCurrentProgramScene putting the vertical scene on the main OBS canvas is still happening. Though just like CurrentProgramSceneChanged, this may need a new request to change a canvas scene, rather than expanding program scene to handle multiple canvases.

SceneNameChanged is still not firing on alternative canvases (could this be related to the plugin which provides the canvas instead of OBS? I do see code changes related to it in this PR)

SceneItemEnableStateChanged still isn't passing along canvasName/canvasUuid

Copy link
Member

@Warchamp7 Warchamp7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Canvas will need to be added to the category list in docs/docs/generate_md.py.

The places noting @category canvases should be adjusted to @category canvas

@Warchamp7
Copy link
Member

Events without canvasName/canvasUuid

SceneItemCreated SceneItemRemoved SceneItemListReindexed SceneItemEnableStateChanged

SceneTransitionStarted CurrentProgramSceneChanged SceneTransitionEnded

This is not an exhaustive list of events as I don't subscribe to all events available through the websocket.

I'm not sure if it makes sense for Scene Item events to include Canvas info. They already include the Scene context and the Canvas can be determined using that.

@exeldro exeldro force-pushed the canvas branch 2 times, most recently from 5a45ba9 to 6b8b5df Compare February 22, 2026 07:19
@dennisrijsdijk
Copy link

Events without canvasName/canvasUuid

SceneItemCreated SceneItemRemoved SceneItemListReindexed SceneItemEnableStateChanged

SceneTransitionStarted CurrentProgramSceneChanged SceneTransitionEnded

This is not an exhaustive list of events as I don't subscribe to all events available through the websocket.

I'm not sure if it makes sense for Scene Item events to include Canvas info. They already include the Scene context and the Canvas can be determined using that.

unfortunately, I've got legacy setups going back years where the user actions only have the scene name and scene item id, not the scene uuid, and as I recall, scene and group names are not unique across canvases. Having the canvas info included rules out any ambiguity between same-named scenes on different canvases.

@exeldro exeldro requested a review from Warchamp7 February 22, 2026 07:34
@dennisrijsdijk
Copy link

can confirm by the way, SceneNameChanged now functions as expected, and SceneItemEnableStateChanged now includes the canvas info. Previous comment also updated for the issues that remain.

@Warchamp7
Copy link
Member

Warchamp7 commented Feb 24, 2026

Following the developments here and seeing ZERO progress in almost SIX months has been even more frustrating to watch, especially knowing there is a solution offered (albeit maybe not perfect, but a solution nevertheless) yet arguments continue over the specifics of implementation that, frankly, really don't matter compared to the COMPLETE LOSS OF FUNCTIONALITY.

I understand the frustration but we've only had a single OBS release since the time this PR was opened. Even in the best case scenario it would have been fixed in December. It is getting attention now to hopefully be fixed for the next release, or a minor update shortly after.

I'm not sure if it makes sense for Scene Item events to include Canvas info. They already include the Scene context and the Canvas can be determined using that.

unfortunately, I've got legacy setups going back years where the user actions only have the scene name and scene item id, not the scene uuid, and as I recall, scene and group names are not unique across canvases. Having the canvas info included rules out any ambiguity between same-named scenes on different canvases.

At some point in the future the use of name is going to be removed entirely in favor of UUIDs since they are, as the name suggests, unique. Any current setup would fall apart if a scene had two reference copies of the same source right now, as name will grab the first match and there can be multiple.

If you're able to update those setups to utilize the canvas aware data being included by this update, I'd highly recommend also implementing some form of user data update/migration on initialization that updates them to use UUIDs for both handling that edge case as well as future proofing.

@exeldro exeldro force-pushed the canvas branch 2 times, most recently from 4d433a4 to fd793d5 Compare February 24, 2026 15:38
@PatTheMav
Copy link
Member

It looks like canvas removal and destruction are both combined into a single "Canvas Removed" event in the web socket API - is that intentional? If a canvas had no other strong references when it was removed it is also destroyed after, wouldn't that result in the websocket event effectively being emitted twice?

@exeldro
Copy link
Contributor Author

exeldro commented Feb 24, 2026

@PatTheMav I kept it the same as source removed and destroyed, but missed the obs_canvas_removed check, added now

@dennisrijsdijk
Copy link

I just wanted to confirm before this gets merged, it doesn't look like canvas scene switching was addressed yet.

Mentioned in #1314 (comment), the scene from the alternate canvas is rendered onto the main canvas if set using SetCurrentProgramScene, and I don't believe an alternate method for canvases was added in this PR

I just tested it again, and came to the conclusion this is still an issue.

In addition to that, I also still don't get CurrentProgramSceneChanged events for alternate canvases.

@exeldro
Copy link
Contributor Author

exeldro commented Feb 25, 2026

@dennisrijsdijk I am not planning on adding scene switching as that can differ depending on how a plugin uses the canvas

@dennisrijsdijk
Copy link

gotcha, in that case I would say some guardrails should be added to SetCurrentProgramScene to make sure the call can only be used on scenes from the main canvas so the afforementioned issue doesn't happen.

@stevo-ko
Copy link

I am not planning on adding scene switching as that can differ depending on how a plugin uses the canvas

Is my assumption correct that when the scene switching is not added , we can not for example change a scene in the aitum vertical canvas from streamer.bot or equivalents?

Shouldn't something like the call to switch from scene x to scene y be generalised in plugins and not be a everyone makes its own soup?

@exeldro
Copy link
Contributor Author

exeldro commented Feb 25, 2026

@stevo-ko for switching scenes in Aitum Vertical and Aitum Stream Suite vendor requests can be used. As a canvas does not have to use scenes and/or transitions making a generalized way of switching scenes would be difficult. If it is possible it would be something for a separate pull request in my opinion.

@exeldro
Copy link
Contributor Author

exeldro commented Feb 25, 2026

Added canvas check to SetCurrentProgramScene and SetCurrentPreviewScene

@RytoEX RytoEX requested a review from Warchamp7 February 25, 2026 18:07
@RytoEX RytoEX merged commit 6287e95 into obsproject:master Feb 25, 2026
1 check passed
@exeldro
Copy link
Contributor Author

exeldro commented Feb 26, 2026

For all that are following this PR there are follow up changes in #1331

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.