diff --git a/.gitignore b/.gitignore index bf1ec86..7e6985d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,8 @@ __pycache__ obsstudio_sdk.egg-info dist docs -setup.py \ No newline at end of file +setup.py + +venv +quick.py +config.toml \ No newline at end of file diff --git a/README.md b/README.md index 92e1fc3..ff0d837 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # obs_sdk + ### A Python SDK for OBS Studio WebSocket v5.0 -This is a wrapper around OBS Websocket. +This is a wrapper around OBS Websocket. Not all endpoints in the official documentation are implemented. But all endpoints in the Requests section is implemented. You can find the relevant document using below link. [obs-websocket github page](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#Requests) @@ -11,14 +12,26 @@ Not all endpoints in the official documentation are implemented. But all endpoin pip install obsstudio-sdk ``` - ### How to Use -* Import and start using - Required parameters are as follows: - host: obs websocket server - port: port to access server - password: obs websocket server password +- Load connection info from toml config. A valid `config.toml` might look like this: + +```toml +[connection] +host = "localhost" +port = 4455 +password = "mystrongpass" +``` + +It should be placed next to your `__main__.py` file. + +Otherwise: + +- Import and start using + Parameters are as follows: + host: obs websocket server + port: port to access server + password: obs websocket server password ``` >>>from obsstudio_sdk.reqs import ReqClient @@ -26,12 +39,12 @@ pip install obsstudio-sdk >>>client = ReqClient('192.168.1.1', 4444, 'somepassword') ``` -Now you can make calls to OBS +Now you can make calls to OBS -Example: Toggle the mute state of your Mic input +Example: Toggle the mute state of your Mic input ``` >>>cl.ToggleInputMute('Mic/Aux') >>> -``` \ No newline at end of file +``` diff --git a/build/lib/obsstudio_sdk/__init__.py b/build/lib/obsstudio_sdk/__init__.py new file mode 100644 index 0000000..7c892fc --- /dev/null +++ b/build/lib/obsstudio_sdk/__init__.py @@ -0,0 +1,4 @@ +from .events import EventsClient +from .reqs import ReqClient + +__ALL__ = ["ReqClient", "EventsClient"] diff --git a/build/lib/obsstudio_sdk/baseclient.py b/build/lib/obsstudio_sdk/baseclient.py new file mode 100644 index 0000000..cc403f8 --- /dev/null +++ b/build/lib/obsstudio_sdk/baseclient.py @@ -0,0 +1,71 @@ +import base64 +import hashlib +import json +from pathlib import Path +from random import randint + +import tomllib +import websocket + + +class ObsClient(object): + def __init__(self, host=None, port=None, password=None): + self.host = host + self.port = port + self.password = password + if not (self.host and self.port and self.password): + conn = self._conn_from_toml() + self.host = conn["host"] + self.port = conn["port"] + self.password = conn["password"] + self.ws = websocket.WebSocket() + self.ws.connect(f"ws://{self.host}:{self.port}") + self.server_hello = json.loads(self.ws.recv()) + + def _conn_from_toml(self): + filepath = Path.cwd() / "config.toml" + self._conn = dict() + with open(filepath, "rb") as f: + self._conn = tomllib.load(f) + return self._conn["connection"] + + def authenticate(self): + secret = base64.b64encode( + hashlib.sha256( + ( + self.password + self.server_hello["d"]["authentication"]["salt"] + ).encode() + ).digest() + ) + + auth = base64.b64encode( + hashlib.sha256( + ( + secret.decode() + + self.server_hello["d"]["authentication"]["challenge"] + ).encode() + ).digest() + ).decode() + + payload = {"op": 1, "d": {"rpcVersion": 1, "authentication": auth}} + + self.ws.send(json.dumps(payload)) + return self.ws.recv() + + def req(self, req_type, req_data=None): + if req_data: + payload = { + "op": 6, + "d": { + "requestType": req_type, + "requestId": randint(1, 1000), + "requestData": req_data, + }, + } + else: + payload = { + "op": 6, + "d": {"requestType": req_type, "requestId": randint(1, 1000)}, + } + self.ws.send(json.dumps(payload)) + return json.loads(self.ws.recv()) diff --git a/build/lib/obsstudio_sdk/events.py b/build/lib/obsstudio_sdk/events.py new file mode 100644 index 0000000..3e007b0 --- /dev/null +++ b/build/lib/obsstudio_sdk/events.py @@ -0,0 +1,43 @@ +import json +import time +from threading import Thread + +from .baseclient import ObsClient +from .subject import Callback + +""" +A class to interact with obs-websocket events +defined in official github repo +https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events +""" + + +class EventsClient(object): + DELAY = 0.001 + + def __init__(self, **kwargs): + self.base_client = ObsClient(**kwargs) + self.base_client.authenticate() + self.callback = Callback() + + self.running = True + worker = Thread(target=self.trigger, daemon=True) + worker.start() + + def trigger(self): + """ + Continuously listen for events. + + Triggers a callback on event received. + """ + while self.running: + self.data = json.loads(self.base_client.ws.recv()) + event, data = (self.data["d"].get("eventType"), self.data["d"]) + self.callback.trigger(event, data) + time.sleep(self.DELAY) + + def unsubscribe(self): + """ + stop listening for events + """ + self.running = False diff --git a/build/lib/obsstudio_sdk/reqs.py b/build/lib/obsstudio_sdk/reqs.py new file mode 100644 index 0000000..924682e --- /dev/null +++ b/build/lib/obsstudio_sdk/reqs.py @@ -0,0 +1,1928 @@ +from .baseclient import ObsClient + +""" +A class to interact with obs-websocket requests +defined in official github repo +https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#Requests +""" + + +class ReqClient(object): + def __init__(self, **kwargs): + self.base_client = ObsClient(**kwargs) + self.base_client.authenticate() + + def GetVersion(self): + """ + Gets data about the current plugin and RPC version. + + :return: The version info as a dictionary + :rtype: dict + + + """ + response = self.base_client.req("GetVersion") + return response + + def GetStats(self): + """ + Gets statistics about OBS, obs-websocket, and the current session. + + :return: The stats info as a dictionary + :rtype: dict + + + """ + response = self.base_client.req("GetStats") + return response + + def BroadcastCustomEvent(self, eventData): + """ + Broadcasts a CustomEvent to all WebSocket clients. Receivers are clients which are identified and subscribed. + + :param eventData: Data payload to emit to all receivers + :type eventData: object + :return: empty response + :rtype: str + + + """ + req_data = eventData + response = self.base_client.req("BroadcastCustomEvent", req_data) + return response + + def CallVendorRequest(self, vendorName, requestType, requestData=None): + """ + Call a request registered to a vendor. + + A vendor is a unique name registered by a + third-party plugin or script, which allows + for custom requests and events to be added + to obs-websocket. If a plugin or script + implements vendor requests or events, + documentation is expected to be provided with them. + + :param vendorName: Name of the vendor to use + :type vendorName: str + :param requestType: The request type to call + :type requestType: str + :param requestData: Object containing appropriate request data + :type requestData: dict, optional + :return: responseData + :rtype: dict + + + """ + response = self.base_client.req(req_type=requestType, req_data=requestData) + return response + + def GetHotkeyList(self): + """ + Gets an array of all hotkey names in OBS + + :return: hotkeys + :rtype: list[str] + + + """ + response = self.base_client.req("GetHotkeyList") + return response + + def TriggerHotkeyByName(self, hotkeyName): + """ + Triggers a hotkey using its name. For hotkey names + See GetHotkeyList + + :param hotkeyName: Name of the hotkey to trigger + :type hotkeyName: str + + + """ + payload = {"hotkeyName": hotkeyName} + response = self.base_client.req("TriggerHotkeyByName", payload) + return response + + def TriggerHotkeyByKeySequence( + self, keyId, pressShift, pressCtrl, pressAlt, pressCmd + ): + """ + Triggers a hotkey using a sequence of keys. + + :param keyId: The OBS key ID to use. See https://github.com/obsproject/obs-studio/blob/master/libobs/obs-hotkeys.h + :type keyId: str + :param keyModifiers: Object containing key modifiers to apply. + :type keyModifiers: dict + :param keyModifiers.shift: Press Shift + :type keyModifiers.shift: bool + :param keyModifiers.control: Press CTRL + :type keyModifiers.control: bool + :param keyModifiers.alt: Press ALT + :type keyModifiers.alt: bool + :param keyModifiers.cmd: Press CMD (Mac) + :type keyModifiers.cmd: bool + + + """ + payload = { + "keyId": keyId, + "keyModifiers": { + "shift": pressShift, + "control": pressCtrl, + "alt": pressAlt, + "cmd": pressCmd, + }, + } + + response = self.base_client.req("TriggerHotkeyByKeySequence", payload) + return response + + def Sleep(self, sleepMillis=None, sleepFrames=None): + """ + Sleeps for a time duration or number of frames. + Only available in request batches with types SERIAL_REALTIME or SERIAL_FRAME + + :param sleepMillis: Number of milliseconds to sleep for (if SERIAL_REALTIME mode) 0 <= sleepMillis <= 50000 + :type sleepMillis: int + :param sleepFrames: Number of frames to sleep for (if SERIAL_FRAME mode) 0 <= sleepFrames <= 10000 + :type sleepFrames: int + + + """ + payload = {"sleepMillis": sleepMillis, "sleepFrames": sleepFrames} + response = self.base_client.req("Sleep", payload) + return response + + def GetPersistentData(self, realm, slotName): + """ + Gets the value of a "slot" from the selected persistent data realm. + + :param realm: The data realm to select + OBS_WEBSOCKET_DATA_REALM_GLOBAL or OBS_WEBSOCKET_DATA_REALM_PROFILE + :type realm: str + :param slotName: The name of the slot to retrieve data from + :type slotName: str + :return: slotValue Value associated with the slot + :rtype: any + + + """ + payload = {"realm": realm, "slotName": slotName} + response = self.base_client.req("GetPersistentData", payload) + return response + + def SetPersistentData(self, realm, slotName, slotValue): + """ + Sets the value of a "slot" from the selected persistent data realm. + + :param realm: The data realm to select. + OBS_WEBSOCKET_DATA_REALM_GLOBAL or OBS_WEBSOCKET_DATA_REALM_PROFILE + :type realm: str + :param slotName: The name of the slot to retrieve data from + :type slotName: str + :param slotValue: The value to apply to the slot + :type slotValue: any + + + """ + payload = {"realm": realm, "slotName": slotName, "slotValue": slotValue} + response = self.base_client.req("SetPersistentData", payload) + return response + + def GetSceneCollectionList(self): + """ + Gets an array of all scene collections + + :return: sceneCollections + :rtype: list[str] + + + """ + response = self.base_client.req("GetSceneCollectionList") + return response + + def SetCurrentSceneCollection(self, name): + """ + Creates a new scene collection, switching to it in the process + Note: This will block until the collection has finished changing + + :param name: Name of the scene collection to switch to + :type name: str + + + """ + payload = {"sceneCollectionName": name} + response = self.base_client.req("SetCurrentSceneCollection", payload) + return response + + def CreateSceneCollection(self, name): + """ + Creates a new scene collection, switching to it in the process. + Note: This will block until the collection has finished changing. + + :param name: Name for the new scene collection + :type name: str + + + """ + payload = {"sceneCollectionName": name} + response = self.base_client.req("CreateSceneCollection", payload) + return response + + def GetProfileList(self): + """ + Gets a list of all profiles + + :return: profiles (List of all profiles) + :rtype: list[str] + + + """ + response = self.base_client.req("GetProfileList") + return response + + def SetCurrentProfile(self, name): + """ + Switches to a profile + + :param name: Name of the profile to switch to + :type name: str + + + """ + payload = {"profileName": name} + response = self.base_client.req("SetCurrentProfile", payload) + return response + + def CreateProfile(self, name): + """ + Creates a new profile, switching to it in the process + + :param name: Name for the new profile + :type name: str + + + """ + payload = {"profileName": name} + response = self.base_client.req("CreateProfile", payload) + return response + + def RemoveProfile(self, name): + """ + Removes a profile. If the current profile is chosen, + it will change to a different profile first. + + :param name: Name of the profile to remove + :type name: str + + + """ + payload = {"profileName": name} + response = self.base_client.req("RemoveProfile", payload) + return response + + def GetProfileParameter(self, category, name): + """ + Gets a parameter from the current profile's configuration.. + + :param category: Category of the parameter to get + :type category: str + :param name: Name of the parameter to get + :type name: str + + :return: Value and default value for the parameter + :rtype: str + + + """ + payload = {"parameterCategory": category, "parameterName": name} + response = self.base_client.req("GetProfileParameter", payload) + return response + + def SetProfileParameter(self, category, name, value): + """ + Gets a parameter from the current profile's configuration.. + + :param category: Category of the parameter to set + :type category: str + :param name: Name of the parameter to set + :type name: str + :param value: Value of the parameter to set. Use null to delete + :type value: str + + :return: Value and default value for the parameter + :rtype: str + + + """ + payload = { + "parameterCategory": category, + "parameterName": name, + "parameterValue": value, + } + response = self.base_client.req("SetProfileParameter", payload) + return response + + def GetVideoSettings(self): + """ + Gets the current video settings. + Note: To get the true FPS value, divide the FPS numerator by the FPS denominator. + Example: 60000/1001 + + + """ + response = self.base_client.req("GetVideoSettings") + return response + + def SetVideoSettings( + self, numerator, denominator, base_width, base_height, out_width, out_height + ): + """ + Sets the current video settings. + Note: Fields must be specified in pairs. + For example, you cannot set only baseWidth without needing to specify baseHeight. + + :param numerator: Numerator of the fractional FPS value >=1 + :type numerator: int + :param denominator: Denominator of the fractional FPS value >=1 + :type denominator: int + :param base_width: Width of the base (canvas) resolution in pixels (>= 1, <= 4096) + :type base_width: int + :param base_height: Height of the base (canvas) resolution in pixels (>= 1, <= 4096) + :type base_height: int + :param out_width: Width of the output resolution in pixels (>= 1, <= 4096) + :type out_width: int + :param out_height: Height of the output resolution in pixels (>= 1, <= 4096) + :type out_height: int + + + """ + payload = { + "fpsNumerator": numerator, + "fpsDenominator": denominator, + "baseWidth": base_width, + "baseHeight": base_height, + "outputWidth": out_width, + "outputHeight": out_height, + } + response = self.base_client.req("SetVideoSettings", payload) + return response + + def GetStreamServiceSettings(self): + """ + Gets the current stream service settings (stream destination). + + + """ + response = self.base_client.req("GetStreamServiceSettings") + return response + + def SetStreamServiceSettings(self, ss_type, ss_settings): + """ + Sets the current stream service settings (stream destination). + Note: Simple RTMP settings can be set with type rtmp_custom + and the settings fields server and key. + + :param ss_type: Type of stream service to apply. Example: rtmp_common or rtmp_custom + :type ss_type: string + :param ss_setting: Settings to apply to the service + :type ss_setting: dict + + + """ + payload = { + "streamServiceType": ss_type, + "streamServiceSettings": ss_settings, + } + response = self.base_client.req("SetStreamServiceSettings", payload) + return response + + def GetSourceActive(self, name): + """ + Gets the active and show state of a source + + :param name: Name of the source to get the active state of + :type name: str + + + """ + payload = {"sourceName": name} + response = self.base_client.req("GetSourceActive", payload) + return response + + def GetSourceScreenshot(self, name, img_format, width, height, quality): + """ + Gets a Base64-encoded screenshot of a source. + The imageWidth and imageHeight parameters are + treated as "scale to inner", meaning the smallest ratio + will be used and the aspect ratio of the original resolution is kept. + If imageWidth and imageHeight are not specified, the compressed image + will use the full resolution of the source. + + :param name: Name of the source to take a screenshot of + :type name: str + :param format: Image compression format to use. Use GetVersion to get compatible image formats + :type format: str + :param width: Width to scale the screenshot to (>= 8, <= 4096) + :type width: int + :param height: Height to scale the screenshot to (>= 8, <= 4096) + :type height: int + :param quality: Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use "default" + :type quality: int + + + """ + payload = { + "sourceName": name, + "imageFormat": img_format, + "imageWidth": width, + "imageHeight": height, + "imageCompressionQuality": quality, + } + response = self.base_client.req("GetSourceScreenshot", payload) + return response + + def SaveSourceScreenshot(self, name, img_format, file_path, width, height, quality): + """ + Saves a Base64-encoded screenshot of a source. + The imageWidth and imageHeight parameters are + treated as "scale to inner", meaning the smallest ratio + will be used and the aspect ratio of the original resolution is kept. + If imageWidth and imageHeight are not specified, the compressed image + will use the full resolution of the source. + + :param name: Name of the source to take a screenshot of + :type name: str + :param format: Image compression format to use. Use GetVersion to get compatible image formats + :type format: str + :param file_path: Path to save the screenshot file to. Eg. C:\\Users\\user\\Desktop\\screenshot.png + :type file_path: str + :param width: Width to scale the screenshot to (>= 8, <= 4096) + :type width: int + :param height: Height to scale the screenshot to (>= 8, <= 4096) + :type height: int + :param quality: Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use "default" + :type quality: int + + + """ + payload = { + "sourceName": name, + "imageFormat": img_format, + "imageFilePath": file_path, + "imageWidth": width, + "imageHeight": height, + "imageCompressionQuality": quality, + } + response = self.base_client.req("SaveSourceScreenshot", payload) + return response + + def GetSceneList(self): + """ + Gets a list of all scenes in OBS. + + + """ + response = self.base_client.req("GetSceneList") + return response + + def GetGroupList(self): + """ + Gets a list of all groups in OBS. + Groups in OBS are actually scenes, + but renamed and modified. In obs-websocket, + we treat them as scenes where we can.. + + + """ + response = self.base_client.req("GetSceneList") + return response + + def GetCurrentProgramScene(self): + """ + Gets the current program scene. + + + """ + response = self.base_client.req("GetCurrentProgramScene") + return response + + def SetCurrentProgramScene(self, name): + """ + Sets the current program scene + + :param name: Scene to set as the current program scene + :type name: str + + + """ + payload = {"sceneName": name} + response = self.base_client.req("SetCurrentProgramScene", payload) + return response + + def GetCurrentPreviewScene(self): + """ + Gets the current preview scene + + + """ + response = self.base_client.req("GetCurrentPreviewScene") + return response + + def SetCurrentPreviewScene(self, name): + """ + Sets the current program scene + + :param name: Scene to set as the current preview scene + :type name: str + + + """ + payload = {"sceneName": name} + response = self.base_client.req("SetCurrentPreviewScene", payload) + return response + + def CreateScene(self, name): + """ + Creates a new scene in OBS. + + :param name: Name for the new scene + :type name: str + + + """ + payload = {"sceneName": name} + response = self.base_client.req("CreateScene", payload) + return response + + def RemoveScene(self, name): + """ + Removes a scene from OBS + + :param name: Name of the scene to remove + :type name: str + + + """ + payload = {"sceneName": name} + response = self.base_client.req("RemoveScene", payload) + return response + + def SetSceneName(self, old_name, new_name): + """ + Sets the name of a scene (rename). + + :param old_name: Name of the scene to be renamed + :type old_name: str + :param new_name: New name for the scene + :type new_name: str + + + """ + payload = {"sceneName": old_name, "newSceneName": new_name} + response = self.base_client.req("SetSceneName", payload) + return response + + def GetSceneSceneTransitionOverride(self, name): + """ + Gets the scene transition overridden for a scene. + + :param name: Name of the scene + :type name: str + + + """ + payload = {"sceneName": name} + response = self.base_client.req("GetSceneSceneTransitionOverride", payload) + return response + + def SetSceneSceneTransitionOverride(self, scene_name, tr_name, tr_duration): + """ + Gets the scene transition overridden for a scene. + + :param scene_name: Name of the scene + :type scene_name: str + :param tr_name: Name of the scene transition to use as override. Specify null to remove + :type tr_name: str + :param tr_duration: Duration to use for any overridden transition. Specify null to remove (>= 50, <= 20000) + :type tr_duration: int + + + """ + payload = { + "sceneName": scene_name, + "transitionName": tr_name, + "transitionDuration": tr_duration, + } + response = self.base_client.req("SetSceneSceneTransitionOverride", payload) + return response + + def GetInputList(self, kind): + """ + Gets a list of all inputs in OBS. + + :param kind: Restrict the list to only inputs of the specified kind + :type kind: str + + + """ + payload = {"inputKind": kind} + response = self.base_client.req("GetInputList", payload) + return response + + def GetInputKindList(self, unversioned): + """ + Gets a list of all available input kinds in OBS. + + :param unversioned: True == Return all kinds as unversioned, False == Return with version suffixes (if available) + :type unversioned: bool + + + """ + payload = {"unversioned": unversioned} + response = self.base_client.req("GetInputKindList", payload) + return response + + def GetSpecialInputs(self): + """ + Gets the name of all special inputs. + + + """ + response = self.base_client.req("GetSpecialInputs") + return response + + def CreateInput( + self, sceneName, inputName, inputKind, inputSettings, sceneItemEnabled + ): + """ + Creates a new input, adding it as a scene item to the specified scene. + + :param sceneName: Name of the scene to add the input to as a scene item + :type sceneName: str + :param inputName Name of the new input to created + :type inputName: str + :param inputKind: The kind of input to be created + :type inputKind: str + :param inputSettings: Settings object to initialize the input with + :type inputSettings: object + :param sceneItemEnabled: Whether to set the created scene item to enabled or disabled + :type sceneItemEnabled: bool + + + """ + payload = { + "sceneName": sceneName, + "inputName": inputName, + "inputKind": inputKind, + "inputSettings": inputSettings, + "sceneItemEnabled": sceneItemEnabled, + } + response = self.base_client.req("CreateInput", payload) + return response + + def RemoveInput(self, name): + """ + Removes an existing input + + :param name: Name of the input to remove + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("RemoveInput", payload) + return response + + def SetInputName(self, old_name, new_name): + """ + Sets the name of an input (rename). + + :param old_name: Current input name + :type old_name: str + :param new_name: New name for the input + :type new_name: str + + + """ + payload = {"inputName": old_name, "newInputName": new_name} + response = self.base_client.req("SetInputName", payload) + return response + + def GetInputDefaultSettings(self, kind): + """ + Gets the default settings for an input kind. + + :param kind: Input kind to get the default settings for + :type kind: str + + + """ + payload = {"inputKind": kind} + response = self.base_client.req("GetInputDefaultSettings", payload) + return response + + def GetInputSettings(self, name): + """ + Gets the settings of an input. + Note: Does not include defaults. To create the entire settings object, + overlay inputSettings over the defaultInputSettings provided by GetInputDefaultSettings. + + :param name: Input kind to get the default settings for + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("GetInputSettings", payload) + return response + + def SetInputSettings(self, name, settings, overlay): + """ + Sets the settings of an input. + + :param name: Name of the input to set the settings of + :type name: str + :param settings: Object of settings to apply + :type settings: dict + :param overlay: True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. + :type overlay: bool + + + """ + payload = {"inputName": name, "inputSettings": settings, "overlay": overlay} + response = self.base_client.req("SetInputSettings", payload) + return response + + def GetInputMute(self, name): + """ + Gets the audio mute state of an input + + :param name: Name of input to get the mute state of + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("GetInputMute", payload) + return response + + def SetInputMute(self, name, muted): + """ + Sets the audio mute state of an input. + + :param name: Name of the input to set the mute state of + :type name: str + :param muted: Whether to mute the input or not + :type muted: bool + + + """ + payload = {"inputName": name, "inputMuted": muted} + response = self.base_client.req("SetInputMute", payload) + return response + + def ToggleInputMute(self, name): + """ + Toggles the audio mute state of an input. + + :param name: Name of the input to toggle the mute state of + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("ToggleInputMute", payload) + return response + + def GetInputVolume(self, name): + """ + Gets the current volume setting of an input. + + :param name: Name of the input to get the volume of + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("GetInputVolume", payload) + return response + + def SetInputVolume(self, name, vol_mul=None, vol_db=None): + """ + Sets the volume setting of an input. + + :param name: Name of the input to set the volume of + :type name: str + :param vol_mul: Volume setting in mul (>= 0, <= 20) + :type vol_mul: int + :param vol_db: Volume setting in dB (>= -100, <= 26) + :type vol_db: int + + + """ + payload = { + "inputName": name, + "inputVolumeMul": vol_mul, + "inputVolumeDb": vol_db, + } + response = self.base_client.req("SetInputVolume", payload) + return response + + def GetInputAudioBalance(self, name): + """ + Gets the audio balance of an input. + + :param name: Name of the input to get the audio balance of + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("GetInputAudioBalance", payload) + return response + + def SetInputAudioBalance(self, name, balance): + """ + Sets the audio balance of an input. + + :param name: Name of the input to get the audio balance of + :type name: str + :param balance: New audio balance value (>= 0.0, <= 1.0) + :type balance: int + + + """ + payload = {"inputName": name, "inputAudioBalance": balance} + response = self.base_client.req("SetInputAudioBalance", payload) + return response + + def GetInputAudioOffset(self, name): + """ + Gets the audio sync offset of an input. + + :param name: Name of the input to get the audio sync offset of + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("GetInputAudioOffset", payload) + return response + + def SetInputAudioSyncOffset(self, name, offset): + """ + Sets the audio sync offset of an input. + + :param name: Name of the input to set the audio sync offset of + :type name: str + :param offset: New audio sync offset in milliseconds (>= -950, <= 20000) + :type offset: int + + + """ + payload = {"inputName": name, "inputAudioSyncOffset": offset} + response = self.base_client.req("SetInputAudioSyncOffset", payload) + return response + + def GetInputAudioMonitorType(self, name): + """ + Gets the audio monitor type of an input. + + The available audio monitor types are: + OBS_MONITORING_TYPE_NONE + OBS_MONITORING_TYPE_MONITOR_ONLY + OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT + + + :param name: Name of the input to get the audio monitor type of + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("GetInputAudioMonitorType", payload) + return response + + def SetInputAudioMonitorType(self, name, mon_type): + """ + Sets the audio monitor type of an input. + + :param name: Name of the input to set the audio monitor type of + :type name: str + :param mon_type: Audio monitor type + :type mon_type: int + + + """ + payload = {"inputName": name, "monitorType": mon_type} + response = self.base_client.req("SetInputAudioMonitorType", payload) + return response + + def GetInputAudioTracks(self, name): + """ + Gets the enable state of all audio tracks of an input. + + :param name: Name of the input + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("GetInputAudioTracks", payload) + return response + + def SetInputAudioTracks(self, name, track): + """ + Sets the audio monitor type of an input. + + :param name: Name of the input + :type name: str + :param track: Track settings to apply + :type track: int + + + """ + payload = {"inputName": name, "inputAudioTracks": track} + response = self.base_client.req("SetInputAudioTracks", payload) + return response + + def GetInputPropertiesListPropertyItems(self, input_name, prop_name): + """ + Gets the items of a list property from an input's properties. + Note: Use this in cases where an input provides a dynamic, + selectable list of items. For example, display capture, + where it provides a list of available displays. + + :param input_name: Name of the input + :type input_name: str + :param prop_name: Name of the list property to get the items of + :type prop_name: str + + + """ + payload = {"inputName": input_name, "propertyName": prop_name} + response = self.base_client.req("GetInputPropertiesListPropertyItems", payload) + return response + + def PressInputPropertiesButton(self, input_name, prop_name): + """ + Presses a button in the properties of an input. + Note: Use this in cases where there is a button + in the properties of an input that cannot be accessed in any other way. + For example, browser sources, where there is a refresh button. + + :param input_name: Name of the input + :type input_name: str + :param prop_name: Name of the button property to press + :type prop_name: str + + + """ + payload = {"inputName": input_name, "propertyName": prop_name} + response = self.base_client.req("PressInputPropertiesButton", payload) + return response + + def GetTransitionKindList(self): + """ + Gets an array of all available transition kinds. + Similar to GetInputKindList + + + """ + response = self.base_client.req("GetTransitionKindList") + return response + + def GetSceneTransitionList(self): + """ + Gets an array of all scene transitions in OBS. + + + """ + response = self.base_client.req("GetSceneTransitionList") + return response + + def GetCurrentSceneTransition(self): + """ + Gets an array of all scene transitions in OBS. + + + """ + response = self.base_client.req("GetCurrentSceneTransition") + return response + + def SetCurrentSceneTransition(self, name): + """ + Sets the current scene transition. + Small note: While the namespace of scene transitions is generally unique, + that uniqueness is not a guarantee as it is with other resources like inputs. + + :param name: Name of the transition to make active + :type name: str + + + """ + payload = {"transitionName": name} + response = self.base_client.req("SetCurrentSceneTransition", payload) + return response + + def SetCurrentSceneTransitionDuration(self, duration): + """ + Sets the duration of the current scene transition, if it is not fixed. + + :param duration: Duration in milliseconds (>= 50, <= 20000) + :type duration: str + + + """ + payload = {"transitionDuration": duration} + response = self.base_client.req("SetCurrentSceneTransitionDuration", payload) + return response + + def SetCurrentSceneTransitionSettings(self, settings, overlay=None): + """ + Sets the settings of the current scene transition. + + :param settings: Settings object to apply to the transition. Can be {} + :type settings: dict + :param overlay: Whether to overlay over the current settings or replace them + :type overlay: bool + + + """ + payload = {"transitionSettings": settings, "overlay": overlay} + response = self.base_client.req("SetCurrentSceneTransitionSettings", payload) + return response + + def GetCurrentSceneTransitionCursor(self): + """ + Gets the cursor position of the current scene transition. + Note: transitionCursor will return 1.0 when the transition is inactive. + + + """ + response = self.base_client.req("GetCurrentSceneTransitionCursor") + return response + + def TriggerStudioModeTransition(self): + """ + Triggers the current scene transition. + Same functionality as the Transition button in studio mode. + Note: Studio mode should be active. if not throws an + RequestStatus::StudioModeNotActive (506) in response + + + """ + response = self.base_client.req("TriggerStudioModeTransition") + return response + + def SetTBarPosition(self, pos, release=None): + """ + Sets the position of the TBar. + Very important note: This will be deprecated + and replaced in a future version of obs-websocket. + + :param pos: New position (>= 0.0, <= 1.0) + :type pos: float + :param release: Whether to release the TBar. Only set false if you know that you will be sending another position update + :type release: bool + + + """ + payload = {"position": pos, "release": release} + response = self.base_client.req("SetTBarPosition", payload) + return response + + def GetSourceFilterList(self, name): + """ + Gets a list of all of a source's filters. + + :param name: Name of the source + :type name: str + + + """ + payload = {"sourceName": name} + response = self.base_client.req("GetSourceFilterList", payload) + return response + + def GetSourceFilterDefaultSettings(self, kind): + """ + Gets the default settings for a filter kind. + + :param kind: Filter kind to get the default settings for + :type kind: str + + + """ + payload = {"filterKind": kind} + response = self.base_client.req("GetSourceFilterDefaultSettings", payload) + return response + + def CreateSourceFilter( + self, source_name, filter_name, filter_kind, filter_settings=None + ): + """ + Gets the default settings for a filter kind. + + :param source_name: Name of the source to add the filter to + :type source_name: str + :param filter_name: Name of the new filter to be created + :type filter_name: str + :param filter_kind: The kind of filter to be created + :type filter_kind: str + :param filter_settings: Settings object to initialize the filter with + :type filter_settings: dict + + + """ + payload = { + "sourceName": source_name, + "filterName": filter_name, + "filterKind": filter_kind, + "filterSettings": filter_settings, + } + response = self.base_client.req("CreateSourceFilter", payload) + return response + + def RemoveSourceFilter(self, source_name, filter_name): + """ + Gets the default settings for a filter kind. + + :param source_name: Name of the source the filter is on + :type source_name: str + :param filter_name: Name of the filter to remove + :type filter_name: str + + + """ + payload = { + "sourceName": source_name, + "filterName": filter_name, + } + response = self.base_client.req("RemoveSourceFilter", payload) + return response + + def SetSourceFilterName(self, source_name, old_filter_name, new_filter_name): + """ + Sets the name of a source filter (rename). + + :param source_name: Name of the source the filter is on + :type source_name: str + :param old_filter_name: Current name of the filter + :type old_filter_name: str + :param new_filter_name: New name for the filter + :type new_filter_name: str + + + """ + payload = { + "sourceName": source_name, + "filterName": old_filter_name, + "newFilterName": new_filter_name, + } + response = self.base_client.req("SetSourceFilterName", payload) + return response + + def GetSourceFilter(self, source_name, filter_name): + """ + Gets the info for a specific source filter. + + :param source_name: Name of the source + :type source_name: str + :param filter_name: Name of the filter + :type filter_name: str + + + """ + payload = {"sourceName": source_name, "filterName": filter_name} + response = self.base_client.req("GetSourceFilter", payload) + return response + + def SetSourceFilterIndex(self, source_name, filter_name, filter_index): + """ + Gets the info for a specific source filter. + + :param source_name: Name of the source the filter is on + :type source_name: str + :param filter_name: Name of the filter + :type filter_name: str + :param filterIndex: New index position of the filter (>= 0) + :type filterIndex: int + + + """ + payload = { + "sourceName": source_name, + "filterName": filter_name, + "filterIndex": filter_index, + } + response = self.base_client.req("SetSourceFilterIndex", payload) + return response + + def SetSourceFilterSettings(self, source_name, filter_name, settings, overlay=None): + """ + Gets the info for a specific source filter. + + :param source_name: Name of the source the filter is on + :type source_name: str + :param filter_name: Name of the filter to set the settings of + :type filter_name: str + :param settings: Dictionary of settings to apply + :type settings: dict + :param overlay: True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. + :type overlay: bool + + + """ + payload = { + "sourceName": source_name, + "filterName": filter_name, + "filterSettings": settings, + "overlay": overlay, + } + response = self.base_client.req("SetSourceFilterSettings", payload) + return response + + def SetSourceFilterEnabled(self, source_name, filter_name, enabled): + """ + Gets the info for a specific source filter. + + :param source_name: Name of the source the filter is on + :type source_name: str + :param filter_name: Name of the filter + :type filter_name: str + :param enabled: New enable state of the filter + :type enabled: bool + + + """ + payload = { + "sourceName": source_name, + "filterName": filter_name, + "filterEnabled": enabled, + } + response = self.base_client.req("SetSourceFilterEnabled", payload) + return response + + def GetSceneItemList(self, name): + """ + Gets a list of all scene items in a scene. + + :param name: Name of the scene to get the items of + :type name: str + + + """ + payload = {"sceneName": name} + response = self.base_client.req("GetSceneItemList", payload) + return response + + def GetGroupItemList(self, name): + """ + Gets a list of all scene items in a scene. + + :param name: Name of the group to get the items of + :type name: str + + + """ + payload = {"sceneName": name} + response = self.base_client.req("GetGroupItemList", payload) + return response + + def GetSceneItemId(self, scene_name, source_name, offset=None): + """ + Searches a scene for a source, and returns its id. + + :param scene_name: Name of the scene or group to search in + :type scene_name: str + :param source_name: Name of the source to find + :type source_name: str + :param offset: Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item (>= -1) + :type offset: int + + + """ + payload = { + "sceneName": scene_name, + "sourceName": source_name, + "searchOffset": offset, + } + response = self.base_client.req("GetSceneItemId", payload) + return response + + def CreateSceneItem(self, scene_name, source_name, enabled=None): + """ + Creates a new scene item using a source. + Scenes only + + :param scene_name: Name of the scene to create the new item in + :type scene_name: str + :param source_name: Name of the source to add to the scene + :type source_name: str + :param enabled: Enable state to apply to the scene item on creation + :type enabled: bool + + + """ + payload = { + "sceneName": scene_name, + "sourceName": source_name, + "sceneItemEnabled": enabled, + } + response = self.base_client.req("CreateSceneItem", payload) + return response + + def RemoveSceneItem(self, scene_name, item_id): + """ + Removes a scene item from a scene. + Scenes only + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item + :type item_id: int + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + } + response = self.base_client.req("RemoveSceneItem", payload) + return response + + def DuplicateSceneItem(self, scene_name, item_id, dest_scene_name=None): + """ + Duplicates a scene item, copying all transform and crop info. + Scenes only + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + :param dest_scene_name: Name of the scene to create the duplicated item in + :type dest_scene_name: str + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + "destinationSceneName": dest_scene_name, + } + response = self.base_client.req("DuplicateSceneItem", payload) + return response + + def GetSceneItemTransform(self, scene_name, item_id): + """ + Gets the transform and crop info of a scene item. + Scenes and Groups + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + } + response = self.base_client.req("GetSceneItemTransform", payload) + return response + + def SetSceneItemTransform(self, scene_name, item_id, transform): + """ + Sets the transform and crop info of a scene item. + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + :param transform: Dictionary containing scene item transform info to update + :type transform: dict + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemTransform": transform, + } + response = self.base_client.req("SetSceneItemTransform", payload) + return response + + def GetSceneItemEnabled(self, scene_name, item_id): + """ + Gets the enable state of a scene item. + Scenes and Groups + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + } + response = self.base_client.req("GetSceneItemEnabled", payload) + return response + + def SetSceneItemEnabled(self, scene_name, item_id, enabled): + """ + Sets the enable state of a scene item. + Scenes and Groups' + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + :param enabled: New enable state of the scene item + :type enabled: bool + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemEnabled": enabled, + } + response = self.base_client.req("SetSceneItemEnabled", payload) + return response + + def GetSceneItemLocked(self, scene_name, item_id): + """ + Gets the lock state of a scene item. + Scenes and Groups + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + } + response = self.base_client.req("GetSceneItemLocked", payload) + return response + + def SetSceneItemLocked(self, scene_name, item_id, locked): + """ + Sets the lock state of a scene item. + Scenes and Groups + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + :param locked: New lock state of the scene item + :type locked: bool + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemLocked": locked, + } + response = self.base_client.req("SetSceneItemLocked", payload) + return response + + def GetSceneItemIndex(self, scene_name, item_id): + """ + Gets the index position of a scene item in a scene. + An index of 0 is at the bottom of the source list in the UI. + Scenes and Groups + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + } + response = self.base_client.req("GetSceneItemIndex", payload) + return response + + def SetSceneItemIndex(self, scene_name, item_id, item_index): + """ + Sets the index position of a scene item in a scene. + Scenes and Groups + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + :param item_index: New index position of the scene item (>= 0) + :type item_index: int + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemLocked": item_index, + } + response = self.base_client.req("SetSceneItemIndex", payload) + return response + + def GetSceneItemBlendMode(self, scene_name, item_id): + """ + Gets the blend mode of a scene item. + Blend modes: + + OBS_BLEND_NORMAL + OBS_BLEND_ADDITIVE + OBS_BLEND_SUBTRACT + OBS_BLEND_SCREEN + OBS_BLEND_MULTIPLY + OBS_BLEND_LIGHTEN + OBS_BLEND_DARKEN + Scenes and Groups + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + } + response = self.base_client.req("GetSceneItemBlendMode", payload) + return response + + def SetSceneItemBlendMode(self, scene_name, item_id, blend): + """ + Sets the blend mode of a scene item. + Scenes and Groups + + :param scene_name: Name of the scene the item is in + :type scene_name: str + :param item_id: Numeric ID of the scene item (>= 0) + :type item_id: int + :param blend: New blend mode + :type blend: str + + + """ + payload = { + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemBlendMode": blend, + } + response = self.base_client.req("SetSceneItemBlendMode", payload) + return response + + def GetVirtualCamStatus(self): + """ + Gets the status of the virtualcam output. + + + """ + response = self.base_client.req("GetVirtualCamStatus") + return response + + def ToggleVirtualCam(self): + """ + Toggles the state of the virtualcam output. + + + """ + response = self.base_client.req("ToggleVirtualCam") + return response + + def StartVirtualCam(self): + """ + Starts the virtualcam output. + + + """ + response = self.base_client.req("StartVirtualCam") + return response + + def StopVirtualCam(self): + """ + Stops the virtualcam output. + + + """ + response = self.base_client.req("StopVirtualCam") + return response + + def GetReplayBufferStatus(self): + """ + Gets the status of the replay buffer output. + + + """ + response = self.base_client.req("GetReplayBufferStatus") + return response + + def ToggleReplayBuffer(self): + """ + Toggles the state of the replay buffer output. + + + """ + response = self.base_client.req("ToggleReplayBuffer") + return response + + def StartReplayBuffer(self): + """ + Starts the replay buffer output. + + + """ + response = self.base_client.req("StartReplayBuffer") + return response + + def StopReplayBuffer(self): + """ + Stops the replay buffer output. + + + """ + response = self.base_client.req("StopReplayBuffer") + return response + + def SaveReplayBuffer(self): + """ + Saves the contents of the replay buffer output. + + + """ + response = self.base_client.req("SaveReplayBuffer") + return response + + def GetLastReplayBufferReplay(self): + """ + Gets the filename of the last replay buffer save file. + + + """ + response = self.base_client.req("GetLastReplayBufferReplay") + return response + + def GetStreamStatus(self): + """ + Gets the status of the stream output. + + + """ + response = self.base_client.req("GetStreamStatus") + return response + + def ToggleStream(self): + """ + Toggles the status of the stream output. + + + """ + response = self.base_client.req("ToggleStream") + return response + + def StartStream(self): + """ + Starts the stream output. + + + """ + response = self.base_client.req("StartStream") + return response + + def StopStream(self): + """ + Stops the stream output. + + + """ + response = self.base_client.req("StopStream") + return response + + def SendStreamCaption(self, caption): + """ + Sends CEA-608 caption text over the stream output. + + :param caption: Caption text + :type caption: str + + + """ + response = self.base_client.req("SendStreamCaption") + return response + + def GetRecordStatus(self): + """ + Gets the status of the record output. + + + """ + response = self.base_client.req("GetRecordStatus") + return response + + def ToggleRecord(self): + """ + Toggles the status of the record output. + + + """ + response = self.base_client.req("ToggleRecord") + return response + + def StartRecord(self): + """ + Starts the record output. + + + """ + response = self.base_client.req("StartRecord") + return response + + def StopRecord(self): + """ + Stops the record output. + + + """ + response = self.base_client.req("StopRecord") + return response + + def ToggleRecordPause(self): + """ + Toggles pause on the record output. + + + """ + response = self.base_client.req("ToggleRecordPause") + return response + + def PauseRecord(self): + """ + Pauses the record output. + + + """ + response = self.base_client.req("PauseRecord") + return response + + def ResumeRecord(self): + """ + Resumes the record output. + + + """ + response = self.base_client.req("ResumeRecord") + return response + + def GetMediaInputStatus(self, name): + """ + Gets the status of a media input. + + Media States: + OBS_MEDIA_STATE_NONE + OBS_MEDIA_STATE_PLAYING + OBS_MEDIA_STATE_OPENING + OBS_MEDIA_STATE_BUFFERING + OBS_MEDIA_STATE_PAUSED + OBS_MEDIA_STATE_STOPPED + OBS_MEDIA_STATE_ENDED + OBS_MEDIA_STATE_ERROR + + :param name: Name of the media input + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("GetMediaInputStatus", payload) + return response + + def SetMediaInputCursor(self, name, cursor): + """ + Sets the cursor position of a media input. + This request does not perform bounds checking of the cursor position. + + :param name: Name of the media input + :type name: str + :param cursor: New cursor position to set (>= 0) + :type cursor: int + + + """ + payload = {"inputName": name, "mediaCursor": cursor} + response = self.base_client.req("SetMediaInputCursor", payload) + return response + + def OffsetMediaInputCursor(self, name, offset): + """ + Offsets the current cursor position of a media input by the specified value. + This request does not perform bounds checking of the cursor position. + + :param name: Name of the media input + :type name: str + :param offset: Value to offset the current cursor position by + :type offset: int + + + """ + payload = {"inputName": name, "mediaCursorOffset": offset} + response = self.base_client.req("OffsetMediaInputCursor", payload) + return response + + def TriggerMediaInputAction(self, name, action): + """ + Triggers an action on a media input. + + :param name: Name of the media input + :type name: str + :param action: Identifier of the ObsMediaInputAction enum + :type action: str + + + """ + payload = {"inputName": name, "mediaAction": action} + response = self.base_client.req("TriggerMediaInputAction", payload) + return response + + def GetStudioModeEnabled(self): + """ + Gets whether studio is enabled. + + + """ + response = self.base_client.req("GetStudioModeEnabled") + return response + + def SetStudioModeEnabled(self, enabled): + """ + Enables or disables studio mode + + :param enabled: True == Enabled, False == Disabled + :type enabled: bool + + + """ + payload = {"studioModeEnabled": enabled} + response = self.base_client.req("SetStudioModeEnabled", payload) + return response + + def OpenInputPropertiesDialog(self, name): + """ + Opens the properties dialog of an input. + + :param name: Name of the input to open the dialog of + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("OpenInputPropertiesDialog", payload) + return response + + def OpenInputFiltersDialog(self, name): + """ + Opens the filters dialog of an input. + + :param name: Name of the input to open the dialog of + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("OpenInputFiltersDialog", payload) + return response + + def OpenInputInteractDialog(self, name): + """ + Opens the filters dialog of an input. + + :param name: Name of the input to open the dialog of + :type name: str + + + """ + payload = {"inputName": name} + response = self.base_client.req("OpenInputInteractDialog", payload) + return response + + def GetMonitorList(self, name): + """ + Gets a list of connected monitors and information about them. + + + """ + response = self.base_client.req("GetMonitorList") + return response diff --git a/build/lib/obsstudio_sdk/subject.py b/build/lib/obsstudio_sdk/subject.py new file mode 100644 index 0000000..24732c5 --- /dev/null +++ b/build/lib/obsstudio_sdk/subject.py @@ -0,0 +1,58 @@ +import re + + +class Callback: + """Adds support for callbacks""" + + def __init__(self): + """list of current callbacks""" + + self._callbacks = list() + + def to_camel_case(self, s): + s = "".join(word.title() for word in s.split("_")) + return s[2:] + + def to_snake_case(self, s): + s = re.sub(r"(? list: + """returns a list of registered events""" + + return [self.to_camel_case(fn.__name__) for fn in self._callbacks] + + def trigger(self, event, data=None): + """trigger callback on update""" + + for fn in self._callbacks: + if fn.__name__ == self.to_snake_case(event): + if "eventData" in data: + fn(data["eventData"]) + else: + fn() + + def register(self, fns): + """registers callback functions""" + + try: + iter(fns) + for fn in fns: + if fn not in self._callbacks: + self._callbacks.append(fn) + except TypeError as e: + if fns not in self._callbacks: + self._callbacks.append(fns) + + def deregister(self, callback): + """deregisters a callback from _callbacks""" + + try: + self._callbacks.remove(callback) + except ValueError: + print(f"Failed to remove: {callback}") + + def clear(self): + """clears the _callbacks list""" + + self._callbacks.clear() diff --git a/examples/events/__main__.py b/examples/events/__main__.py new file mode 100644 index 0000000..4f6c0c5 --- /dev/null +++ b/examples/events/__main__.py @@ -0,0 +1,26 @@ +import obsstudio_sdk as obs + + +class Observer: + def __init__(self, cl): + self._cl = cl + self._cl.callback.register( + [self.on_current_program_scene_changed, self.on_exit_started] + ) + print(f"Registered events: {self._cl.callback.get()}") + + def on_exit_started(self): + print(f"OBS closing!") + self._cl.unsubscribe() + + def on_current_program_scene_changed(self, data): + print(f"Switched to scene {data['sceneName']}") + + +if __name__ == "__main__": + cl = obs.EventsClient() + observer = Observer(cl) + + while cmd := input(" to exit\n"): + if not cmd: + break diff --git a/examples/scene_rotate/__main__.py b/examples/scene_rotate/__main__.py new file mode 100644 index 0000000..23f71bb --- /dev/null +++ b/examples/scene_rotate/__main__.py @@ -0,0 +1,19 @@ +import time + +import obsstudio_sdk as obs + + +def main(): + res = cl.GetSceneList() + scenes = reversed(tuple(d["sceneName"] for d in res["d"]["responseData"]["scenes"])) + + for sc in scenes: + print(f"Switching to scene {sc}") + cl.SetCurrentProgramScene(sc) + time.sleep(0.5) + + +if __name__ == "__main__": + cl = obs.ReqClient() + + main() diff --git a/obsstudio_sdk/__init__.py b/obsstudio_sdk/__init__.py index 8b13789..7c892fc 100644 --- a/obsstudio_sdk/__init__.py +++ b/obsstudio_sdk/__init__.py @@ -1 +1,4 @@ +from .events import EventsClient +from .reqs import ReqClient +__ALL__ = ["ReqClient", "EventsClient"] diff --git a/obsstudio_sdk/baseclient.py b/obsstudio_sdk/baseclient.py index 1326f16..809d207 100644 --- a/obsstudio_sdk/baseclient.py +++ b/obsstudio_sdk/baseclient.py @@ -1,53 +1,73 @@ -import websocket -import json -import hashlib import base64 +import hashlib +import json +from pathlib import Path from random import randint +import tomllib +import websocket + + class ObsClient(object): - def __init__(self, host, port, password): - self.host = host - self.port = port - self.password = password + def __init__(self, **kwargs): + defaultkwargs = {key: None for key in ["host", "port", "password"]} + kwargs = defaultkwargs | kwargs + for attr, val in kwargs.items(): + setattr(self, attr, val) + if not (self.host and self.port and self.password): + conn = self._conn_from_toml() + self.host = conn["host"] + self.port = conn["port"] + self.password = conn["password"] + self.ws = websocket.WebSocket() self.ws.connect(f"ws://{self.host}:{self.port}") self.server_hello = json.loads(self.ws.recv()) + def _conn_from_toml(self): + filepath = Path.cwd() / "config.toml" + self._conn = dict() + with open(filepath, "rb") as f: + self._conn = tomllib.load(f) + return self._conn["connection"] + def authenticate(self): secret = base64.b64encode( hashlib.sha256( - (self.password + self.server_hello['d']['authentication']['salt']).encode()).digest()) - + ( + self.password + self.server_hello["d"]["authentication"]["salt"] + ).encode() + ).digest() + ) + auth = base64.b64encode( - hashlib.sha256( - (secret.decode() + self.server_hello['d']['authentication']['challenge']).encode()).digest()).decode() - - payload = { "op":1, "d": { - "rpcVersion": 1, - "authentication": auth} - } - + hashlib.sha256( + ( + secret.decode() + + self.server_hello["d"]["authentication"]["challenge"] + ).encode() + ).digest() + ).decode() + + payload = {"op": 1, "d": {"rpcVersion": 1, "authentication": auth}} + self.ws.send(json.dumps(payload)) return self.ws.recv() def req(self, req_type, req_data=None): - if req_data == None: - payload = { - "op": 6, - "d": { - "requestType": req_type, - "requestId": randint(1, 1000) - } - } - else: + if req_data: payload = { "op": 6, "d": { "requestType": req_type, "requestId": randint(1, 1000), - "requestData": req_data - } + "requestData": req_data, + }, + } + else: + payload = { + "op": 6, + "d": {"requestType": req_type, "requestId": randint(1, 1000)}, } self.ws.send(json.dumps(payload)) return json.loads(self.ws.recv()) - \ No newline at end of file diff --git a/obsstudio_sdk/callback.py b/obsstudio_sdk/callback.py new file mode 100644 index 0000000..24732c5 --- /dev/null +++ b/obsstudio_sdk/callback.py @@ -0,0 +1,58 @@ +import re + + +class Callback: + """Adds support for callbacks""" + + def __init__(self): + """list of current callbacks""" + + self._callbacks = list() + + def to_camel_case(self, s): + s = "".join(word.title() for word in s.split("_")) + return s[2:] + + def to_snake_case(self, s): + s = re.sub(r"(? list: + """returns a list of registered events""" + + return [self.to_camel_case(fn.__name__) for fn in self._callbacks] + + def trigger(self, event, data=None): + """trigger callback on update""" + + for fn in self._callbacks: + if fn.__name__ == self.to_snake_case(event): + if "eventData" in data: + fn(data["eventData"]) + else: + fn() + + def register(self, fns): + """registers callback functions""" + + try: + iter(fns) + for fn in fns: + if fn not in self._callbacks: + self._callbacks.append(fn) + except TypeError as e: + if fns not in self._callbacks: + self._callbacks.append(fns) + + def deregister(self, callback): + """deregisters a callback from _callbacks""" + + try: + self._callbacks.remove(callback) + except ValueError: + print(f"Failed to remove: {callback}") + + def clear(self): + """clears the _callbacks list""" + + self._callbacks.clear() diff --git a/obsstudio_sdk/events.py b/obsstudio_sdk/events.py new file mode 100644 index 0000000..6c47dc6 --- /dev/null +++ b/obsstudio_sdk/events.py @@ -0,0 +1,43 @@ +import json +import time +from threading import Thread + +from .baseclient import ObsClient +from .callback import Callback + +""" +A class to interact with obs-websocket events +defined in official github repo +https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events +""" + + +class EventsClient(object): + DELAY = 0.001 + + def __init__(self, **kwargs): + self.base_client = ObsClient(**kwargs) + self.base_client.authenticate() + self.callback = Callback() + + self.running = True + worker = Thread(target=self.trigger, daemon=True) + worker.start() + + def trigger(self): + """ + Continuously listen for events. + + Triggers a callback on event received. + """ + while self.running: + self.data = json.loads(self.base_client.ws.recv()) + event, data = (self.data["d"].get("eventType"), self.data["d"]) + self.callback.trigger(event, data) + time.sleep(self.DELAY) + + def unsubscribe(self): + """ + stop listening for events + """ + self.running = False diff --git a/obsstudio_sdk/reqs.py b/obsstudio_sdk/reqs.py index 1c2571a..924682e 100644 --- a/obsstudio_sdk/reqs.py +++ b/obsstudio_sdk/reqs.py @@ -1,27 +1,29 @@ -from . import baseclient +from .baseclient import ObsClient """ A class to interact with obs-websocket requests defined in official github repo https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#Requests """ + + class ReqClient(object): - def __init__(self, host, port, password): - self.base_client = baseclient.ObsClient(host, port, password) + def __init__(self, **kwargs): + self.base_client = ObsClient(**kwargs) self.base_client.authenticate() def GetVersion(self): """ Gets data about the current plugin and RPC version. - + :return: The version info as a dictionary :rtype: dict """ - response = self.base_client.req('GetVersion') + response = self.base_client.req("GetVersion") return response - + def GetStats(self): """ Gets statistics about OBS, obs-websocket, and the current session. @@ -31,7 +33,7 @@ class ReqClient(object): """ - response = self.base_client.req('GetStats') + response = self.base_client.req("GetStats") return response def BroadcastCustomEvent(self, eventData): @@ -46,20 +48,20 @@ class ReqClient(object): """ req_data = eventData - response = self.base_client.req('BroadcastCustomEvent', req_data) + response = self.base_client.req("BroadcastCustomEvent", req_data) return response def CallVendorRequest(self, vendorName, requestType, requestData=None): """ Call a request registered to a vendor. - - A vendor is a unique name registered by a - third-party plugin or script, which allows + + A vendor is a unique name registered by a + third-party plugin or script, which allows for custom requests and events to be added - to obs-websocket. If a plugin or script - implements vendor requests or events, + to obs-websocket. If a plugin or script + implements vendor requests or events, documentation is expected to be provided with them. - + :param vendorName: Name of the vendor to use :type vendorName: str :param requestType: The request type to call @@ -83,9 +85,9 @@ class ReqClient(object): """ - response = self.base_client.req('GetHotkeyList') + response = self.base_client.req("GetHotkeyList") return response - + def TriggerHotkeyByName(self, hotkeyName): """ Triggers a hotkey using its name. For hotkey names @@ -96,11 +98,13 @@ class ReqClient(object): """ - payload = {'hotkeyName': hotkeyName} - response = self.base_client.req('TriggerHotkeyByName', payload) + payload = {"hotkeyName": hotkeyName} + response = self.base_client.req("TriggerHotkeyByName", payload) return response - - def TriggerHotkeyByKeySequence(self,keyId, pressShift, pressCtrl, pressAlt, pressCmd): + + def TriggerHotkeyByKeySequence( + self, keyId, pressShift, pressCtrl, pressAlt, pressCmd + ): """ Triggers a hotkey using a sequence of keys. @@ -120,21 +124,21 @@ class ReqClient(object): """ payload = { - 'keyId': keyId, - 'keyModifiers': { - 'shift': pressShift, - 'control': pressCtrl, - 'alt': pressAlt, - 'cmd': pressCmd - } + "keyId": keyId, + "keyModifiers": { + "shift": pressShift, + "control": pressCtrl, + "alt": pressAlt, + "cmd": pressCmd, + }, } - - response = self.base_client.req('TriggerHotkeyByKeySequence', payload) + + response = self.base_client.req("TriggerHotkeyByKeySequence", payload) return response def Sleep(self, sleepMillis=None, sleepFrames=None): """ - Sleeps for a time duration or number of frames. + Sleeps for a time duration or number of frames. Only available in request batches with types SERIAL_REALTIME or SERIAL_FRAME :param sleepMillis: Number of milliseconds to sleep for (if SERIAL_REALTIME mode) 0 <= sleepMillis <= 50000 @@ -144,18 +148,15 @@ class ReqClient(object): """ - payload = { - 'sleepMillis': sleepMillis, - 'sleepFrames': sleepFrames - } - response = self.base_client.req('Sleep', payload) + payload = {"sleepMillis": sleepMillis, "sleepFrames": sleepFrames} + response = self.base_client.req("Sleep", payload) return response def GetPersistentData(self, realm, slotName): """ Gets the value of a "slot" from the selected persistent data realm. - :param realm: The data realm to select + :param realm: The data realm to select OBS_WEBSOCKET_DATA_REALM_GLOBAL or OBS_WEBSOCKET_DATA_REALM_PROFILE :type realm: str :param slotName: The name of the slot to retrieve data from @@ -165,18 +166,15 @@ class ReqClient(object): """ - payload = { - 'realm': realm, - 'slotName': slotName - } - response = self.base_client.req('GetPersistentData', payload) + payload = {"realm": realm, "slotName": slotName} + response = self.base_client.req("GetPersistentData", payload) return response def SetPersistentData(self, realm, slotName, slotValue): """ Sets the value of a "slot" from the selected persistent data realm. - :param realm: The data realm to select. + :param realm: The data realm to select. OBS_WEBSOCKET_DATA_REALM_GLOBAL or OBS_WEBSOCKET_DATA_REALM_PROFILE :type realm: str :param slotName: The name of the slot to retrieve data from @@ -186,12 +184,8 @@ class ReqClient(object): """ - payload = { - 'realm': realm, - 'slotName': slotName, - 'slotValue': slotValue - } - response = self.base_client.req('SetPersistentData', payload) + payload = {"realm": realm, "slotName": slotName, "slotValue": slotValue} + response = self.base_client.req("SetPersistentData", payload) return response def GetSceneCollectionList(self): @@ -203,7 +197,7 @@ class ReqClient(object): """ - response = self.base_client.req('GetSceneCollectionList') + response = self.base_client.req("GetSceneCollectionList") return response def SetCurrentSceneCollection(self, name): @@ -216,22 +210,22 @@ class ReqClient(object): """ - payload = {'sceneCollectionName': name} - response = self.base_client.req('SetCurrentSceneCollection', payload) + payload = {"sceneCollectionName": name} + response = self.base_client.req("SetCurrentSceneCollection", payload) return response def CreateSceneCollection(self, name): """ Creates a new scene collection, switching to it in the process. Note: This will block until the collection has finished changing. - + :param name: Name for the new scene collection :type name: str """ - payload = {'sceneCollectionName': name} - response = self.base_client.req('CreateSceneCollection', payload) + payload = {"sceneCollectionName": name} + response = self.base_client.req("CreateSceneCollection", payload) return response def GetProfileList(self): @@ -243,7 +237,7 @@ class ReqClient(object): """ - response = self.base_client.req('GetProfileList') + response = self.base_client.req("GetProfileList") return response def SetCurrentProfile(self, name): @@ -255,10 +249,10 @@ class ReqClient(object): """ - payload = {'profileName': name} - response = self.base_client.req('SetCurrentProfile', payload) + payload = {"profileName": name} + response = self.base_client.req("SetCurrentProfile", payload) return response - + def CreateProfile(self, name): """ Creates a new profile, switching to it in the process @@ -268,13 +262,13 @@ class ReqClient(object): """ - payload = {'profileName': name} - response = self.base_client.req('CreateProfile', payload) + payload = {"profileName": name} + response = self.base_client.req("CreateProfile", payload) return response def RemoveProfile(self, name): """ - Removes a profile. If the current profile is chosen, + Removes a profile. If the current profile is chosen, it will change to a different profile first. :param name: Name of the profile to remove @@ -282,8 +276,8 @@ class ReqClient(object): """ - payload = {'profileName': name} - response = self.base_client.req('RemoveProfile', payload) + payload = {"profileName": name} + response = self.base_client.req("RemoveProfile", payload) return response def GetProfileParameter(self, category, name): @@ -300,11 +294,8 @@ class ReqClient(object): """ - payload = { - 'parameterCategory': category, - 'parameterName': name - } - response = self.base_client.req('GetProfileParameter', payload) + payload = {"parameterCategory": category, "parameterName": name} + response = self.base_client.req("GetProfileParameter", payload) return response def SetProfileParameter(self, category, name, value): @@ -324,28 +315,30 @@ class ReqClient(object): """ payload = { - 'parameterCategory': category, - 'parameterName': name, - 'parameterValue': value + "parameterCategory": category, + "parameterName": name, + "parameterValue": value, } - response = self.base_client.req('SetProfileParameter', payload) + response = self.base_client.req("SetProfileParameter", payload) return response def GetVideoSettings(self): """ Gets the current video settings. - Note: To get the true FPS value, divide the FPS numerator by the FPS denominator. + Note: To get the true FPS value, divide the FPS numerator by the FPS denominator. Example: 60000/1001 - + """ - response = self.base_client.req('GetVideoSettings') + response = self.base_client.req("GetVideoSettings") return response - def SetVideoSettings(self, numerator, denominator, base_width, base_height, out_width, out_height): + def SetVideoSettings( + self, numerator, denominator, base_width, base_height, out_width, out_height + ): """ Sets the current video settings. - Note: Fields must be specified in pairs. + Note: Fields must be specified in pairs. For example, you cannot set only baseWidth without needing to specify baseHeight. :param numerator: Numerator of the fractional FPS value >=1 @@ -364,23 +357,23 @@ class ReqClient(object): """ payload = { - 'fpsNumerator': numerator, - 'fpsDenominator': denominator, - 'baseWidth': base_width, - 'baseHeight': base_height, - 'outputWidth': out_width, - 'outputHeight': out_height + "fpsNumerator": numerator, + "fpsDenominator": denominator, + "baseWidth": base_width, + "baseHeight": base_height, + "outputWidth": out_width, + "outputHeight": out_height, } - response = self.base_client.req('SetVideoSettings', payload) + response = self.base_client.req("SetVideoSettings", payload) return response def GetStreamServiceSettings(self): """ Gets the current stream service settings (stream destination). - + """ - response = self.base_client.req('GetStreamServiceSettings') + response = self.base_client.req("GetStreamServiceSettings") return response def SetStreamServiceSettings(self, ss_type, ss_settings): @@ -397,10 +390,10 @@ class ReqClient(object): """ payload = { - 'streamServiceType': ss_type, - 'streamServiceSettings': ss_settings, + "streamServiceType": ss_type, + "streamServiceSettings": ss_settings, } - response = self.base_client.req('SetStreamServiceSettings', payload) + response = self.base_client.req("SetStreamServiceSettings", payload) return response def GetSourceActive(self, name): @@ -412,17 +405,17 @@ class ReqClient(object): """ - payload = {'sourceName': name} - response = self.base_client.req('GetSourceActive', payload) + payload = {"sourceName": name} + response = self.base_client.req("GetSourceActive", payload) return response def GetSourceScreenshot(self, name, img_format, width, height, quality): """ Gets a Base64-encoded screenshot of a source. - The imageWidth and imageHeight parameters are - treated as "scale to inner", meaning the smallest ratio - will be used and the aspect ratio of the original resolution is kept. - If imageWidth and imageHeight are not specified, the compressed image + The imageWidth and imageHeight parameters are + treated as "scale to inner", meaning the smallest ratio + will be used and the aspect ratio of the original resolution is kept. + If imageWidth and imageHeight are not specified, the compressed image will use the full resolution of the source. :param name: Name of the source to take a screenshot of @@ -439,22 +432,22 @@ class ReqClient(object): """ payload = { - 'sourceName': name, - 'imageFormat': img_format, - 'imageWidth': width, - 'imageHeight': height, - 'imageCompressionQuality': quality + "sourceName": name, + "imageFormat": img_format, + "imageWidth": width, + "imageHeight": height, + "imageCompressionQuality": quality, } - response = self.base_client.req('GetSourceScreenshot', payload) + response = self.base_client.req("GetSourceScreenshot", payload) return response def SaveSourceScreenshot(self, name, img_format, file_path, width, height, quality): """ Saves a Base64-encoded screenshot of a source. - The imageWidth and imageHeight parameters are - treated as "scale to inner", meaning the smallest ratio - will be used and the aspect ratio of the original resolution is kept. - If imageWidth and imageHeight are not specified, the compressed image + The imageWidth and imageHeight parameters are + treated as "scale to inner", meaning the smallest ratio + will be used and the aspect ratio of the original resolution is kept. + If imageWidth and imageHeight are not specified, the compressed image will use the full resolution of the source. :param name: Name of the source to take a screenshot of @@ -469,39 +462,39 @@ class ReqClient(object): :type height: int :param quality: Compression quality to use. 0 for high compression, 100 for uncompressed. -1 to use "default" :type quality: int - + """ payload = { - 'sourceName': name, - 'imageFormat': img_format, - 'imageFilePath': file_path, - 'imageWidth': width, - 'imageHeight': height, - 'imageCompressionQuality': quality + "sourceName": name, + "imageFormat": img_format, + "imageFilePath": file_path, + "imageWidth": width, + "imageHeight": height, + "imageCompressionQuality": quality, } - response = self.base_client.req('SaveSourceScreenshot', payload) + response = self.base_client.req("SaveSourceScreenshot", payload) return response def GetSceneList(self): """ Gets a list of all scenes in OBS. - + """ - response = self.base_client.req('GetSceneList') + response = self.base_client.req("GetSceneList") return response - + def GetGroupList(self): """ Gets a list of all groups in OBS. - Groups in OBS are actually scenes, - but renamed and modified. In obs-websocket, + Groups in OBS are actually scenes, + but renamed and modified. In obs-websocket, we treat them as scenes where we can.. - + """ - response = self.base_client.req('GetSceneList') + response = self.base_client.req("GetSceneList") return response def GetCurrentProgramScene(self): @@ -510,7 +503,7 @@ class ReqClient(object): """ - response = self.base_client.req('GetCurrentProgramScene') + response = self.base_client.req("GetCurrentProgramScene") return response def SetCurrentProgramScene(self, name): @@ -522,17 +515,17 @@ class ReqClient(object): """ - payload = {'sceneName': name} - response = self.base_client.req('SetCurrentProgramScene', payload) + payload = {"sceneName": name} + response = self.base_client.req("SetCurrentProgramScene", payload) return response def GetCurrentPreviewScene(self): """ Gets the current preview scene - + """ - response = self.base_client.req('GetCurrentPreviewScene') + response = self.base_client.req("GetCurrentPreviewScene") return response def SetCurrentPreviewScene(self, name): @@ -544,8 +537,8 @@ class ReqClient(object): """ - payload = {'sceneName': name} - response = self.base_client.req('SetCurrentPreviewScene', payload) + payload = {"sceneName": name} + response = self.base_client.req("SetCurrentPreviewScene", payload) return response def CreateScene(self, name): @@ -557,8 +550,8 @@ class ReqClient(object): """ - payload = {'sceneName': name } - response = self.base_client.req('CreateScene', payload) + payload = {"sceneName": name} + response = self.base_client.req("CreateScene", payload) return response def RemoveScene(self, name): @@ -570,8 +563,8 @@ class ReqClient(object): """ - payload = {'sceneName': name } - response = self.base_client.req('RemoveScene', payload) + payload = {"sceneName": name} + response = self.base_client.req("RemoveScene", payload) return response def SetSceneName(self, old_name, new_name): @@ -585,11 +578,8 @@ class ReqClient(object): """ - payload = { - 'sceneName': old_name, - 'newSceneName': new_name - } - response = self.base_client.req('SetSceneName', payload) + payload = {"sceneName": old_name, "newSceneName": new_name} + response = self.base_client.req("SetSceneName", payload) return response def GetSceneSceneTransitionOverride(self, name): @@ -598,11 +588,11 @@ class ReqClient(object): :param name: Name of the scene :type name: str - + """ - payload = {'sceneName': name} - response = self.base_client.req('GetSceneSceneTransitionOverride', payload) + payload = {"sceneName": name} + response = self.base_client.req("GetSceneSceneTransitionOverride", payload) return response def SetSceneSceneTransitionOverride(self, scene_name, tr_name, tr_duration): @@ -619,11 +609,11 @@ class ReqClient(object): """ payload = { - 'sceneName': scene_name, - 'transitionName': tr_name, - 'transitionDuration': tr_duration - } - response = self.base_client.req('SetSceneSceneTransitionOverride', payload) + "sceneName": scene_name, + "transitionName": tr_name, + "transitionDuration": tr_duration, + } + response = self.base_client.req("SetSceneSceneTransitionOverride", payload) return response def GetInputList(self, kind): @@ -632,11 +622,11 @@ class ReqClient(object): :param kind: Restrict the list to only inputs of the specified kind :type kind: str - + """ - payload = {'inputKind': kind} - response = self.base_client.req('GetInputList', payload) + payload = {"inputKind": kind} + response = self.base_client.req("GetInputList", payload) return response def GetInputKindList(self, unversioned): @@ -645,11 +635,11 @@ class ReqClient(object): :param unversioned: True == Return all kinds as unversioned, False == Return with version suffixes (if available) :type unversioned: bool - + """ - payload = {'unversioned': unversioned} - response = self.base_client.req('GetInputKindList', payload) + payload = {"unversioned": unversioned} + response = self.base_client.req("GetInputKindList", payload) return response def GetSpecialInputs(self): @@ -658,10 +648,12 @@ class ReqClient(object): """ - response = self.base_client.req('GetSpecialInputs') + response = self.base_client.req("GetSpecialInputs") return response - def CreateInput(self, sceneName, inputName, inputKind, inputSettings, sceneItemEnabled): + def CreateInput( + self, sceneName, inputName, inputKind, inputSettings, sceneItemEnabled + ): """ Creates a new input, adding it as a scene item to the specified scene. @@ -675,17 +667,17 @@ class ReqClient(object): :type inputSettings: object :param sceneItemEnabled: Whether to set the created scene item to enabled or disabled :type sceneItemEnabled: bool - + """ payload = { - 'sceneName': sceneName, - 'inputName': inputName, - 'inputKind': inputKind, - 'inputSettings': inputSettings, - 'sceneItemEnabled': sceneItemEnabled + "sceneName": sceneName, + "inputName": inputName, + "inputKind": inputKind, + "inputSettings": inputSettings, + "sceneItemEnabled": sceneItemEnabled, } - response = self.base_client.req('CreateInput', payload) + response = self.base_client.req("CreateInput", payload) return response def RemoveInput(self, name): @@ -697,8 +689,8 @@ class ReqClient(object): """ - payload = {'inputName': name} - response = self.base_client.req('RemoveInput', payload) + payload = {"inputName": name} + response = self.base_client.req("RemoveInput", payload) return response def SetInputName(self, old_name, new_name): @@ -712,11 +704,8 @@ class ReqClient(object): """ - payload = { - 'inputName': old_name, - 'newInputName': new_name - } - response = self.base_client.req('SetInputName', payload) + payload = {"inputName": old_name, "newInputName": new_name} + response = self.base_client.req("SetInputName", payload) return response def GetInputDefaultSettings(self, kind): @@ -725,26 +714,26 @@ class ReqClient(object): :param kind: Input kind to get the default settings for :type kind: str - + """ - payload = {'inputKind': kind} - response = self.base_client.req('GetInputDefaultSettings', payload) + payload = {"inputKind": kind} + response = self.base_client.req("GetInputDefaultSettings", payload) return response def GetInputSettings(self, name): """ Gets the settings of an input. - Note: Does not include defaults. To create the entire settings object, + Note: Does not include defaults. To create the entire settings object, overlay inputSettings over the defaultInputSettings provided by GetInputDefaultSettings. :param name: Input kind to get the default settings for :type name: str - + """ - payload = {'inputName': name} - response = self.base_client.req('GetInputSettings', payload) + payload = {"inputName": name} + response = self.base_client.req("GetInputSettings", payload) return response def SetInputSettings(self, name, settings, overlay): @@ -757,15 +746,11 @@ class ReqClient(object): :type settings: dict :param overlay: True == apply the settings on top of existing ones, False == reset the input to its defaults, then apply settings. :type overlay: bool - + """ - payload = { - 'inputName': name, - 'inputSettings': settings, - 'overlay': overlay - } - response = self.base_client.req('SetInputSettings', payload) + payload = {"inputName": name, "inputSettings": settings, "overlay": overlay} + response = self.base_client.req("SetInputSettings", payload) return response def GetInputMute(self, name): @@ -774,11 +759,11 @@ class ReqClient(object): :param name: Name of input to get the mute state of :type name: str - + """ - payload = {'inputName': name} - response = self.base_client.req('GetInputMute', payload) + payload = {"inputName": name} + response = self.base_client.req("GetInputMute", payload) return response def SetInputMute(self, name, muted): @@ -792,11 +777,8 @@ class ReqClient(object): """ - payload = { - 'inputName': name, - 'inputMuted': muted - } - response = self.base_client.req('SetInputMute', payload) + payload = {"inputName": name, "inputMuted": muted} + response = self.base_client.req("SetInputMute", payload) return response def ToggleInputMute(self, name): @@ -805,11 +787,11 @@ class ReqClient(object): :param name: Name of the input to toggle the mute state of :type name: str - + """ - payload = {'inputName': name} - response = self.base_client.req('ToggleInputMute', payload) + payload = {"inputName": name} + response = self.base_client.req("ToggleInputMute", payload) return response def GetInputVolume(self, name): @@ -818,11 +800,11 @@ class ReqClient(object): :param name: Name of the input to get the volume of :type name: str - + """ - payload = {'inputName': name} - response = self.base_client.req('GetInputVolume', payload) + payload = {"inputName": name} + response = self.base_client.req("GetInputVolume", payload) return response def SetInputVolume(self, name, vol_mul=None, vol_db=None): @@ -839,30 +821,30 @@ class ReqClient(object): """ payload = { - 'inputName': name, - 'inputVolumeMul': vol_mul, - 'inputVolumeDb': vol_db + "inputName": name, + "inputVolumeMul": vol_mul, + "inputVolumeDb": vol_db, } - response = self.base_client.req('SetInputVolume', payload) + response = self.base_client.req("SetInputVolume", payload) return response def GetInputAudioBalance(self, name): """ Gets the audio balance of an input. - + :param name: Name of the input to get the audio balance of :type name: str - + """ - payload = {'inputName': name} - response = self.base_client.req('GetInputAudioBalance', payload) + payload = {"inputName": name} + response = self.base_client.req("GetInputAudioBalance", payload) return response def SetInputAudioBalance(self, name, balance): """ Sets the audio balance of an input. - + :param name: Name of the input to get the audio balance of :type name: str :param balance: New audio balance value (>= 0.0, <= 1.0) @@ -870,30 +852,27 @@ class ReqClient(object): """ - payload = { - 'inputName': name, - 'inputAudioBalance': balance - } - response = self.base_client.req('SetInputAudioBalance', payload) + payload = {"inputName": name, "inputAudioBalance": balance} + response = self.base_client.req("SetInputAudioBalance", payload) return response def GetInputAudioOffset(self, name): """ Gets the audio sync offset of an input. - + :param name: Name of the input to get the audio sync offset of :type name: str - + """ - payload = {'inputName': name} - response = self.base_client.req('GetInputAudioOffset', payload) + payload = {"inputName": name} + response = self.base_client.req("GetInputAudioOffset", payload) return response def SetInputAudioSyncOffset(self, name, offset): """ Sets the audio sync offset of an input. - + :param name: Name of the input to set the audio sync offset of :type name: str :param offset: New audio sync offset in milliseconds (>= -950, <= 20000) @@ -901,11 +880,8 @@ class ReqClient(object): """ - payload = { - 'inputName': name, - 'inputAudioSyncOffset': offset - } - response = self.base_client.req('SetInputAudioSyncOffset', payload) + payload = {"inputName": name, "inputAudioSyncOffset": offset} + response = self.base_client.req("SetInputAudioSyncOffset", payload) return response def GetInputAudioMonitorType(self, name): @@ -917,20 +893,20 @@ class ReqClient(object): OBS_MONITORING_TYPE_MONITOR_ONLY OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT - + :param name: Name of the input to get the audio monitor type of :type name: str - + """ - payload = {'inputName': name} - response = self.base_client.req('GetInputAudioMonitorType', payload) + payload = {"inputName": name} + response = self.base_client.req("GetInputAudioMonitorType", payload) return response def SetInputAudioMonitorType(self, name, mon_type): """ Sets the audio monitor type of an input. - + :param name: Name of the input to set the audio monitor type of :type name: str :param mon_type: Audio monitor type @@ -938,11 +914,8 @@ class ReqClient(object): """ - payload = { - 'inputName': name, - 'monitorType': mon_type - } - response = self.base_client.req('SetInputAudioMonitorType', payload) + payload = {"inputName": name, "monitorType": mon_type} + response = self.base_client.req("SetInputAudioMonitorType", payload) return response def GetInputAudioTracks(self, name): @@ -951,17 +924,17 @@ class ReqClient(object): :param name: Name of the input :type name: str - + """ - payload = {'inputName': name} - response = self.base_client.req('GetInputAudioTracks', payload) + payload = {"inputName": name} + response = self.base_client.req("GetInputAudioTracks", payload) return response def SetInputAudioTracks(self, name, track): """ Sets the audio monitor type of an input. - + :param name: Name of the input :type name: str :param track: Track settings to apply @@ -969,39 +942,33 @@ class ReqClient(object): """ - payload = { - 'inputName': name, - 'inputAudioTracks': track - } - response = self.base_client.req('SetInputAudioTracks', payload) + payload = {"inputName": name, "inputAudioTracks": track} + response = self.base_client.req("SetInputAudioTracks", payload) return response def GetInputPropertiesListPropertyItems(self, input_name, prop_name): """ Gets the items of a list property from an input's properties. - Note: Use this in cases where an input provides a dynamic, - selectable list of items. For example, display capture, + Note: Use this in cases where an input provides a dynamic, + selectable list of items. For example, display capture, where it provides a list of available displays. :param input_name: Name of the input :type input_name: str :param prop_name: Name of the list property to get the items of :type prop_name: str - + """ - payload = { - 'inputName': input_name, - 'propertyName': prop_name - } - response = self.base_client.req('GetInputPropertiesListPropertyItems', payload) + payload = {"inputName": input_name, "propertyName": prop_name} + response = self.base_client.req("GetInputPropertiesListPropertyItems", payload) return response def PressInputPropertiesButton(self, input_name, prop_name): """ Presses a button in the properties of an input. - Note: Use this in cases where there is a button - in the properties of an input that cannot be accessed in any other way. + Note: Use this in cases where there is a button + in the properties of an input that cannot be accessed in any other way. For example, browser sources, where there is a refresh button. :param input_name: Name of the input @@ -1011,39 +978,36 @@ class ReqClient(object): """ - payload = { - 'inputName': input_name, - 'propertyName': prop_name - } - response = self.base_client.req('PressInputPropertiesButton', payload) + payload = {"inputName": input_name, "propertyName": prop_name} + response = self.base_client.req("PressInputPropertiesButton", payload) return response def GetTransitionKindList(self): """ Gets an array of all available transition kinds. Similar to GetInputKindList - + """ - response = self.base_client.req('GetTransitionKindList') + response = self.base_client.req("GetTransitionKindList") return response def GetSceneTransitionList(self): """ Gets an array of all scene transitions in OBS. - + """ - response = self.base_client.req('GetSceneTransitionList') + response = self.base_client.req("GetSceneTransitionList") return response def GetCurrentSceneTransition(self): """ Gets an array of all scene transitions in OBS. - + """ - response = self.base_client.req('GetCurrentSceneTransition') + response = self.base_client.req("GetCurrentSceneTransition") return response def SetCurrentSceneTransition(self, name): @@ -1057,10 +1021,10 @@ class ReqClient(object): """ - payload = {'transitionName': name} - response = self.base_client.req('SetCurrentSceneTransition', payload) + payload = {"transitionName": name} + response = self.base_client.req("SetCurrentSceneTransition", payload) return response - + def SetCurrentSceneTransitionDuration(self, duration): """ Sets the duration of the current scene transition, if it is not fixed. @@ -1070,8 +1034,8 @@ class ReqClient(object): """ - payload = {'transitionDuration': duration} - response = self.base_client.req('SetCurrentSceneTransitionDuration', payload) + payload = {"transitionDuration": duration} + response = self.base_client.req("SetCurrentSceneTransitionDuration", payload) return response def SetCurrentSceneTransitionSettings(self, settings, overlay=None): @@ -1085,39 +1049,36 @@ class ReqClient(object): """ - payload = { - 'transitionSettings': settings, - 'overlay': overlay - } - response = self.base_client.req('SetCurrentSceneTransitionSettings', payload) + payload = {"transitionSettings": settings, "overlay": overlay} + response = self.base_client.req("SetCurrentSceneTransitionSettings", payload) return response def GetCurrentSceneTransitionCursor(self): """ Gets the cursor position of the current scene transition. Note: transitionCursor will return 1.0 when the transition is inactive. - + """ - response = self.base_client.req('GetCurrentSceneTransitionCursor') + response = self.base_client.req("GetCurrentSceneTransitionCursor") return response def TriggerStudioModeTransition(self): """ - Triggers the current scene transition. + Triggers the current scene transition. Same functionality as the Transition button in studio mode. - Note: Studio mode should be active. if not throws an + Note: Studio mode should be active. if not throws an RequestStatus::StudioModeNotActive (506) in response """ - response = self.base_client.req('TriggerStudioModeTransition') + response = self.base_client.req("TriggerStudioModeTransition") return response def SetTBarPosition(self, pos, release=None): """ Sets the position of the TBar. - Very important note: This will be deprecated + Very important note: This will be deprecated and replaced in a future version of obs-websocket. :param pos: New position (>= 0.0, <= 1.0) @@ -1127,11 +1088,8 @@ class ReqClient(object): """ - payload = { - 'position': pos, - 'release': release - } - response = self.base_client.req('SetTBarPosition', payload) + payload = {"position": pos, "release": release} + response = self.base_client.req("SetTBarPosition", payload) return response def GetSourceFilterList(self, name): @@ -1140,11 +1098,11 @@ class ReqClient(object): :param name: Name of the source :type name: str - + """ - payload = {'sourceName': name} - response = self.base_client.req('GetSourceFilterList', payload) + payload = {"sourceName": name} + response = self.base_client.req("GetSourceFilterList", payload) return response def GetSourceFilterDefaultSettings(self, kind): @@ -1153,14 +1111,16 @@ class ReqClient(object): :param kind: Filter kind to get the default settings for :type kind: str - + """ - payload = {'filterKind': kind} - response = self.base_client.req('GetSourceFilterDefaultSettings', payload) + payload = {"filterKind": kind} + response = self.base_client.req("GetSourceFilterDefaultSettings", payload) return response - def CreateSourceFilter(self, source_name, filter_name, filter_kind, filter_settings=None): + def CreateSourceFilter( + self, source_name, filter_name, filter_kind, filter_settings=None + ): """ Gets the default settings for a filter kind. @@ -1176,12 +1136,12 @@ class ReqClient(object): """ payload = { - 'sourceName': source_name, - 'filterName': filter_name, - 'filterKind': filter_kind, - 'filterSettings': filter_settings + "sourceName": source_name, + "filterName": filter_name, + "filterKind": filter_kind, + "filterSettings": filter_settings, } - response = self.base_client.req('CreateSourceFilter', payload) + response = self.base_client.req("CreateSourceFilter", payload) return response def RemoveSourceFilter(self, source_name, filter_name): @@ -1196,10 +1156,10 @@ class ReqClient(object): """ payload = { - 'sourceName': source_name, - 'filterName': filter_name, + "sourceName": source_name, + "filterName": filter_name, } - response = self.base_client.req('RemoveSourceFilter', payload) + response = self.base_client.req("RemoveSourceFilter", payload) return response def SetSourceFilterName(self, source_name, old_filter_name, new_filter_name): @@ -1216,11 +1176,11 @@ class ReqClient(object): """ payload = { - 'sourceName': source_name, - 'filterName': old_filter_name, - 'newFilterName': new_filter_name, + "sourceName": source_name, + "filterName": old_filter_name, + "newFilterName": new_filter_name, } - response = self.base_client.req('SetSourceFilterName', payload) + response = self.base_client.req("SetSourceFilterName", payload) return response def GetSourceFilter(self, source_name, filter_name): @@ -1231,14 +1191,11 @@ class ReqClient(object): :type source_name: str :param filter_name: Name of the filter :type filter_name: str - + """ - payload = { - 'sourceName': source_name, - 'filterName': filter_name - } - response = self.base_client.req('GetSourceFilter', payload) + payload = {"sourceName": source_name, "filterName": filter_name} + response = self.base_client.req("GetSourceFilter", payload) return response def SetSourceFilterIndex(self, source_name, filter_name, filter_index): @@ -1255,11 +1212,11 @@ class ReqClient(object): """ payload = { - 'sourceName': source_name, - 'filterName': filter_name, - 'filterIndex': filter_index + "sourceName": source_name, + "filterName": filter_name, + "filterIndex": filter_index, } - response = self.base_client.req('SetSourceFilterIndex', payload) + response = self.base_client.req("SetSourceFilterIndex", payload) return response def SetSourceFilterSettings(self, source_name, filter_name, settings, overlay=None): @@ -1278,12 +1235,12 @@ class ReqClient(object): """ payload = { - 'sourceName': source_name, - 'filterName': filter_name, - 'filterSettings': settings, - 'overlay': overlay + "sourceName": source_name, + "filterName": filter_name, + "filterSettings": settings, + "overlay": overlay, } - response = self.base_client.req('SetSourceFilterSettings', payload) + response = self.base_client.req("SetSourceFilterSettings", payload) return response def SetSourceFilterEnabled(self, source_name, filter_name, enabled): @@ -1300,11 +1257,11 @@ class ReqClient(object): """ payload = { - 'sourceName': source_name, - 'filterName': filter_name, - 'filterEnabled': enabled + "sourceName": source_name, + "filterName": filter_name, + "filterEnabled": enabled, } - response = self.base_client.req('SetSourceFilterEnabled', payload) + response = self.base_client.req("SetSourceFilterEnabled", payload) return response def GetSceneItemList(self, name): @@ -1313,11 +1270,11 @@ class ReqClient(object): :param name: Name of the scene to get the items of :type name: str - + """ - payload = {'sceneName': name} - response = self.base_client.req('GetSceneItemList', payload) + payload = {"sceneName": name} + response = self.base_client.req("GetSceneItemList", payload) return response def GetGroupItemList(self, name): @@ -1326,11 +1283,11 @@ class ReqClient(object): :param name: Name of the group to get the items of :type name: str - + """ - payload = {'sceneName': name} - response = self.base_client.req('GetGroupItemList', payload) + payload = {"sceneName": name} + response = self.base_client.req("GetGroupItemList", payload) return response def GetSceneItemId(self, scene_name, source_name, offset=None): @@ -1343,15 +1300,15 @@ class ReqClient(object): :type source_name: str :param offset: Number of matches to skip during search. >= 0 means first forward. -1 means last (top) item (>= -1) :type offset: int - + """ payload = { - 'sceneName': scene_name, - 'sourceName': source_name, - 'searchOffset': offset + "sceneName": scene_name, + "sourceName": source_name, + "searchOffset": offset, } - response = self.base_client.req('GetSceneItemId', payload) + response = self.base_client.req("GetSceneItemId", payload) return response def CreateSceneItem(self, scene_name, source_name, enabled=None): @@ -1365,15 +1322,15 @@ class ReqClient(object): :type source_name: str :param enabled: Enable state to apply to the scene item on creation :type enabled: bool - + """ payload = { - 'sceneName': scene_name, - 'sourceName': source_name, - 'sceneItemEnabled': enabled + "sceneName": scene_name, + "sourceName": source_name, + "sceneItemEnabled": enabled, } - response = self.base_client.req('CreateSceneItem', payload) + response = self.base_client.req("CreateSceneItem", payload) return response def RemoveSceneItem(self, scene_name, item_id): @@ -1389,10 +1346,10 @@ class ReqClient(object): """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, + "sceneName": scene_name, + "sceneItemId": item_id, } - response = self.base_client.req('RemoveSceneItem', payload) + response = self.base_client.req("RemoveSceneItem", payload) return response def DuplicateSceneItem(self, scene_name, item_id, dest_scene_name=None): @@ -1406,15 +1363,15 @@ class ReqClient(object): :type item_id: int :param dest_scene_name: Name of the scene to create the duplicated item in :type dest_scene_name: str - + """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, - 'destinationSceneName': dest_scene_name + "sceneName": scene_name, + "sceneItemId": item_id, + "destinationSceneName": dest_scene_name, } - response = self.base_client.req('DuplicateSceneItem', payload) + response = self.base_client.req("DuplicateSceneItem", payload) return response def GetSceneItemTransform(self, scene_name, item_id): @@ -1426,14 +1383,14 @@ class ReqClient(object): :type scene_name: str :param item_id: Numeric ID of the scene item (>= 0) :type item_id: int - + """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, + "sceneName": scene_name, + "sceneItemId": item_id, } - response = self.base_client.req('GetSceneItemTransform', payload) + response = self.base_client.req("GetSceneItemTransform", payload) return response def SetSceneItemTransform(self, scene_name, item_id, transform): @@ -1448,11 +1405,11 @@ class ReqClient(object): :type transform: dict """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, - 'sceneItemTransform': transform + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemTransform": transform, } - response = self.base_client.req('SetSceneItemTransform', payload) + response = self.base_client.req("SetSceneItemTransform", payload) return response def GetSceneItemEnabled(self, scene_name, item_id): @@ -1464,14 +1421,14 @@ class ReqClient(object): :type scene_name: str :param item_id: Numeric ID of the scene item (>= 0) :type item_id: int - + """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, + "sceneName": scene_name, + "sceneItemId": item_id, } - response = self.base_client.req('GetSceneItemEnabled', payload) + response = self.base_client.req("GetSceneItemEnabled", payload) return response def SetSceneItemEnabled(self, scene_name, item_id, enabled): @@ -1489,11 +1446,11 @@ class ReqClient(object): """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, - 'sceneItemEnabled': enabled + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemEnabled": enabled, } - response = self.base_client.req('SetSceneItemEnabled', payload) + response = self.base_client.req("SetSceneItemEnabled", payload) return response def GetSceneItemLocked(self, scene_name, item_id): @@ -1505,14 +1462,14 @@ class ReqClient(object): :type scene_name: str :param item_id: Numeric ID of the scene item (>= 0) :type item_id: int - + """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, + "sceneName": scene_name, + "sceneItemId": item_id, } - response = self.base_client.req('GetSceneItemLocked', payload) + response = self.base_client.req("GetSceneItemLocked", payload) return response def SetSceneItemLocked(self, scene_name, item_id, locked): @@ -1530,11 +1487,11 @@ class ReqClient(object): """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, - 'sceneItemLocked': locked + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemLocked": locked, } - response = self.base_client.req('SetSceneItemLocked', payload) + response = self.base_client.req("SetSceneItemLocked", payload) return response def GetSceneItemIndex(self, scene_name, item_id): @@ -1547,14 +1504,14 @@ class ReqClient(object): :type scene_name: str :param item_id: Numeric ID of the scene item (>= 0) :type item_id: int - + """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, + "sceneName": scene_name, + "sceneItemId": item_id, } - response = self.base_client.req('GetSceneItemIndex', payload) + response = self.base_client.req("GetSceneItemIndex", payload) return response def SetSceneItemIndex(self, scene_name, item_id, item_index): @@ -1572,18 +1529,18 @@ class ReqClient(object): """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, - 'sceneItemLocked': item_index + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemLocked": item_index, } - response = self.base_client.req('SetSceneItemIndex', payload) + response = self.base_client.req("SetSceneItemIndex", payload) return response def GetSceneItemBlendMode(self, scene_name, item_id): """ Gets the blend mode of a scene item. Blend modes: - + OBS_BLEND_NORMAL OBS_BLEND_ADDITIVE OBS_BLEND_SUBTRACT @@ -1597,14 +1554,14 @@ class ReqClient(object): :type scene_name: str :param item_id: Numeric ID of the scene item (>= 0) :type item_id: int - + """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, + "sceneName": scene_name, + "sceneItemId": item_id, } - response = self.base_client.req('GetSceneItemBlendMode', payload) + response = self.base_client.req("GetSceneItemBlendMode", payload) return response def SetSceneItemBlendMode(self, scene_name, item_id, blend): @@ -1622,29 +1579,29 @@ class ReqClient(object): """ payload = { - 'sceneName': scene_name, - 'sceneItemId': item_id, - 'sceneItemBlendMode': blend + "sceneName": scene_name, + "sceneItemId": item_id, + "sceneItemBlendMode": blend, } - response = self.base_client.req('SetSceneItemBlendMode', payload) + response = self.base_client.req("SetSceneItemBlendMode", payload) return response def GetVirtualCamStatus(self): """ Gets the status of the virtualcam output. - + """ - response = self.base_client.req('GetVirtualCamStatus') + response = self.base_client.req("GetVirtualCamStatus") return response def ToggleVirtualCam(self): """ Toggles the state of the virtualcam output. - + """ - response = self.base_client.req('ToggleVirtualCam') + response = self.base_client.req("ToggleVirtualCam") return response def StartVirtualCam(self): @@ -1653,7 +1610,7 @@ class ReqClient(object): """ - response = self.base_client.req('StartVirtualCam') + response = self.base_client.req("StartVirtualCam") return response def StopVirtualCam(self): @@ -1662,7 +1619,7 @@ class ReqClient(object): """ - response = self.base_client.req('StopVirtualCam') + response = self.base_client.req("StopVirtualCam") return response def GetReplayBufferStatus(self): @@ -1671,16 +1628,16 @@ class ReqClient(object): """ - response = self.base_client.req('GetReplayBufferStatus') + response = self.base_client.req("GetReplayBufferStatus") return response def ToggleReplayBuffer(self): """ Toggles the state of the replay buffer output. - + """ - response = self.base_client.req('ToggleReplayBuffer') + response = self.base_client.req("ToggleReplayBuffer") return response def StartReplayBuffer(self): @@ -1689,7 +1646,7 @@ class ReqClient(object): """ - response = self.base_client.req('StartReplayBuffer') + response = self.base_client.req("StartReplayBuffer") return response def StopReplayBuffer(self): @@ -1698,7 +1655,7 @@ class ReqClient(object): """ - response = self.base_client.req('StopReplayBuffer') + response = self.base_client.req("StopReplayBuffer") return response def SaveReplayBuffer(self): @@ -1707,34 +1664,34 @@ class ReqClient(object): """ - response = self.base_client.req('SaveReplayBuffer') + response = self.base_client.req("SaveReplayBuffer") return response def GetLastReplayBufferReplay(self): """ Gets the filename of the last replay buffer save file. - + """ - response = self.base_client.req('GetLastReplayBufferReplay') + response = self.base_client.req("GetLastReplayBufferReplay") return response def GetStreamStatus(self): """ Gets the status of the stream output. - + """ - response = self.base_client.req('GetStreamStatus') + response = self.base_client.req("GetStreamStatus") return response def ToggleStream(self): """ Toggles the status of the stream output. - + """ - response = self.base_client.req('ToggleStream') + response = self.base_client.req("ToggleStream") return response def StartStream(self): @@ -1743,7 +1700,7 @@ class ReqClient(object): """ - response = self.base_client.req('StartStream') + response = self.base_client.req("StartStream") return response def StopStream(self): @@ -1752,7 +1709,7 @@ class ReqClient(object): """ - response = self.base_client.req('StopStream') + response = self.base_client.req("StopStream") return response def SendStreamCaption(self, caption): @@ -1764,16 +1721,16 @@ class ReqClient(object): """ - response = self.base_client.req('SendStreamCaption') + response = self.base_client.req("SendStreamCaption") return response def GetRecordStatus(self): """ Gets the status of the record output. - + """ - response = self.base_client.req('GetRecordStatus') + response = self.base_client.req("GetRecordStatus") return response def ToggleRecord(self): @@ -1782,7 +1739,7 @@ class ReqClient(object): """ - response = self.base_client.req('ToggleRecord') + response = self.base_client.req("ToggleRecord") return response def StartRecord(self): @@ -1791,7 +1748,7 @@ class ReqClient(object): """ - response = self.base_client.req('StartRecord') + response = self.base_client.req("StartRecord") return response def StopRecord(self): @@ -1800,7 +1757,7 @@ class ReqClient(object): """ - response = self.base_client.req('StopRecord') + response = self.base_client.req("StopRecord") return response def ToggleRecordPause(self): @@ -1809,7 +1766,7 @@ class ReqClient(object): """ - response = self.base_client.req('ToggleRecordPause') + response = self.base_client.req("ToggleRecordPause") return response def PauseRecord(self): @@ -1818,7 +1775,7 @@ class ReqClient(object): """ - response = self.base_client.req('PauseRecord') + response = self.base_client.req("PauseRecord") return response def ResumeRecord(self): @@ -1827,7 +1784,7 @@ class ReqClient(object): """ - response = self.base_client.req('ResumeRecord') + response = self.base_client.req("ResumeRecord") return response def GetMediaInputStatus(self, name): @@ -1849,8 +1806,8 @@ class ReqClient(object): """ - payload = {'inputName': name} - response = self.base_client.req('GetMediaInputStatus', payload) + payload = {"inputName": name} + response = self.base_client.req("GetMediaInputStatus", payload) return response def SetMediaInputCursor(self, name, cursor): @@ -1865,11 +1822,8 @@ class ReqClient(object): """ - payload = { - 'inputName': name, - 'mediaCursor': cursor - } - response = self.base_client.req('SetMediaInputCursor', payload) + payload = {"inputName": name, "mediaCursor": cursor} + response = self.base_client.req("SetMediaInputCursor", payload) return response def OffsetMediaInputCursor(self, name, offset): @@ -1884,11 +1838,8 @@ class ReqClient(object): """ - payload = { - 'inputName': name, - 'mediaCursorOffset': offset - } - response = self.base_client.req('OffsetMediaInputCursor', payload) + payload = {"inputName": name, "mediaCursorOffset": offset} + response = self.base_client.req("OffsetMediaInputCursor", payload) return response def TriggerMediaInputAction(self, name, action): @@ -1902,20 +1853,17 @@ class ReqClient(object): """ - payload = { - 'inputName': name, - 'mediaAction': action - } - response = self.base_client.req('TriggerMediaInputAction', payload) + payload = {"inputName": name, "mediaAction": action} + response = self.base_client.req("TriggerMediaInputAction", payload) return response def GetStudioModeEnabled(self): """ Gets whether studio is enabled. - + """ - response = self.base_client.req('GetStudioModeEnabled') + response = self.base_client.req("GetStudioModeEnabled") return response def SetStudioModeEnabled(self, enabled): @@ -1927,8 +1875,8 @@ class ReqClient(object): """ - payload = {'studioModeEnabled': enabled} - response = self.base_client.req('SetStudioModeEnabled', payload) + payload = {"studioModeEnabled": enabled} + response = self.base_client.req("SetStudioModeEnabled", payload) return response def OpenInputPropertiesDialog(self, name): @@ -1940,8 +1888,8 @@ class ReqClient(object): """ - payload = {'inputName': name} - response = self.base_client.req('OpenInputPropertiesDialog', payload) + payload = {"inputName": name} + response = self.base_client.req("OpenInputPropertiesDialog", payload) return response def OpenInputFiltersDialog(self, name): @@ -1953,8 +1901,8 @@ class ReqClient(object): """ - payload = {'inputName': name} - response = self.base_client.req('OpenInputFiltersDialog', payload) + payload = {"inputName": name} + response = self.base_client.req("OpenInputFiltersDialog", payload) return response def OpenInputInteractDialog(self, name): @@ -1966,15 +1914,15 @@ class ReqClient(object): """ - payload = {'inputName': name} - response = self.base_client.req('OpenInputInteractDialog', payload) + payload = {"inputName": name} + response = self.base_client.req("OpenInputInteractDialog", payload) return response def GetMonitorList(self, name): """ Gets a list of connected monitors and information about them. - + """ - response = self.base_client.req('GetMonitorList') - return response \ No newline at end of file + response = self.base_client.req("GetMonitorList") + return response