A Python SDK for OBS Studio WebSocket v5.0
—
The Subs enum provides fine-grained control over which OBS events to receive, allowing you to optimize network traffic and callback processing load. Different events have different frequencies and use cases.
from enum import IntFlag
class Subs(IntFlag):
# Low-volume event categories (individual flags)
GENERAL = 1 << 0 # General events
CONFIG = 1 << 1 # Configuration changes
SCENES = 1 << 2 # Scene events
INPUTS = 1 << 3 # Input events
TRANSITIONS = 1 << 4 # Transition events
FILTERS = 1 << 5 # Filter events
OUTPUTS = 1 << 6 # Output events
SCENEITEMS = 1 << 7 # Scene item events
MEDIAINPUTS = 1 << 8 # Media input events
VENDORS = 1 << 9 # Vendor events
UI = 1 << 10 # UI events
# High-volume event categories (individual flags)
INPUTVOLUMEMETERS = 1 << 16 # Volume meter updates (very frequent)
INPUTACTIVESTATECHANGED = 1 << 17 # Input active state changes
INPUTSHOWSTATECHANGED = 1 << 18 # Input show state changes
SCENEITEMTRANSFORMCHANGED = 1 << 19 # Scene item transform changes (frequent)
# Composite subscription flags
LOW_VOLUME = (GENERAL | CONFIG | SCENES | INPUTS | TRANSITIONS |
FILTERS | OUTPUTS | SCENEITEMS | MEDIAINPUTS | VENDORS | UI)
HIGH_VOLUME = (INPUTVOLUMEMETERS | INPUTACTIVESTATECHANGED |
INPUTSHOWSTATECHANGED | SCENEITEMTRANSFORMCHANGED)
ALL = LOW_VOLUME | HIGH_VOLUMEThese events occur occasionally and are suitable for most applications:
These events occur frequently and should be used with caution:
import obsws_python as obs
# Most applications - low-volume events only
client = obs.EventClient(subs=obs.Subs.LOW_VOLUME)
# Specific categories only
client = obs.EventClient(subs=obs.Subs.SCENES | obs.Subs.INPUTS)
# All events (use carefully)
client = obs.EventClient(subs=obs.Subs.ALL)
# No events (request-only mode)
client = obs.EventClient(subs=0)import obsws_python as obs
# Scene and input events only
scene_input_subs = obs.Subs.SCENES | obs.Subs.INPUTS
client = obs.EventClient(subs=scene_input_subs)
# Low-volume events plus transform changes
interactive_subs = obs.Subs.LOW_VOLUME | obs.Subs.SCENEITEMTRANSFORMCHANGED
client = obs.EventClient(subs=interactive_subs)
# Streaming application - outputs and scenes
streaming_subs = obs.Subs.OUTPUTS | obs.Subs.SCENES | obs.Subs.GENERAL
client = obs.EventClient(subs=streaming_subs)
# Audio monitoring - inputs and volume meters
audio_subs = obs.Subs.INPUTS | obs.Subs.INPUTVOLUMEMETERS
client = obs.EventClient(subs=audio_subs)| Subscription | Frequency | Use Cases |
|---|---|---|
LOW_VOLUME | Occasional | General applications, automation |
SCENES | Low | Scene switching apps |
INPUTS | Low-Medium | Audio/video control apps |
OUTPUTS | Low | Streaming/recording monitors |
SCENEITEMTRANSFORMCHANGED | High | Interactive scene editors |
INPUTACTIVESTATECHANGED | Medium | Source monitoring |
INPUTVOLUMEMETERS | Very High | Real-time audio visualizers |
import obsws_python as obs
# Only scene changes - very lightweight
client = obs.EventClient(subs=obs.Subs.SCENES)
def on_current_program_scene_changed(data):
print(f"Scene changed to: {data.scene_name}")
client.callback.register(on_current_program_scene_changed)
input("Monitoring scene changes only...\n")
client.disconnect()import obsws_python as obs
# Audio-focused events
audio_subs = obs.Subs.INPUTS | obs.Subs.INPUTVOLUMEMETERS
client = obs.EventClient(subs=audio_subs)
volume_count = 0
def on_input_mute_state_changed(data):
print(f"Mute changed: {data.input_name} = {data.input_muted}")
def on_input_volume_changed(data):
print(f"Volume changed: {data.input_name} = {data.input_volume_db}dB")
def on_input_volume_meters(data):
global volume_count
volume_count += 1
# Only log every 50 volume updates to avoid spam
if volume_count % 50 == 0:
inputs_with_audio = [name for name, levels in data.inputs.items()
if any(level > -60 for level in levels)]
if inputs_with_audio:
print(f"Audio detected in: {', '.join(inputs_with_audio)}")
client.callback.register([
on_input_mute_state_changed,
on_input_volume_changed,
on_input_volume_meters
])
print("Audio monitoring active (includes volume meters)")
input("Press Enter to stop...\n")
client.disconnect()import obsws_python as obs
from datetime import datetime
# Events relevant for streaming dashboard
dashboard_subs = (obs.Subs.SCENES | obs.Subs.OUTPUTS |
obs.Subs.INPUTS | obs.Subs.GENERAL)
client = obs.EventClient(subs=dashboard_subs)
def log_with_time(message):
timestamp = datetime.now().strftime("%H:%M:%S")
print(f"[{timestamp}] {message}")
def on_current_program_scene_changed(data):
log_with_time(f"🎬 Scene: {data.scene_name}")
def on_stream_state_changed(data):
if data.output_active:
log_with_time("🔴 Stream STARTED")
else:
log_with_time("⚫ Stream STOPPED")
def on_record_state_changed(data):
if data.output_active:
log_with_time("📹 Recording STARTED")
else:
log_with_time("⏹️ Recording STOPPED")
def on_input_mute_state_changed(data):
emoji = "🔇" if data.input_muted else "🔊"
log_with_time(f"{emoji} {data.input_name}")
client.callback.register([
on_current_program_scene_changed,
on_stream_state_changed,
on_record_state_changed,
on_input_mute_state_changed
])
log_with_time("Streaming dashboard monitoring started")
input("Press Enter to stop...\n")
client.disconnect()import obsws_python as obs
# Scene editing with high-frequency transform events
editor_subs = (obs.Subs.SCENES | obs.Subs.SCENEITEMS |
obs.Subs.SCENEITEMTRANSFORMCHANGED)
client = obs.EventClient(subs=editor_subs)
transform_updates = {}
def on_scene_item_created(data):
print(f"➕ Item created: {data.source_name} in {data.scene_name}")
def on_scene_item_removed(data):
print(f"➖ Item removed: {data.source_name} from {data.scene_name}")
def on_scene_item_transform_changed(data):
# Track transform updates per item
item_key = f"{data.scene_name}:{data.scene_item_id}"
transform_updates[item_key] = transform_updates.get(item_key, 0) + 1
# Log every 10 updates per item
if transform_updates[item_key] % 10 == 0:
print(f"🔄 Transform updates for item {data.scene_item_id}: {transform_updates[item_key]}")
def on_scene_item_enable_state_changed(data):
state = "enabled" if data.scene_item_enabled else "disabled"
print(f"👁️ Item {data.scene_item_id} {state}")
client.callback.register([
on_scene_item_created,
on_scene_item_removed,
on_scene_item_transform_changed,
on_scene_item_enable_state_changed
])
print("Scene editor monitoring active (includes transform changes)")
print("Move scene items around to see transform events...")
input("Press Enter to stop...\n")
client.disconnect()
# Show final transform update counts
if transform_updates:
print("\nFinal transform update counts:")
for item, count in transform_updates.items():
print(f" {item}: {count} updates")Install with Tessl CLI
npx tessl i tessl/pypi-obsws-python