or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

error-handling.mdevent-client.mdevent-subscriptions.mdindex.mdrequest-client.md

event-subscriptions.mddocs/

0

# Event Subscriptions

1

2

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.

3

4

## Subscription System

5

6

### Subs Enum

7

8

```python { .api }

9

from enum import IntFlag

10

11

class Subs(IntFlag):

12

# Low-volume event categories (individual flags)

13

GENERAL = 1 << 0 # General events

14

CONFIG = 1 << 1 # Configuration changes

15

SCENES = 1 << 2 # Scene events

16

INPUTS = 1 << 3 # Input events

17

TRANSITIONS = 1 << 4 # Transition events

18

FILTERS = 1 << 5 # Filter events

19

OUTPUTS = 1 << 6 # Output events

20

SCENEITEMS = 1 << 7 # Scene item events

21

MEDIAINPUTS = 1 << 8 # Media input events

22

VENDORS = 1 << 9 # Vendor events

23

UI = 1 << 10 # UI events

24

25

# High-volume event categories (individual flags)

26

INPUTVOLUMEMETERS = 1 << 16 # Volume meter updates (very frequent)

27

INPUTACTIVESTATECHANGED = 1 << 17 # Input active state changes

28

INPUTSHOWSTATECHANGED = 1 << 18 # Input show state changes

29

SCENEITEMTRANSFORMCHANGED = 1 << 19 # Scene item transform changes (frequent)

30

31

# Composite subscription flags

32

LOW_VOLUME = (GENERAL | CONFIG | SCENES | INPUTS | TRANSITIONS |

33

FILTERS | OUTPUTS | SCENEITEMS | MEDIAINPUTS | VENDORS | UI)

34

HIGH_VOLUME = (INPUTVOLUMEMETERS | INPUTACTIVESTATECHANGED |

35

INPUTSHOWSTATECHANGED | SCENEITEMTRANSFORMCHANGED)

36

ALL = LOW_VOLUME | HIGH_VOLUME

37

```

38

39

## Event Categories

40

41

### Low-Volume Events

42

43

These events occur occasionally and are suitable for most applications:

44

45

#### GENERAL (Subs.GENERAL)

46

- General OBS events

47

- ExitStarted

48

- VendorEvent

49

- CustomEvent

50

51

#### CONFIG (Subs.CONFIG)

52

- Configuration changes

53

- CurrentSceneCollectionChanging

54

- CurrentSceneCollectionChanged

55

- SceneCollectionListChanged

56

- CurrentProfileChanging

57

- CurrentProfileChanged

58

- ProfileListChanged

59

60

#### SCENES (Subs.SCENES)

61

- Scene management events

62

- SceneCreated

63

- SceneRemoved

64

- SceneNameChanged

65

- CurrentProgramSceneChanged

66

- CurrentPreviewSceneChanged

67

- SceneListChanged

68

69

#### INPUTS (Subs.INPUTS)

70

- Input management events

71

- InputCreated

72

- InputRemoved

73

- InputNameChanged

74

- InputSettingsChanged

75

- InputMuteStateChanged

76

- InputVolumeChanged

77

78

#### TRANSITIONS (Subs.TRANSITIONS)

79

- Scene transition events

80

- CurrentSceneTransitionChanged

81

- CurrentSceneTransitionDurationChanged

82

- SceneTransitionStarted

83

- SceneTransitionEnded

84

- SceneTransitionVideoEnded

85

86

#### FILTERS (Subs.FILTERS)

87

- Source filter events

88

- SourceFilterCreated

89

- SourceFilterRemoved

90

- SourceFilterNameChanged

91

- SourceFilterSettingsChanged

92

- SourceFilterEnableStateChanged

93

94

#### OUTPUTS (Subs.OUTPUTS)

95

- Output events (streaming, recording)

96

- StreamStateChanged

97

- RecordStateChanged

98

- ReplayBufferStateChanged

99

- VirtualcamStateChanged

100

- ReplayBufferSaved

101

102

#### SCENEITEMS (Subs.SCENEITEMS)

103

- Scene item management events

104

- SceneItemCreated

105

- SceneItemRemoved

106

- SceneItemListReindexed

107

- SceneItemEnableStateChanged

108

- SceneItemLockStateChanged

109

110

#### MEDIAINPUTS (Subs.MEDIAINPUTS)

111

- Media input events

112

- MediaInputPlaybackStarted

113

- MediaInputPlaybackEnded

114

- MediaInputActionTriggered

115

116

#### VENDORS (Subs.VENDORS)

117

- Third-party vendor events

