-
Notifications
You must be signed in to change notification settings - Fork 105
Scripting
This section will describe how to use the scripting API to add custom macro conditions and actions.
The API is not limited to scripts or Python, but the examples showcased here will only be using Python for brevity.
This examples shows how to register a new condition type which will randomly evaluate to true based on provided user input percentage in the range from 0 to 100:
import obspython as obs
import threading # Required by advss helpers
import random
CONDITION_NAME = "Random condition"
###############################################################################
# This function will define the UI for the custom condition type based on a obs_properties object.
# In this case only a single float selection field for specifying the probability of returning true.
# This isn't mandatory.
# You can also have a condition without any additional UI elements.
###############################################################################
def get_condition_properties():
props = obs.obs_properties_create()
obs.obs_properties_add_float(
props, "probability", "Probability of returning true", 0, 100, 0.1
)
return props
###############################################################################
# You can provide default values for each of the settings you have defined earlier.
# This isn't mandatory.
# You can also have a condition without any settings to be modified.
###############################################################################
def get_condition_defaults():
default_settings = obs.obs_data_create()
obs.obs_data_set_default_double(default_settings, "probability", 33.3)
return default_settings
###############################################################################
# This function will be used by the advanced scene switcher to determine if a condition evaluates to true or false.
# The settings for each instance of this condition type will be passed via the data parameter.
###############################################################################
def my_python_condition(data):
target = obs.obs_data_get_double(data, "probability")
value = random.uniform(0, 100)
return value <= target
###############################################################################
# Let's register the new condition type
###############################################################################
def script_load(settings):
advss_register_condition(
CONDITION_NAME,
my_python_condition,
get_condition_properties,
get_condition_defaults(),
)
###############################################################################
# Deregistering is useful if you plan unloading the script files
###############################################################################
def script_unload():
advss_deregister_condition(CONDITION_NAME)
###############################################################################
########################### boilerplate code below ############################
###############################################################################
This is the custom condition type we defined with this script in action:

