CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-obsws-python

A Python SDK for OBS Studio WebSocket v5.0

Pending
Overview
Eval results
Files

event-subscriptions.mddocs/

Event Subscriptions

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.

Subscription System

Subs Enum

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_VOLUME

Event Categories

Low-Volume Events

These events occur occasionally and are suitable for most applications:

GENERAL (Subs.GENERAL)

  • General OBS events
  • ExitStarted
  • VendorEvent
  • CustomEvent

CONFIG (Subs.CONFIG)

  • Configuration changes
  • CurrentSceneCollectionChanging
  • CurrentSceneCollectionChanged
  • SceneCollectionListChanged
  • CurrentProfileChanging
  • CurrentProfileChanged
  • ProfileListChanged

SCENES (Subs.SCENES)

  • Scene management events
  • SceneCreated
  • SceneRemoved
  • SceneNameChanged
  • CurrentProgramSceneChanged
  • CurrentPreviewSceneChanged
  • SceneListChanged

INPUTS (Subs.INPUTS)

  • Input management events
  • InputCreated
  • InputRemoved
  • InputNameChanged
  • InputSettingsChanged
  • InputMuteStateChanged
  • InputVolumeChanged

TRANSITIONS (Subs.TRANSITIONS)

  • Scene transition events
  • CurrentSceneTransitionChanged
  • CurrentSceneTransitionDurationChanged
  • SceneTransitionStarted
  • SceneTransitionEnded
  • SceneTransitionVideoEnded

FILTERS (Subs.FILTERS)

  • Source filter events
  • SourceFilterCreated
  • SourceFilterRemoved
  • SourceFilterNameChanged
  • SourceFilterSettingsChanged
  • SourceFilterEnableStateChanged

OUTPUTS (Subs.OUTPUTS)

  • Output events (streaming, recording)
  • StreamStateChanged
  • RecordStateChanged
  • ReplayBufferStateChanged
  • VirtualcamStateChanged
  • ReplayBufferSaved

SCENEITEMS (Subs.SCENEITEMS)

  • Scene item management events
  • SceneItemCreated
  • SceneItemRemoved
  • SceneItemListReindexed
  • SceneItemEnableStateChanged
  • SceneItemLockStateChanged

MEDIAINPUTS (Subs.MEDIAINPUTS)

  • Media input events
  • MediaInputPlaybackStarted
  • MediaInputPlaybackEnded
  • MediaInputActionTriggered

VENDORS (Subs.VENDORS)

  • Third-party vendor events
  • VendorEvent (vendor-specific events)

UI (Subs.UI)

  • UI-related events
  • StudioModeStateChanged
  • ScreenshotSaved

High-Volume Events

These events occur frequently and should be used with caution:

INPUTVOLUMEMETERS (Subs.INPUTVOLUMEMETERS)

  • Real-time volume level updates for all inputs
  • InputVolumeMeters event (fires continuously while audio is active)
  • Warning: Very high frequency, can generate hundreds of events per second

INPUTACTIVESTATECHANGED (Subs.INPUTACTIVESTATECHANGED)

  • Input active state changes
  • InputActiveStateChanged event
  • Fires when inputs become active/inactive (e.g., when sources start/stop producing content)

INPUTSHOWSTATECHANGED (Subs.INPUTSHOWSTATECHANGED)

  • Input show state changes
  • InputShowStateChanged event
  • Fires when inputs become visible/hidden in scenes

SCENEITEMTRANSFORMCHANGED (Subs.SCENEITEMTRANSFORMCHANGED)

  • Scene item transform changes
  • SceneItemTransformChanged event
  • Fires frequently when dragging or animating scene items

Usage Patterns

Recommended Subscription Levels

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)

Custom Subscription Combinations

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)

Performance Considerations

Event Frequency Guide

SubscriptionFrequencyUse Cases
LOW_VOLUMEOccasionalGeneral applications, automation
SCENESLowScene switching apps
INPUTSLow-MediumAudio/video control apps
OUTPUTSLowStreaming/recording monitors
SCENEITEMTRANSFORMCHANGEDHighInteractive scene editors
INPUTACTIVESTATECHANGEDMediumSource monitoring
INPUTVOLUMEMETERSVery HighReal-time audio visualizers

Best Practices

  1. Start with LOW_VOLUME: Most applications don't need high-frequency events
  2. Add specific categories: Only subscribe to events you actually handle
  3. Avoid ALL subscription: Unless building comprehensive OBS control software
  4. Monitor performance: High-volume events can impact application performance
  5. Use filtering: Handle events efficiently in your callbacks

Event Handling Examples

Minimal Event Monitoring

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()

Audio Application

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()

Streaming Dashboard

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()

Scene Editor Events

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

docs

error-handling.md

event-client.md

event-subscriptions.md

index.md

request-client.md

tile.json