The windows-2022 runner had NSIS pre-installed. The windows-2025 runners
are slimmer and do not have NSIS installed. The windows-2025 runners do
have winget available, which can be used to install NSIS.
The windows-2025 runners do not have NSIS in PATH by default, so we need
to specify it manually in the config files.
Follow-up to ac19ea6633.
The windows-2022 runner had NSIS pre-installed. The windows-2025 runners
are slimmer and do not have NSIS installed. The windows-2025 runners do
have winget available, which can be used to install NSIS.
The windows-2025 runners do not have NSIS in PATH by default, so we need
to specify it manually in the config files.
Microsoft's sarif-multitool requires platform-specific binaries to run
(even though it's installed via npm) and does not ship an Apple Silicon
binary. With Rosetta 2 being deprecated in macOS 27, the tool would
stop working once the project had updated to macOS 27 runners.
Using "jq" provides a cleaner alternative, as the required
transformation is transparent in code and does not require any
additional tools or binaries.
Recent Homebrew versions require 3rd party taps to be explicitly trusted
before they can be used to install formulas.
The "obsproject/tools" tap is used to provide pinned formulas of some
code formatters used by CI and thus needs to be trusted to enable
installation of these formulas.
Previously it was setting the `averageBitRate` value to what is being set in Variable Bitrate rate control mode. However, CQVBR is initialized with a value of `0` and instead Target Quality is being used. This adds a check for the CQVBR mode and if it's set will update the `targetQuality` value, otherwise it will update `averageBitRate`.
Additionally reset `averageBitRate` to 0 if CQVBR is active, and reset `targetQuality` to 0 if it's not in any VBR mode
This will also allow us to move to clang-format 22 which ships with
VS 2026.
* Update the CI image to windows-2025-vs2026
* Update VS generator to 2026
* Update Windows SDK to 26100
This was used to ensure that we had Python 3.12 or newer. The Ubuntu
24.04 runners now have Python 3.12, and the macOS 15 and 26 runners have
Python 3.14.
When OBS runs via Rosetta 2 emulation on an Apple Silicon host, the
next automatic update via Sparkle should use a native Apple Silicon
build rather than the newest Intel build.
This is achieved by setting a custom feed URL on the delegate object
which will then respond with this URL (or alternatively with "nil")
when Sparkle calls the appropriate delegate method.
Adds necessary delegate method to OBSSupdateDelegate to provide
alternative AppCast feed URL at runtime.
The NSString pointer is allowed to be "nil" as Sparkle will only use
a non-nil return value to change from the default feed URL.
MSVC Build Tools 14.50 shipping in Visual Studio 2026 18.0 have
officially deprecated any experimental implementation of coroutines.
The WinRT base header does conditionally include the experimental header
if no "native" implementation can be found (which will be true for
any C++ language version before C++20).
Even though libobs-winrt does not make use of any coroutines, it has to
include the base header and will thus trigger this error.
Per the official deprecation notice, this warning can be silenced and
will be automatically resolved once the project upgrades to C++20
support.
- Update nv-codec to n13.0.19.0
- Update FFmpeg to 8.1
- Update qrcodegen-cmake to v1.8.0-cmake4
- Update libdatachannel to v0.24.2
- Update plog to version 1.1.11
- Update Qt to 6.11.1
- Update libvpl to version 2.16.0
- Update vpl-grpu-rt to version 26.1.5
- Update ECM to version 6.26.0
With the switch to Xcode 26.5 the analyze command started to use the
built-in compilation cache (per the CMake preset) which breaks those
builds specifically as no writable CAS path is set for this workflow.
This change adds the same code used for the normal build workflow to
set a specific CAS path. Because the contents of that path are not
retained by a caching action, no actual caching for analyze builds takes
place.
When the app is quit on macOS, the underlying process is either
triggered by an application-level "Quit" event or by a main window
"close" event.
If the application-level "Quit" event is the trigger, OBSBasic::saveAll
is called twice: First by Qt's session manager (via OBSApp::commitData)
and another time by the main window's close event handled by
OBSBasic::closeWindow.
However if the main window is closed first (and is the first to call
"saveAll") the underlying OAuth data object is destroyed after the data
has been saved. When the second "saveAll" call takes place, it
encounters a "nullptr" for the auth object, which makes "Auth::Save"
effectively remove any OAuth configuration from the settings file
(undoing prior work).
At the other end, if the application quits first, some dock windows
might have been explicitly closed by Qt before the main window is closed
and thus the second call to "saveAll" will overwrite valid browser dock
state data with incomplete data (any dock that has been closed by Qt
before will not be present in that data).
Wrapping the code responsible for saving OAuth and browser dock state
data in a "std::call_once" block should ensure that this data is only
written once and by whoever gets to call "saveAll" first (at which point
state data is still considered "complete").
Custom configuration for multitrack-enabled services is only supposed
to be available for the "rtmp_custom" service type, as that's also
the condition for the corresponding text input to become visible in the
settings dialog.
When a user switches their desired service from the custom service back
to another service that also supports multitrack, the custom service
configuration is still present and will be applied even though it
should only be effective for the custom service.
This change makes the simple decision to ignore any available custom
multitrack configuration if the service is not "rtmp_custom" and
requires an "auto_config_url" to be available in that case. Otherwise
the "rtmp_custom" service requires an "custom_config" to be available.
That way the implementation reflects the behavior of the settings dialog
and will not lead to the present unexpected behavior, including:
* The custom configuration is "merged" with the config ID provided
via the "auto_config_url".
* A non-custom service might fail to configure because the custom config
is applied and might be missing required fields.
* A non-custom service might succeed to configure because the custom
config is applied and has all required fields, but the service was
meant for an entirely different service.
Additionally the unused "MultitrackVideoDeveloperModeEnabled" function
was removed. For simplicity's sake, all legacy code paths that allowed
interference or custom overrides with the service configuration for
established services are removed.
If such functionality is still desired, it needs to be reimplemented in
a service-agnostic way, taking the possibility of other multitrack-
capable services into account.
Frontend plugins should not require being placed in the frontend
directory to be built successfully. Indeed they should only depend
on libobs and the obs-frontend-api and thus their source tree should
be able to exist anywhere (even standalone) and the plugin should still
compile successfully (just like any 3rd party plugin).
Thus moving those plugins into the main plugin directory ensures that
they don't require on any "special sauce" within the source tree to
compile.