Modern .NET client for OBS Studio WebSocket v5, with generated protocol types and DI-first integration.
net10.0net9.0
dotnet add package ObsWebSocket.Core- Strongly typed request/response DTOs generated from OBS protocol
- Strongly typed OBS event args
- Async-first API (
Task,ValueTask, cancellation support) - DI helpers via
AddObsWebSocketClient() - Configurable JSON or MessagePack transport
- Reconnect and timeout options via
ObsWebSocketClientOptions - Convenience helpers for common scene/input/filter workflows
- This library is for OBS WebSocket v5 only (OBS Studio 28+).
- Make sure OBS WebSocket server is enabled (
Tools -> WebSocket Server Settings). - If you use authentication, provide the correct password in options/config.
appsettings.json:
{
"Obs": {
"ServerUri": "ws://localhost:4455",
"Password": "",
"EventSubscriptions": null,
"Format": "Json"
}
}Program.cs:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ObsWebSocket.Core;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.Configure<ObsWebSocketClientOptions>(
builder.Configuration.GetSection("Obs"));
builder.Services.AddObsWebSocketClient();
builder.Services.AddHostedService<Worker>();
await builder.Build().RunAsync();Worker example:
using Microsoft.Extensions.Hosting;
using ObsWebSocket.Core;
using ObsWebSocket.Core.Events.Generated;
public sealed class Worker(ObsWebSocketClient client) : IHostedService
{
public async Task StartAsync(CancellationToken ct)
{
client.CurrentProgramSceneChanged += OnSceneChanged;
await client.ConnectAsync(ct);
var version = await client.GetVersionAsync(cancellationToken: ct);
Console.WriteLine($"Connected to OBS {version?.ObsVersion}");
}
public async Task StopAsync(CancellationToken ct)
{
client.CurrentProgramSceneChanged -= OnSceneChanged;
if (client.IsConnected)
{
await client.DisconnectAsync();
}
}
private static void OnSceneChanged(object? sender, CurrentProgramSceneChangedEventArgs e)
{
Console.WriteLine($"Program scene: {e.EventData.SceneName}");
}
}Common helper APIs include:
SwitchSceneAndWaitAsync(...)SetInputTextAsync(...)SetSceneItemEnabledAsync(...)SourceExistsAsync(...)GetSourceFilterSettingsAsync<T>(...)WaitForEventAsync<TEventArgs>(...)
For generated request models and direct requests, see:
ObsWebSocket.Core.Protocol.RequestsObsWebSocket.Core.Protocol.ResponsesObsWebSocket.Core.Events.Generated
Batch API note (AOT-safe path):
BatchRequestItem.RequestDatashould benull,JsonElement, or a generated*RequestDataDTO fromObsWebSocket.Core.Protocol.Requests.- Arbitrary anonymous/POCO objects are not guaranteed to be serializable in Native AOT builds.
ObsWebSocket.Example contains a host-based sample using configuration + DI.
- Interactive mode: starts a command loop (
help,version,scene,batch-example, etc.) - Transport validation mode: runs JSON + MsgPack validation cycles (scene/input/filter stub-heavy calls), then enters the interactive loop
- One-shot mode: pass a command as process arguments to run it directly and exit (for CI/automation), for example:
ObsWebSocket.Example run-transport-tests
appsettings.json:
{
"Obs": {
"ServerUri": "ws://localhost:4455",
"Password": "",
"EventSubscriptions": null,
"Format": "Json"
},
"ExampleValidation": {
"RunValidationOnStartup": false,
"ValidationIterations": 1
}
}Interactive command to run validation on demand:
run-transport-tests
Build and run the example as Native AOT:
dotnet publish ObsWebSocket.Example/ObsWebSocket.Example.csproj -c Release -r win-x64 --self-contained true
./ObsWebSocket.Example/bin/Release/net10.0/win-x64/publish/ObsWebSocket.Example.exeContributions are welcome. See CONTRIBUTING.md.
MIT. See LICENSE.txt.