mirror of
https://github.com/onyx-and-iris/obsws-python.git
synced 2024-11-22 12:50:53 +00:00
Merge pull request #16 from onyx-and-iris/dev
add values to defaultkwargs, fix event names in readme + other minor additions
This commit is contained in:
commit
ce6873f57a
51
README.md
51
README.md
@ -12,7 +12,7 @@ Not all endpoints in the official documentation are implemented.
|
|||||||
|
|
||||||
- [OBS Studio](https://obsproject.com/)
|
- [OBS Studio](https://obsproject.com/)
|
||||||
- [OBS Websocket v5 Plugin](https://github.com/obsproject/obs-websocket/releases/tag/5.0.0)
|
- [OBS Websocket v5 Plugin](https://github.com/obsproject/obs-websocket/releases/tag/5.0.0)
|
||||||
- With the release of OBS Studio version 28, Websocket plugin is included by default. But it should be manually installed for earlier versions of OBS.
|
- With the release of OBS Studio version 28, Websocket plugin is included by default. But it should be manually installed for earlier versions of OBS.
|
||||||
- Python 3.10 or greater
|
- Python 3.10 or greater
|
||||||
|
|
||||||
### How to install using pip
|
### How to install using pip
|
||||||
@ -23,7 +23,19 @@ pip install obsws-python
|
|||||||
|
|
||||||
### How to Use
|
### How to Use
|
||||||
|
|
||||||
Load connection info from toml config. A valid `config.toml` might look like this:
|
By default the clients connect with parameters:
|
||||||
|
|
||||||
|
- `host`: "localhost"
|
||||||
|
- `port`: 4455
|
||||||
|
- `password`: None
|
||||||
|
|
||||||
|
You may override these parameters by storing them in a toml config file or passing them as keyword arguments.
|
||||||
|
|
||||||
|
Order of precedence: keyword arguments then config file then default values.
|
||||||
|
|
||||||
|
#### `config file`
|
||||||
|
|
||||||
|
A valid `config.toml` might look like this:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[connection]
|
[connection]
|
||||||
@ -36,12 +48,6 @@ It should be placed next to your `__main__.py` file.
|
|||||||
|
|
||||||
#### Otherwise:
|
#### Otherwise:
|
||||||
|
|
||||||
Import and start using, keyword arguments are as follows:
|
|
||||||
|
|
||||||
- `host`: obs websocket server
|
|
||||||
- `port`: port to access server
|
|
||||||
- `password`: obs websocket server password
|
|
||||||
|
|
||||||
Example `__main__.py`:
|
Example `__main__.py`:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@ -75,7 +81,7 @@ For a full list of requests refer to [Requests](https://github.com/obsproject/ob
|
|||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
When registering a function callback use the name of the expected API event in snake case form.
|
When registering a callback function use the name of the expected API event in snake case form, prepended with "on\_".
|
||||||
|
|
||||||
example:
|
example:
|
||||||
|
|
||||||
@ -83,23 +89,23 @@ example:
|
|||||||
# load conn info from config.toml
|
# load conn info from config.toml
|
||||||
cl = obs.EventClient()
|
cl = obs.EventClient()
|
||||||
|
|
||||||
def scene_created(data):
|
def on_scene_created(data):
|
||||||
...
|
...
|
||||||
|
|
||||||
# SceneCreated
|
# SceneCreated
|
||||||
cl.callback.register(scene_created)
|
cl.callback.register(on_scene_created)
|
||||||
|
|
||||||
def input_mute_state_changed(data):
|
def on_input_mute_state_changed(data):
|
||||||
...
|
...
|
||||||
|
|
||||||
# InputMuteStateChanged
|
# InputMuteStateChanged
|
||||||
cl.callback.register(input_mute_state_changed)
|
cl.callback.register(on_input_mute_state_changed)
|
||||||
|
|
||||||
# returns a list of currently registered events
|
# returns a list of currently registered events
|
||||||
print(cl.callback.get())
|
print(cl.callback.get())
|
||||||
|
|
||||||
# You may also deregister a callback
|
# You may also deregister a callback
|
||||||
cl.callback.deregister(input_mute_state_changed)
|
cl.callback.deregister(on_input_mute_state_changed)
|
||||||
```
|
```
|
||||||
|
|
||||||
`register(fns)` and `deregister(fns)` accept both single functions and lists of functions.
|
`register(fns)` and `deregister(fns)` accept both single functions and lists of functions.
|
||||||
@ -116,7 +122,7 @@ example:
|
|||||||
resp = cl.get_version()
|
resp = cl.get_version()
|
||||||
print(resp.attrs())
|
print(resp.attrs())
|
||||||
|
|
||||||
def scene_created(data):
|
def on_scene_created(data):
|
||||||
print(data.attrs())
|
print(data.attrs())
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -126,6 +132,21 @@ If a request fails an `OBSSDKError` will be raised with a status code.
|
|||||||
|
|
||||||
For a full list of status codes refer to [Codes](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requeststatus)
|
For a full list of status codes refer to [Codes](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requeststatus)
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
If you want to see the raw messages simply set log level to DEBUG
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import obsws_python as obs
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
### Tests
|
### Tests
|
||||||
|
|
||||||
First install development dependencies:
|
First install development dependencies:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from .version import version as __version__
|
|
||||||
from .enum import Subs
|
from .enum import Subs
|
||||||
from .events import EventClient
|
from .events import EventClient
|
||||||
from .reqs import ReqClient
|
from .reqs import ReqClient
|
||||||
|
from .version import version as __version__
|
||||||
|
|
||||||
__ALL__ = ["ReqClient", "EventClient", "Subs"]
|
__ALL__ = ["ReqClient", "EventClient", "Subs"]
|
||||||
|
@ -19,28 +19,30 @@ class ObsClient:
|
|||||||
logger = logging.getLogger("baseclient.obsclient")
|
logger = logging.getLogger("baseclient.obsclient")
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
defaultkwargs = {
|
defaultkwargs = {"host": "localhost", "port": 4455, "password": None, "subs": 0}
|
||||||
**{key: None for key in ["host", "port", "password"]},
|
if not any(key in kwargs for key in ("host", "port", "password")):
|
||||||
"subs": 0,
|
kwargs |= self._conn_from_toml()
|
||||||
}
|
|
||||||
kwargs = defaultkwargs | kwargs
|
kwargs = defaultkwargs | kwargs
|
||||||
for attr, val in kwargs.items():
|
for attr, val in kwargs.items():
|
||||||
setattr(self, attr, val)
|
setattr(self, attr, val)
|
||||||
if not (self.host and self.port):
|
|
||||||
conn = self._conn_from_toml()
|
self.logger.info(
|
||||||
self.host = conn["host"]
|
"Connecting with parameters: {host} {port} {password} {subs}".format(
|
||||||
self.port = conn["port"]
|
**self.__dict__
|
||||||
self.password = conn["password"]
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.ws = websocket.WebSocket()
|
self.ws = websocket.WebSocket()
|
||||||
self.ws.connect(f"ws://{self.host}:{self.port}")
|
self.ws.connect(f"ws://{self.host}:{self.port}")
|
||||||
self.server_hello = json.loads(self.ws.recv())
|
self.server_hello = json.loads(self.ws.recv())
|
||||||
|
|
||||||
def _conn_from_toml(self):
|
def _conn_from_toml(self) -> dict:
|
||||||
|
conn = {}
|
||||||
filepath = Path.cwd() / "config.toml"
|
filepath = Path.cwd() / "config.toml"
|
||||||
with open(filepath, "rb") as f:
|
if filepath.exists():
|
||||||
conn = tomllib.load(f)
|
with open(filepath, "rb") as f:
|
||||||
return conn["connection"]
|
conn = tomllib.load(f)
|
||||||
|
return conn["connection"] if "connection" in conn else conn
|
||||||
|
|
||||||
def authenticate(self):
|
def authenticate(self):
|
||||||
payload = {
|
payload = {
|
||||||
@ -52,6 +54,8 @@ class ObsClient:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if "authentication" in self.server_hello["d"]:
|
if "authentication" in self.server_hello["d"]:
|
||||||
|
if not self.password:
|
||||||
|
raise OBSSDKError("authentication enabled but no password provided")
|
||||||
secret = base64.b64encode(
|
secret = base64.b64encode(
|
||||||
hashlib.sha256(
|
hashlib.sha256(
|
||||||
(
|
(
|
||||||
@ -79,14 +83,13 @@ class ObsClient:
|
|||||||
raise OBSSDKError("failed to identify client with the server")
|
raise OBSSDKError("failed to identify client with the server")
|
||||||
|
|
||||||
def req(self, req_type, req_data=None):
|
def req(self, req_type, req_data=None):
|
||||||
id = randint(1, 1000)
|
|
||||||
self.logger.debug(f"Sending request with id {id}")
|
|
||||||
payload = {
|
payload = {
|
||||||
"op": 6,
|
"op": 6,
|
||||||
"d": {"requestType": req_type, "requestId": id},
|
"d": {"requestType": req_type, "requestId": randint(1, 1000)},
|
||||||
}
|
}
|
||||||
if req_data:
|
if req_data:
|
||||||
payload["d"]["requestData"] = req_data
|
payload["d"]["requestData"] = req_data
|
||||||
|
self.logger.debug(f"Sending request {payload}")
|
||||||
self.ws.send(json.dumps(payload))
|
self.ws.send(json.dumps(payload))
|
||||||
response = json.loads(self.ws.recv())
|
response = json.loads(self.ws.recv())
|
||||||
self.logger.debug(f"Response received {response}")
|
self.logger.debug(f"Response received {response}")
|
||||||
|
@ -75,7 +75,7 @@ class ReqClient:
|
|||||||
"""
|
"""
|
||||||
self.send("BroadcastCustomEvent", eventData)
|
self.send("BroadcastCustomEvent", eventData)
|
||||||
|
|
||||||
def call_vendor_request(self, vendorName, requestType, requestData=None):
|
def call_vendor_request(self, vendor_name, request_type, request_data=None):
|
||||||
"""
|
"""
|
||||||
Call a request registered to a vendor.
|
Call a request registered to a vendor.
|
||||||
|
|
||||||
@ -97,7 +97,10 @@ class ReqClient:
|
|||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return self.send(requestType, requestData)
|
payload = {"vendorName": vendor_name, "requestType": request_type}
|
||||||
|
if request_data:
|
||||||
|
payload["requestData"] = request_data
|
||||||
|
return self.send("CallVendorRequest", payload)
|
||||||
|
|
||||||
def get_hot_key_list(self):
|
def get_hot_key_list(self):
|
||||||
"""
|
"""
|
||||||
@ -110,6 +113,8 @@ class ReqClient:
|
|||||||
"""
|
"""
|
||||||
return self.send("GetHotkeyList")
|
return self.send("GetHotkeyList")
|
||||||
|
|
||||||
|
get_hotkey_list = get_hot_key_list
|
||||||
|
|
||||||
def trigger_hot_key_by_name(self, hotkeyName):
|
def trigger_hot_key_by_name(self, hotkeyName):
|
||||||
"""
|
"""
|
||||||
Triggers a hotkey using its name. For hotkey names
|
Triggers a hotkey using its name. For hotkey names
|
||||||
@ -123,6 +128,8 @@ class ReqClient:
|
|||||||
payload = {"hotkeyName": hotkeyName}
|
payload = {"hotkeyName": hotkeyName}
|
||||||
self.send("TriggerHotkeyByName", payload)
|
self.send("TriggerHotkeyByName", payload)
|
||||||
|
|
||||||
|
trigger_hotkey_by_name = trigger_hot_key_by_name
|
||||||
|
|
||||||
def trigger_hot_key_by_key_sequence(
|
def trigger_hot_key_by_key_sequence(
|
||||||
self, keyId, pressShift, pressCtrl, pressAlt, pressCmd
|
self, keyId, pressShift, pressCtrl, pressAlt, pressCmd
|
||||||
):
|
):
|
||||||
@ -155,6 +162,8 @@ class ReqClient:
|
|||||||
}
|
}
|
||||||
self.send("TriggerHotkeyByKeySequence", payload)
|
self.send("TriggerHotkeyByKeySequence", payload)
|
||||||
|
|
||||||
|
trigger_hotkey_by_key_sequence = trigger_hot_key_by_key_sequence
|
||||||
|
|
||||||
def sleep(self, sleepMillis=None, sleepFrames=None):
|
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.
|
||||||
|
@ -1 +1 @@
|
|||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user