As you can see the frequency at which this condition returns true depends on the provided input value, just as we expect it to.
Registering an action would be identical to the example above, but instead of passing a function which returns a boolean value to advss_register_condition, you would pass a function performing your desired actions to advss_register_action.
The boilerplate code mentioned above can be found here for Python and Lua.
Usually you can just copy it directly into your script without any modifications.
Note that if you should choose to unload the scripts, which define custom macro segments, while custom macro segments are still in use, the plugin will no longer be able to query settings of those custom macro segments.
If such a state should be saved (e.g. because OBS was closed with the script no longer being loaded) the plugin will instead replace the custom macro segments with macro segments of type Unknown.
Even if you should choose to reload the script at a later point in time the settings for those Unknown macro segments will be lost and you will have to reconfigure them.
The advanced scene switcher offers the following procedure handlers:
bool advss_register_script_action(in string name, in ptr default_settings, out string properties_signal_name, out string trigger_signal_name)bool advss_register_script_condition(in string name, in ptr default_settings, out string properties_signal_name, out string trigger_signal_name)bool advss_deregister_script_action(in string name)bool advss_deregister_script_condition(in string name)bool advss_get_variable_value(in string name, out string value)bool advss_set_variable_value(in string name, in string value)
The name field of calldata object associated with this procedure should specify the id of the action type you want to register.
It will also be the user facing name in the action type selection.
The name field of calldata object associated with this procedure should specify the a pointer to an obs_data_t object.
It should contain the default values for the settings for your custom action type.
The ownership and thus responsibility to free this obs_data_t* pointer will be that of the advanced scene switcher.
Thus you must not free / release this pointer yourself or you risk a crash of OBS.
This value can be null, if you do not which to provide any default settings.
The properties_signal_name field of calldata object associated with this procedure will specify the name of the signal, which will be called by the advanced scene switcher, when it requests a new obs_properties_t object.
These objects are used to determine which settings UI elements should be shown to the user when creating an instance of your custom action type.
The signal will be registered by the advanced scene switcher.
You only have to connect to it.
When the signal is called by the advanced scene switcher you will have to pass the pointer to the obs_properties_t object you created via calldata_set_ptr in the field named properties.
You can ignore this field, if you do not wish to provide any controls to the user to modify the settings of this action type.
The trigger_signal_name field of calldata object associated with this procedure will specify the name of the signal, which will be called by the advanced scene switcher, when your custom action type needs to be executed.
The signal will be registered by the advanced scene switcher.
You only have to connect to it.
In the following section trigger_signal_name is just a placeholder for the actual signal name.
When trigger_signal_name is called by the advanced scene switcher, the settings for the instance of this action type will be passed as a pointer to an obs_data_t object.
You can access it via calldata_ptr in the settings field of calldata object associated with this procedure.
When trigger_signal_name is called by the advanced scene switcher you will have to pass the result of your operation via calldata_set_bool in the field named result.
In case of a macro action this should always be true unless a catastrophic error occurred which should abort the whole macro's execution.
When trigger_signal_name is called by the advanced scene switcher it will pass completion_id field, which is a unique id for each instance of your custom action being triggered.
When trigger_signal_name is called by the advanced scene switcher it will also pass the name of the signal you will to emit when your action type's operation is done in the completion_signal_name field.
When you emit this completion signal you will also have to pass the completion_id value you have received via trigger_signal_name using calldata_set_int.
The signal will be registered by the advanced scene switcher.
You only have to emit it.
The return value can be queried via success from the calldata object associated with this procedure.
Returns true, if the operation was successful, and false otherwise.
def advss_register_action_type(name, callback, get_properties, default_settings):
proc_handler = obs.obs_get_proc_handler()
data = obs.calldata_create()
obs.calldata_set_string(data, "name", name)
obs.calldata_set_ptr(data, "default_settings", default_settings)
obs.proc_handler_call(proc_handler, "advss_register_script_action", data)
success = obs.calldata_bool(data, "success")
if success == False:
obs.script_log(obs.LOG_WARNING, f'failed to register custom action "{name}"')
obs.calldata_destroy(data)
return
# Run in separate thread to avoid blocking main OBS signal handler.
# Operation completion will be indicated via signal completion_signal_name.
def run_helper(data):
completion_signal_name = obs.calldata_string(data, "completion_signal_name")
id = obs.calldata_int(data, "completion_id")
def thread_func(settings):
settings = obs.obs_data_create_from_json(
obs.calldata_string(data, "settings")
)
callback(settings)
reply_data = obs.calldata_create()
obs.calldata_set_int(reply_data, "completion_id", id)
obs.calldata_set_bool(reply_data, "result", True)
signal_handler = obs.obs_get_signal_handler()
obs.signal_handler_signal(
signal_handler, completion_signal_name, reply_data
)
obs.obs_data_release(settings)
obs.calldata_destroy(reply_data)
threading.Thread(target=thread_func, args={data}).start()
def properties_helper(data):
if get_properties is not None:
properties = get_properties()
else:
properties = None
obs.calldata_set_ptr(data, "properties", properties)
trigger_signal_name = obs.calldata_string(data, "trigger_signal_name")
property_signal_name = obs.calldata_string(data, "properties_signal_name")
signal_handler = obs.obs_get_signal_handler()
obs.signal_handler_connect(signal_handler, trigger_signal_name, run_helper)
obs.signal_handler_connect(signal_handler, property_signal_name, properties_helper)
obs.calldata_destroy(data)
This is almost identical to advss_register_script_action with the only difference being the handling of the result field.
The name field of calldata object associated with this procedure should specify the id of the condition type you want to register.
It will also be the user facing name in the condition type selection.
The name field of calldata object associated with this procedure should specify the a pointer to an obs_data_t object.
It should contain the default values for the settings for your custom condition type.
The ownership and thus responsibility to free this obs_data_t* pointer will be that of the advanced scene switcher.
Thus you must not free / release this pointer yourself or you risk a crash of OBS.
This value can be null, if you do not which to provide any default settings.
The properties_signal_name field of calldata object associated with this procedure will specify the name of the signal, which will be called by the advanced scene switcher, when it requests a new obs_properties_t object.
These objects are used to determine which settings UI elements should be shown to the user when creating an instance of your custom condition type.
The signal will be registered by the advanced scene switcher.
You only have to connect to it.
When the signal is called by the advanced scene switcher you will have to pass the pointer to the obs_properties_t object you created via calldata_set_ptr in the field named properties.
You can ignore this field, if you do not wish to provide any controls to the user to modify the settings of this condition type.
The trigger_signal_name field of calldata object associated with this procedure will specify the name of the signal, which will be called by the advanced scene switcher, when your custom condition check needs to be executed.
The signal will be registered by the advanced scene switcher.
You only have to connect to it.
In the following section trigger_signal_name is just a placeholder for the actual signal name.
When trigger_signal_name is called by the advanced scene switcher, the settings for the instance of this condition type will be passed as a pointer to an obs_data_t object.
You can access it via calldata_ptr in the settings field of calldata object associated with this procedure.
When trigger_signal_name is called by the advanced scene switcher you will have to pass the result of your condition check via calldata_set_bool in the field named result.
When trigger_signal_name is called by the advanced scene switcher it will pass completion_id field, which is a unique id for each instance of your custom condition being triggered.
When trigger_signal_name is called by the advanced scene switcher it will also pass the name of the signal you will to emit when your condition type's operation is done in the completion_signal_name field.
When you emit this completion signal you will also have to pass the completion_id value you have received via trigger_signal_name using calldata_set_int.
The signal will be registered by the advanced scene switcher.
You only have to emit it.
def advss_register_condition_type(name, callback, get_properties, default_settings):
proc_handler = obs.obs_get_proc_handler()
data = obs.calldata_create()
obs.calldata_set_string(data, "name", name)
obs.calldata_set_ptr(data, "default_settings", default_settings)
obs.proc_handler_call(proc_handler, "advss_register_script_condition", data)
success = obs.calldata_bool(data, "success")
if success == False:
obs.script_log(obs.LOG_WARNING, f'failed to register custom condition "{name}"')
obs.calldata_destroy(data)
return
# Run in separate thread to avoid blocking main OBS signal handler.
# Operation completion will be indicated via signal completion_signal_name.
def run_helper(data):
completion_signal_name = obs.calldata_string(data, "completion_signal_name")
id = obs.calldata_int(data, "completion_id")
def thread_func(settings):
settings = obs.obs_data_create_from_json(
obs.calldata_string(data, "settings")
)
callback_result = callback(settings)
reply_data = obs.calldata_create()
obs.calldata_set_int(reply_data, "completion_id", id)
obs.calldata_set_bool(reply_data, "result", callback_result)
signal_handler = obs.obs_get_signal_handler()
obs.signal_handler_signal(
signal_handler, completion_signal_name, reply_data
)
obs.obs_data_release(settings)
obs.calldata_destroy(reply_data)
threading.Thread(target=thread_func, args={data}).start()
def properties_helper(data):
if get_properties is not None:
properties = get_properties()
else:
properties = None
obs.calldata_set_ptr(data, "properties", properties)
trigger_signal_name = obs.calldata_string(data, "trigger_signal_name")
property_signal_name = obs.calldata_string(data, "properties_signal_name")
signal_handler = obs.obs_get_signal_handler()
obs.signal_handler_connect(signal_handler, trigger_signal_name, run_helper)
obs.signal_handler_connect(signal_handler, property_signal_name, properties_helper)
obs.calldata_destroy(data)
The return value can be queried via success from the calldata object associated with this procedure.
Returns true, if the operation was successful, and false otherwise.
The name field of calldata object associated with this procedure should specify the id of the action type you want to deregister.
It will also be the user facing name in the condition type selection.
The return value can be queried via success from the calldata object associated with this procedure.
Returns true, if the operation was successful, and false otherwise.
def advss_deregister_action(name):
proc_handler = obs.obs_get_proc_handler()
data = obs.calldata_create()
obs.calldata_set_string(data, "name", name)
obs.proc_handler_call(proc_handler, "advss_deregister_script_action", data)
success = obs.calldata_bool(data, "success")
if success == False:
obs.script_log(obs.LOG_WARNING, f'failed to deregister custom action"{name}"')
obs.calldata_destroy(data)
This is identical to advss_deregister_script_action.
The name field of calldata object associated with this procedure should specify the id of the condition type you want to deregister.
The return value can be queried via success from the calldata object associated with this procedure.
Returns true, if the operation was successful, and false otherwise.
def advss_deregister_condition(name):
proc_handler = obs.obs_get_proc_handler()
data = obs.calldata_create()
obs.calldata_set_string(data, "name", name)
obs.proc_handler_call(proc_handler, "advss_deregister_script_condition", data)
success = obs.calldata_bool(data, "success")
if success == False:
obs.script_log(obs.LOG_WARNING, f'failed to deregister custom condition "{name}"')
obs.calldata_destroy(data)
The name field of calldata object associated with this procedure should specify the id of the name of the variable for which you want to get the current value.
The value field of calldata object associated with this procedure will contain the value of the specified variable, if the operation was successful.
The return value can be queried via success from the calldata object associated with this procedure.
Returns true, if the operation was successful, and false otherwise.
def advss_get_variable_value(name):
proc_handler = obs.obs_get_proc_handler()
data = obs.calldata_create()
obs.calldata_set_string(data, "name", name)
obs.proc_handler_call(proc_handler, "advss_get_variable_value", data)
success = obs.calldata_bool(data, "success")
if success == False:
obs.script_log(obs.LOG_WARNING, f'failed to get value for variable "{name}"')
obs.calldata_destroy(data)
return None
value = obs.calldata_string(data, "value")
obs.calldata_destroy(data)
return value
The name field of calldata object associated with this procedure should specify the id of the name of the variable for which you want to change the value.
The value field of calldata object associated with this procedure should specify the value you want to set for the specified variable.
The return value can be queried via success from the calldata object associated with this procedure.
Returns true, if the operation was successful, and false otherwise.
def advss_set_variable_value(name, value):
proc_handler = obs.obs_get_proc_handler()
data = obs.calldata_create()
obs.calldata_set_string(data, "name", name)
obs.calldata_set_string(data, "value", value)
obs.proc_handler_call(proc_handler, "advss_set_variable_value", data)
success = obs.calldata_bool(data, "success")
if success == False:
obs.script_log(obs.LOG_WARNING, f'failed to set value for variable "{name}"')
obs.calldata_destroy(data)
return success
- Installation
- Show webcam only when speaking
- Twitch Category Changer
- Hotkeys to control counter in text source (e.g. death or win counter)
- Show text source with latest Twitch follower
- Detect elements on screen and hide them automatically
- Motion detection
- Start other programs when starting OBS
- Crossfading audio during scene changes
- Looping a set of media sources
- Switch scenes randomly
- Re-shuffle VLC source
- Automatically switch scene if a game capture's target window no longer exists
- Audio based scene switching in podcast setting
- Switching scenes based on portrait or landscape mode resolution of a window capture source
- Set up a hotkey to start and stop recording with a fade from and to black
- Automatically cycle through a list of scenes
- Toggle visibility of scene items on a timer
- Advance through a list of scenes by hotkey
- Performing actions only when transitioning from A to B
- Media playlist with commercial interruptions
- Split recording of stream into chunks
- Switching scenes for Aitum Vertical plugin
- Using MIDI devices
- Controlling audio source volume using MIDI devices
- Change capture window of Window Capture source
- Show URLs in clipboard in browser source
- League of Legends process based scene swtich
- Push-to-show source
- General tab overview
- Starting and stopping the plugin
- Macros explained
- Macro tab overview
- Creating a macro
- Pausing macros
- Macro duration modifiers
- Macro docks
- Exporting and importing individual macros
- Audio condition
- Cursor condition
- Date condition
- Hotkey condition
- Media condition
- Process condition
- Scene item transform condition
- Slide Show condition
- Video condition
- Audio action
- Http action
- Hotkey action
- Random action
- Scene item visibility
- Sequence action
- Action Queue example
- Variables
- Macro properties
- Websockets
- Scripting
- Troubleshooting
- Saving and loading settings