118

- VendorEvent (vendor-specific events)

119

120

#### UI (Subs.UI)

121

- UI-related events

122

- StudioModeStateChanged

123

- ScreenshotSaved

124

125

### High-Volume Events

126

127

These events occur frequently and should be used with caution:

128

129

#### INPUTVOLUMEMETERS (Subs.INPUTVOLUMEMETERS)

130

- Real-time volume level updates for all inputs

131

- InputVolumeMeters event (fires continuously while audio is active)

132

- **Warning**: Very high frequency, can generate hundreds of events per second

133

134

#### INPUTACTIVESTATECHANGED (Subs.INPUTACTIVESTATECHANGED)

135

- Input active state changes

136

- InputActiveStateChanged event

137

- Fires when inputs become active/inactive (e.g., when sources start/stop producing content)

138

139

#### INPUTSHOWSTATECHANGED (Subs.INPUTSHOWSTATECHANGED)

140

- Input show state changes

141

- InputShowStateChanged event

142

- Fires when inputs become visible/hidden in scenes

143

144

#### SCENEITEMTRANSFORMCHANGED (Subs.SCENEITEMTRANSFORMCHANGED)

145

- Scene item transform changes

146

- SceneItemTransformChanged event

147

- Fires frequently when dragging or animating scene items

148

149

## Usage Patterns

150

151

### Recommended Subscription Levels

152

153

```python

154

import obsws_python as obs

155

156

# Most applications - low-volume events only

157

client = obs.EventClient(subs=obs.Subs.LOW_VOLUME)

158

159

# Specific categories only

160

client = obs.EventClient(subs=obs.Subs.SCENES | obs.Subs.INPUTS)

161

162

# All events (use carefully)

163

client = obs.EventClient(subs=obs.Subs.ALL)

164

165

# No events (request-only mode)

166

client = obs.EventClient(subs=0)

167

```

168

169

### Custom Subscription Combinations

170

171

```python

172

import obsws_python as obs

173

174

# Scene and input events only

175

scene_input_subs = obs.Subs.SCENES | obs.Subs.INPUTS

176

client = obs.EventClient(subs=scene_input_subs)

177

178

# Low-volume events plus transform changes

179

interactive_subs = obs.Subs.LOW_VOLUME | obs.Subs.SCENEITEMTRANSFORMCHANGED

180

client = obs.EventClient(subs=interactive_subs)

181

182

# Streaming application - outputs and scenes

183

streaming_subs = obs.Subs.OUTPUTS | obs.Subs.SCENES | obs.Subs.GENERAL

184

client = obs.EventClient(subs=streaming_subs)

185

186

# Audio monitoring - inputs and volume meters

187

audio_subs = obs.Subs.INPUTS | obs.Subs.INPUTVOLUMEMETERS

188

client = obs.EventClient(subs=audio_subs)

189

```

190

191

## Performance Considerations

192

193

### Event Frequency Guide

194

195

| Subscription | Frequency | Use Cases |

196

|-------------|-----------|-----------|

197

| `LOW_VOLUME` | Occasional | General applications, automation |

198

| `SCENES` | Low | Scene switching apps |

199

| `INPUTS` | Low-Medium | Audio/video control apps |

200

| `OUTPUTS` | Low | Streaming/recording monitors |

201

| `SCENEITEMTRANSFORMCHANGED` | High | Interactive scene editors |

202

| `INPUTACTIVESTATECHANGED` | Medium | Source monitoring |

203

| `INPUTVOLUMEMETERS` | Very High | Real-time audio visualizers |

204

205

### Best Practices

206

207

1. **Start with LOW_VOLUME**: Most applications don't need high-frequency events

208

2. **Add specific categories**: Only subscribe to events you actually handle

209

3. **Avoid ALL subscription**: Unless building comprehensive OBS control software

210

4. **Monitor performance**: High-volume events can impact application performance

211

5. **Use filtering**: Handle events efficiently in your callbacks

212

213

## Event Handling Examples

214

215

### Minimal Event Monitoring

216

217

```python

218

import obsws_python as obs

219

220

# Only scene changes - very lightweight

221

client = obs.EventClient(subs=obs.Subs.SCENES)

222

223

def on_current_program_scene_changed(data):

224

print(f"Scene changed to: {data.scene_name}")

225

226

client.callback.register(on_current_program_scene_changed)

227

228

input("Monitoring scene changes only...\n")

229

client.disconnect()

230

```

231

232

### Audio Application

233

234

```python

235

import obsws_python as obs

236

237

# Audio-focused events

238

audio_subs = obs.Subs.INPUTS | obs.Subs.INPUTVOLUMEMETERS

239

client = obs.EventClient(subs=audio_subs)

240

241

volume_count = 0

242

243

def on_input_mute_state_changed(data):

244

print(f"Mute changed: {data.input_name} = {data.input_muted}")

245

246

def on_input_volume_changed(data):

247

print(f"Volume changed: {data.input_name} = {data.input_volume_db}dB")

248

249

def on_input_volume_meters(data):

250

global volume_count

251

volume_count += 1

252

253

# Only log every 50 volume updates to avoid spam

254

if volume_count % 50 == 0:

255

inputs_with_audio = [name for name, levels in data.inputs.items()

256

if any(level > -60 for level in levels)]

257

if inputs_with_audio:

258

print(f"Audio detected in: {', '.join(inputs_with_audio)}")

259

260

client.callback.register([

261

on_input_mute_state_changed,

262

on_input_volume_changed,

263

on_input_volume_meters

264

])

265

266

print("Audio monitoring active (includes volume meters)")

267

input("Press Enter to stop...\n")

268

client.disconnect()

269

```

270

271

### Streaming Dashboard

272

273

```python

274

import obsws_python as obs

275

from datetime import datetime

276

277

# Events relevant for streaming dashboard

278

dashboard_subs = (obs.Subs.SCENES | obs.Subs.OUTPUTS |

279

obs.Subs.INPUTS | obs.Subs.GENERAL)

280

client = obs.EventClient(subs=dashboard_subs)

281

282

def log_with_time(message):

283

timestamp = datetime.now().strftime("%H:%M:%S")

284

print(f"[{timestamp}] {message}")

285

286

def on_current_program_scene_changed(data):

287

log_with_time(f"🎬 Scene: {data.scene_name}")

288

289

def on_stream_state_changed(data):

290

if data.output_active:

291

log_with_time("πŸ”΄ Stream STARTED")

292

else:

293

log_with_time("⚫ Stream STOPPED")

294

295

def on_record_state_changed(data):

296

if data.output_active:

297

log_with_time("πŸ“Ή Recording STARTED")

298

else:

299

log_with_time("⏹️ Recording STOPPED")

300

301

def on_input_mute_state_changed(data):

302

emoji = "πŸ”‡" if data.input_muted else "πŸ”Š"

303

log_with_time(f"{emoji} {data.input_name}")

304

305

client.callback.register([

306

on_current_program_scene_changed,

307

on_stream_state_changed,

308

on_record_state_changed,

309

on_input_mute_state_changed

310

])

311

312

log_with_time("Streaming dashboard monitoring started")

313

input("Press Enter to stop...\n")

314

client.disconnect()

315

```

316

317

### Scene Editor Events

318

319

```python

320

import obsws_python as obs

321

322

# Scene editing with high-frequency transform events

323

editor_subs = (obs.Subs.SCENES | obs.Subs.SCENEITEMS |

324

obs.Subs.SCENEITEMTRANSFORMCHANGED)

325

client = obs.EventClient(subs=editor_subs)

326

327

transform_updates = {}

328

329

def on_scene_item_created(data):

330

print(f"βž• Item created: {data.source_name} in {data.scene_name}")

331

332

def on_scene_item_removed(data):

333

print(f"βž– Item removed: {data.source_name} from {data.scene_name}")

334

335

def on_scene_item_transform_changed(data):

336

# Track transform updates per item

337

item_key = f"{data.scene_name}:{data.scene_item_id}"

338

transform_updates[item_key] = transform_updates.get(item_key, 0) + 1

339

340

# Log every 10 updates per item

341

if transform_updates[item_key] % 10 == 0:

342

print(f"πŸ”„ Transform updates for item {data.scene_item_id}: {transform_updates[item_key]}")

343

344

def on_scene_item_enable_state_changed(data):

345

state = "enabled" if data.scene_item_enabled else "disabled"

346

print(f"πŸ‘οΈ Item {data.scene_item_id} {state}")

347

348

client.callback.register([

349

on_scene_item_created,

350

on_scene_item_removed,

351

on_scene_item_transform_changed,

352

on_scene_item_enable_state_changed

353

])

354

355

print("Scene editor monitoring active (includes transform changes)")

356

print("Move scene items around to see transform events...")

357

input("Press Enter to stop...\n")

358

client.disconnect()

359

360

# Show final transform update counts

361

if transform_updates:

362

print("\nFinal transform update counts:")

363

for item, count in transform_updates.items():

364

print(f" {item}: {count} updates")

365

```