Coder Social home page Coder Social logo

obs-websocket-py's People

Contributors

adirio avatar elektordi avatar picocentauri avatar thelan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

obs-websocket-py's Issues

No support for calling Virtual Camera on and off?

I noticed there doesn't seem to be the ability to control the Virtual Camera start and stopping. When I run GetStreamingStatus it returns a T/F value for the Vitrual camera but I couldn't call it on and off. I know it said not to edit the files but I was able to add Virtual Camera support with the addition of a few extra lines in the events and requests .py. Not sure if I did this completely correct but it's enabled control for me.

Events.py, pasted before "class StreamStarting(Baseevents):"

class VirtualCamStarted(Baseevents):
    """VirtualCam started successfully.

    """

    def __init__(self):
        Baseevents.__init__(self)
        self.name = 'VirtualCamStarted'



class VirtualCamStopped(Baseevents):
    """VirtualCam stopped successfully.

    """

    def __init__(self):
        Baseevents.__init__(self)
        self.name = 'VirtualCamStopped'

requests .py, note edits are marked

class GetStreamingStatus(Baserequests):
    """Get current streaming and recording status.

    :Returns:
       *streaming*
            type: boolean
            Current streaming status.
       *recording*
            type: boolean
            Current recording status.
       *stream_timecode*
            type: String (optional)
            Time elapsed since streaming started (only present if currently streaming).
       *rec_timecode*
            type: String (optional)
            Time elapsed since recording started (only present if currently recording).
       *preview_only*
            type: boolean
            Always false. Retrocompatibility with OBSRemote.
    """

    def __init__(self):
        Baserequests.__init__(self)
        self.name = 'GetStreamingStatus'
        self.datain['streaming'] = None
        self.datain['recording'] = None
# Start Edit
        self.datain['virtualcam'] = None
# End Edit
        self.datain['stream-timecode'] = None
        self.datain['rec-timecode'] = None
        self.datain['preview-only'] = None

    def getStreaming(self):
        return self.datain['streaming']

    def getRecording(self):
        return self.datain['recording']

# Start Edit
    def getVirtualCam(self):
        return self.datain['virtualcam']
# End Edit

    def getStreamTimecode(self):
        return self.datain['stream-timecode']

    def getRecTimecode(self):
        return self.datain['rec-timecode']

    def getPreviewOnly(self):
        return self.datain['preview-only']

# Start Edit

class StartStopVirtualCam(Baserequests):
    """Toggle Virtual Camera on or off (depending on the current stream state).

    """

    def __init__(self):
        Baserequests.__init__(self)
        self.name = 'StartStopVirtualCam'

class StartVirtualCam(Baserequests):
    """Start Virtualcam.
Will return an `error` if cam is already active.

    :Arguments:
       
    """

    def __init__(self, stream=None):
        Baserequests.__init__(self)
        self.name = 'StartVirtualCam'
        


class StopVirtualCam(Baserequests):
    """Stop Virtualcam.
Will return an `error` if cam is not active.

    """

    def __init__(self):
        Baserequests.__init__(self)
        self.name = 'StopVirtualCam'
# End Edit


Python 3 compatibility

Could be cool to have Py3 compat.
Putting an issue for this so people can follow up.

If there is some Py3 experts out there, feel free to take a look, never used it myself...

Additional Objects Required for Class "SetSceneItemProperties"

Hi, thanks for excellent work on this library, I am using and appreciating!

There is an issue with the class "SetSceneItemProperties", and possibly others that prevent many fields from being set in OBS. Wrapper currently sends request as single object with keys and values exactly according to obs-websocket documentation for all possible fields. Documentation is slightly convoluted however, the correct behavior for this class should be to send an object with nested objects for "Position, Scale, Crop, and Bound". See comments from haganbmj here:
obs-websocket-community-projects/obs-websocket-js#128

Any field listed in obs-websocket documentation in "x.x" format is referring to a nested object, whereas wrapper is sending the "x.x" documented field as individual keys.

We can observe this in the difference between a set and get request on this class:

<SetSceneItemProperties request ({'item': 'test', 'scene-name': None, 'position.x': 0, 'position.y': 0, 'position.alignment': 5, 'rotation': None, 'scale.x': None, 'scale.y': None, 'crop.top': None, 'crop.bottom': None, 'crop.left': None, 'crop.right': None, 'visible': None, 'locked': None, 'bounds.type': None, 'bounds.alignment': None, 'bounds.x': None, 'bounds.y': None})
called: success ({})>

<GetSceneItemProperties request ({'item': 'test', 'scene-name': None}) called: success ({'bounds': {'alignment': 0, 'type': 'OBS_BOUNDS_NONE', 'x': 0.0, 'y': 0.0}, 'crop': {'bottom': 0, 'left': 0, 'right': 0, 'top': 0}, 'height': 1080.0, 'locked': False, 'name': 'test', 'position': {'alignment': 5, 'x': 1890.0, 'y': 0.0}, 'rotation': 0.0, 'scale': {'x': 1.0, 'y': 1.0}, 'sourceHeight': 1080, 'sourceWidth': 2160, 'visible': True, 'width': 2160.0})>

The OBS Logs show that the set request has failed to properly set those parameters that are shown as being nested in the get request (specifically position in this example):

17:47:35.363: [obs-websocket] Request >> '{"item": "test", "scene-name": null, "position.x": 0, "position.y": 0, "position.alignment": 5, "rotation": null, "scale.x": null, "scale.y": null, "crop.top": null, "crop.bottom": null, "crop.left": null, "crop.right": null, "visible": null, "locked": null, "bounds.type": null, "bounds.alignment": null, "bounds.x": null, "bounds.y": null, "request-type": "SetSceneItemProperties", "message-id": "3"}'
17:47:35.363: [obs-websocket] Update << '{
17:47:35.363: "item-id": 4,
17:47:35.363: "item-name": "test",
17:47:35.363: "scene-name": "1",
17:47:35.363: "transform": {
17:47:35.363: "bounds": {
17:47:35.363: "alignment": 0,
17:47:35.363: "type": "OBS_BOUNDS_NONE",
17:47:35.363: "x": 0.0,
17:47:35.363: "y": 0.0
17:47:35.363: },
17:47:35.363: "crop": {
17:47:35.363: "bottom": 0,
17:47:35.363: "left": 0,
17:47:35.363: "right": 0,
17:47:35.363: "top": 0
17:47:35.363: },
17:47:35.363: "height": 1080.0,
17:47:35.363: "locked": false,
17:47:35.363: "position": {
17:47:35.363: "alignment": 5,
17:47:35.363: "x": 1890.0,
17:47:35.363: "y": 0.0
17:47:35.363: },

17:47:35.363: "rotation": 0.0,
17:47:35.363: "scale": {
17:47:35.363: "x": 1.0,
17:47:35.363: "y": 1.0
17:47:35.363: },
17:47:35.363: "sourceHeight": 1080,
17:47:35.363: "sourceWidth": 2160,
17:47:35.363: "visible": true,
17:47:35.363: "width": 2160.0
17:47:35.363: },
17:47:35.363: "update-type": "SceneItemTransformChanged"
17:47:35.363: }'
17:47:35.363: [obs-websocket] Response << '{
17:47:35.363: "message-id": "3",
17:47:35.363: "status": "ok"

The classes marked in obs-websocket as being deprecated (SetSceneItemPosition, SetSceneItemTransform, SetSceneItemCrop) Are still working correctly with the Wrapper and I am currently using as a work around. Although I do not currently use it, it should be noted there is no alternative class for setting "Bounds".

I briefly attempted to wrap my head around adding this into code myself but have limited time and skill at the moment (although I may still eventually return to attempt it). As mentioned above the deprecated classes are working for me but I didn't see any open or closed issue regarding this and figured I would submit in case you were unaware, or obs-websocket eventually drops the older classes.

Thanks again!

SetVolume argument order changed

76cdd5b changed the signature for SetVolume from

def __init__(self, source, volume):

to

def __init__(self, volume, source, useDecibel=None):

This broke API compatibility and that argument order doesn't make any sense (compared to other requests).

Invalid event TransitionVideoEnd

Following code is working (changing the scene in OBS)

        ws = obsws(host, port, password)
        ws.connect()
        ws.call(requests.SetCurrentScene('Clone Hero'))

But is outputting these errors in console:

Invalid message: {
    "duration": 300,
    "from-scene": "Clone Hero Menu Nav",
    "name": "Fade",
    "to-scene": "Clone Hero",
    "type": "fade_transition",
    "update-type": "TransitionVideoEnd"
} (Invalid event TransitionVideoEnd)
Invalid message: {
    "duration": 300,
    "name": "Fade",
    "to-scene": "Clone Hero",
    "type": "fade_transition",
    "update-type": "TransitionEnd"
} (Invalid event TransitionEnd)

I want to use "TakeSourceScreenshot" in python.

Pardon my broken English.
I want to use "TakeSourceScreenshot" in python.
( "TakeSourceScreenshot" is implemented in obs-websocket 4.6.0)

Could you add the method "TakeSourceScreenShot"?

obs-websocket + APScheduler

Hello , I am just working on a project using both libraries obs-websocket + APScheduler .
I used obs-websocket in conjunction with APSscheduler in order to schedule some jobs. The jobs update some scenes and objects inside the scene.

I used atomical function like this:

def createOBSWS():
    host = settings.WS_HOST
    port = settings.WS_PORT
    password = settings.WS_PASS
    websocket = obsws(host, port, password)
    return websocket

....
....

   if (websocket is None):
        websocket = createOBSWS()
        websocket.connect()
        websocket.call(requests.SetCurrentScene(sceneName))
        websocket.disconnect() 

In both linux and win box , I am getting this kind of errors .

WIN
.... venv\lib\site-packages\websocket\_socket.py", line 139, in _send return sock.send(data) OSError: [WinError 10038] Tentativo di operazione su un elemento diverso dal socket

DEB
lib/python3.5/site-packages/websocket/_socket.py", line 139, in _send return sock.send(data) OSError: [Errno 9] Bad file descriptor

They are both related.
I supposed that I call the disconnect before sending the command to the obs-websocket-server , but I followed your examples.
I tried your last release 0.5, python 3.5 (Debian), python 3.6 (Win)

Requests can't find items or scenes

Issue type

  • Bug
  • Feature request
  • Other

Description

While using Python and obs-websocket-py trying to use SetCurrentScene results in

<SetCurrentScene request({u"error" : u"requested scene does not exist"}) called: failed ({"scene-name" : u"s2"})>

or any other name results in "scene does not exist" error, even if the scene does exists and is read by using GetSceneList(). Same happens for setting source properties - the module always returns a "not found" error, even if scenes / sources can be found in the scene via obs-websocket.py.

Steps to reproduce

Make two scenes in OBS, "s1" and "s2". Then:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import obswebsocket as obsw
import obswebsocket.requests as obsr

client = obsw.obsws("localhost", 4444, "password")
client.connect()
scenes = client.call(obsr.GetSceneList()).dataout["scenes"]
newScene = scenes[1]
res = client.call(obsr.SetCurrentScene(newScene["name"]))
print res
client.disconnect()

Technical information

  • Operating System : Windows 7 Pro x64 SP1
  • OBS Studio version : 19.0.3 x32
  • Python version: 2.7.13 x32
    Using obs-websocket version 4.0 and obs-websocket-py version 0.1.

MessageTimeout

Hi, i'm having a Problem with getting a MessageTimeout after i send a request to GetSceneItemList with the current PreviewScene after an on_preview Event, when i try this on other parts of my code it works fine and does not result in a timeout. According to the log of OBS and Wireshark a response (including "status":"ok") is send by the websocket plugin

in other words:
when i make the request (GetSceneItemList) at the begining of my script (with the Scene Name i get via the getPreviewScene Request) evrything works fine, but when i make the request as a response for an PreviewSceneChange with the Scene name i get from the Event, the request runs into a timeout even though OBS and Wireshark confirm that a response has been send

here is a output from my terminal:

Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Users\Niklas\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1009, in _bootstrap_inner
self.run()
File "C:\Users\Niklas\AppData\Local\Programs\Python\Python310\lib\site-packages\obswebsocket\core.py", line 236, in run
self.core.eventmanager.trigger(obj)
File "C:\Users\Niklas\AppData\Local\Programs\Python\Python310\lib\site-packages\obswebsocket\core.py", line 281, in trigger
callback(data)
File "C:\Users\Niklas\Documents\scripte\python\obs-ws\app.py", line 120, in on_preview
scene_Prev = getSrcForScene(current_Prev)
File "C:\Users\Niklas\Documents\scripte\python\obs-ws\app.py", line 46, in getSrcForScene
result = ws.call(requests.GetSceneItemList(sceneName))
File "C:\Users\Niklas\AppData\Local\Programs\Python\Python310\lib\site-packages\obswebsocket\core.py", line 162, in call
r = self.send(payload)
File "C:\Users\Niklas\AppData\Local\Programs\Python\Python310\lib\site-packages\obswebsocket\core.py", line 179, in send
return self._wait_message(message_id)
File "C:\Users\Niklas\AppData\Local\Programs\Python\Python310\lib\site-packages\obswebsocket\core.py", line 187, in _wait_message
raise exceptions.MessageTimeout(u"No answer for message {}".format(
obswebsocket.exceptions.MessageTimeout: No answer for message 18


I tested this on a windows 10 and an ubuntu Maschine, both running OBS Version 27.1.3 and obs-websocket-py Version 0.5.3

VLC Source Playlist Made Empty

Hi devs,

First, thanks for the awesome module.

I am trying to use SetSourceSettings to change the video playing on a VLC source.
Here is the code I'm using:

video = '/home/streamgaki/Desktop/Videos To Play/Highschool Batsu Clip - Ten Ten.mkv'
request = {'playlist': {'hidden': False, 'selected': False, 'value': video}}
thecall = self.obss.call(requests.SetSourceSettings("VLC", request))

Printing the result of this request gives:
<SetSourceSettings request ({'sourceName': 'VLC', 'sourceSettings': {'playlist': {'hidden': False, 'selected': False, 'value': '/home/streamgaki/Desktop/Videos To Play/Highschool Batsu Clip - Ten Ten.mkv'}}, 'sourceType': None}) called: success ({'sourceName': 'VLC', 'sourceSettings': {'loop': True, 'network_caching': 400, 'playback_behavior': 'always_play', 'playlist': {'hidden': False, 'selected': False, 'value': '/home/streamgaki/Desktop/Videos To Play/Highschool Batsu Clip - Ten Ten.mkv'}, 'shuffle': True, 'subtitle': 1, 'subtitle_enable': False, 'track': 1}, 'sourceType': 'vlc_source'})>

So it looks like it worked, and looking at the OBS log, that seems to be the case:
17:14:18.688: [obs-websocket] Request >> '{"sourceName": "VLC", "sourceSettings": {"playlist": {"hidden": false, "selected": false, "value": "/home/streamgaki/Desktop/Videos To Play/Highschool Batsu Clip - Ten Ten.mkv"}}, "sourceType": null, "request-type": "SetSourceSettings", "message-id": "5"}'
17:14:18.688: [obs-websocket] Response << '{"message-id":"5","sourceName":"VLC","sourceSettings":{"loop":true,"network_caching":400,"playback_behavior":"always_play","playlist":{"hidden":false,"selected":false,"value":"/home/streamgaki/Desktop/Videos To Play/Highschool Batsu Clip - Ten Ten.mkv"},"shuffle":true,"subtitle":1,"subtitle_enable":false,"track":1},"sourceType":"vlc_source","status":"ok"}'

However... checking OBS, the VLC source ends up with nothing in its playlist
image

Am I doing shitty code? Or is the module or OBS being silly?

TypeError when starting stream

When sending the message to start the stream, it seems to have caused a TypeError on my StreamStatus event

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\Colin\AppData\Local\Programs\Python\Python38\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Users\Colin\Documents\_GithubRepos\PTZCamSync\PTZCamSync\lib\site-packages\obswebsocket\core.py", line 236, in run    
    self.core.eventmanager.trigger(obj)
  File "C:\Users\Colin\Documents\_GithubRepos\PTZCamSync\PTZCamSync\lib\site-packages\obswebsocket\core.py", line 280, in trigger
    if trigger is None or isinstance(data, trigger):
TypeError: isinstance() arg 2 must be a type or tuple of types

TransitionEnd and TransitionVideoEnd missing

When triggering a scene change with a transition events are emitted for TransitionEnd and TransitionVideoEnd. These are not defined in events.py.

I've installed via pip, if that explains anything.

Question: Possible to set start time on video?

Is it possible for Media or VLC source to set the starting point in the media file or does the media file always play from the beginning? Kinda like the following.

'sourceSettings' : {'local_file': "path/to/file", 'start': 10.5}

I've asked the same at obs-websocket but I haven't heard if its possible yet and figured someone here may know.

obsproject/obs-websocket#342

Thank you.

Installation on Windows Failure

Hi,
I can't install obs-websocket-py.
Over pip install obs-websocket-py, I get:

Collecting obs-websocket-py
Using cached https://files.pythonhosted.org/packages/2c/82/125306f049d7517f6cbae078fe0dc4cb82df08d5a2b1018b7bbd753eadc8/obs-websocket-py-0.3.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "c:\users\pascal\appdata\local\temp\pip-install-d1x5gc\obs-websocket-py\setup.py", line 9, in
from generate_classes import generate_classes
ImportError: No module named generate_classes

----------------------------------------

Command "python setup.py egg_info" failed with error code 1 in c:\users\pascal\appdata\local\temp\pip-install-d1x5gc\obs-websocket-py\

I need the library for python2.7.
When I try it to install from a cloned git repo, I get:

Processing c:\users\pascal\downloads\obs-websocket-py-master\obs-websocket-py-master
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "c:\users\pascal\appdata\local\temp\pip-req-build-lh8uf8\setup.py", line 10, in
from obswebsocket import version
File "obswebsocket_init_.py", line 8, in
from .core import obsws
File "obswebsocket\core.py", line 18, in
from . import events
ImportError: cannot import name events

----------------------------------------

Command "python setup.py egg_info" failed with error code 1 in c:\users\pascal\appdata\local\temp\pip-req-build-lh8uf8\

And I installed events 0.3 with pip.

pip install events
Requirement already satisfied: events in c:\python27\lib\site-packages (0.3)

May the import of events are not correct?
Or something else?

I hope you can help.

best regards

GetSceneItemProperties 'width' and 'height' should return another value.

Supposedly, width and height are the final sceneitem size. They return the base width and height multiplied by their scale:

// Utils.cpp:784
	obs_data_set_double(data, "width", baseSourceWidth * scale.x);
	obs_data_set_double(data, "height", baseSourceHeight * scale.y);

Shouldn't they be substracted by its crop values before multiplying them? Something like:

// Utils.cpp:784
	obs_data_set_double(data, "width", (baseSourceWidth - crop.left - crop.right)* scale.x);
	obs_data_set_double(data, "height", (baseSourceHeight - crop.top - crop.bottom) * scale.y);

(I don't know C++, maybe it's misspelled)

Saddly, I don't use obs-websocket-py anymore ๐Ÿ˜ข... because I programed my own OBS-OSC-PythonScript 0.1. Now, I don't send OSC messages to Python and Python to Websockets... it's slow and it crashes OBS several times. I directly send OSC messages to Python script ๐Ÿ˜‰.

But I've been using obs-websockets-py for a time and now, I realized that GetSceneItemProperties should be different. As I fixed that in my code, maybe you want to change in yours.

Thank you very much for your code!

Heartbeat addition patch

Adding the two classes below to the request.py and event.py file will enable the heartbeat which was introduced lately in the obs-websocket implementation from: https://github.com/Palakis/obs-websocket/

Is it possible that you/anyone could add those classes to these files?

Kind regards,

Robert Nagtegaal
[email protected]

request.py:

class SetHeartBeat(base_classes.BaseRequest):
    def __init__(self, enable):
        base_classes.BaseRequest.__init__(self)
        self.name = "SetHeartbeat"
        self.dataout["enable"] = enable

event.py:

class Heartbeat(base_classes.BaseEvent):
    def __init__(self):
        base_classes.BaseEvent.__init__(self)
        self.name = "Heartbeat"
        self.datain["current-profile"] = None
        self.datain["current-scene"] = None
        self.datain["pulse"] = False
        self.datain["rec-timecode"] = None
        self.datain["recording"] = None
        self.datain["streaming"] = None
        self.datain["total-record-bytes"] = None
        self.datain["total-record-frames"] = None
        self.datain["total-record-time"] = None

see also: https://github.com/Elektordi/obs-websocket-py/pulls

Add unit tests to the lib

Now that the lib have a common codebase for python 2 and 3, I should add unit tests to prevent any break of one python version while working on the other one!

Maybe it's a good idea to create to server placeholder to answer the lib with static hardcoded answers...

Add CLI for basic requests

So - I have written a thin wrapper around this library which can be used on a command line:
https://gist.github.com/sochotnicky/101e3b2bbcdddd5db065d0ff102d3db2

For example:

$ python obs-cli.py ListSceneCollections
{
    "scene-collections": [
        {
            "sc-name": "Demo - Share Left"
        },
        {
            "sc-name": "Demo - Share Right"
        },
        {
            "sc-name": "Share - WebCam"
        },
        {
            "sc-name": "Untitled"
        }
    ]
}
$ python obs-cli.py SetCurrentSceneCollection Untitled
{}

The way it's done it does not require changes when methods are added. I am sure there's things that do not work well - it would be nice for example if there were annotations on arguments that could be used to figure out expected argument types etc.

I was considering creating a separate repo for it & putting it there, but I figure maybe it could be more useful included here? If you'd be up for the idea - I can open a PR (it would need additional changes to setup.py etc to install the script)

Installation fails on Mac

running Python 3.5.2.

$ pip install obs-websocket-py

Collecting obs-websocket-py
Downloading obs-websocket-py-0.3.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 1, in
File "/private/var/folders/5b/r380sbgs64d9v36w3qdn27m40000gn/T/pip-build-2q0t90dj/obs-websocket-py/setup.py", line 9, in
from generate_classes import generate_classes
ImportError: No module named 'generate_classes'

Can't switch on source?

Hi,
I was experimenting with your websocket lib. Tried one of the samples and it's working.
Switching scenes, listing sources, etc.
Upon trying to enable or disable a source, it seems I can turn them off but not back on?

ws.call(requests.SetSceneItemProperties(scene_name="Scene", item = "nonewsy", visible = 'true'))
time.sleep(2)
ws.call(requests.SetSceneItemProperties(scene_name="Scene", item = "nonewsy", visible = 'false'))

I've tried 0 and 1, with scene_name or without it. The second statement works, the first one does not. Any ideas? Thanks!

Can't get audio source mute status

At least in the current (0.4) version, it is impossible to get the mute status of an audio source, presumably due to using the wrong key when getMute() is called.

source = client.call(obswebsocket.requests.GetVolume("Line 1 (Streaming Music)"))
print source
<GetVolume request ({'source': 'Line 1 (Streaming Music)'}) called: success ({u'muted': True, u'name': u'Line 1 (Streaming Music)', u'volume': 0.20000000298023224})>

...note that the name of the key is muted

....and then:

print source.getMute()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/obswebsocket/requests.py", line 831, in getMute
    return self.datain["mute"]
KeyError: 'mute'

...note the key being used by getMute() is mute.

This is with obs-websocket 4.6.1 on the other end.

PyPi Build Not Compatible with 3.x

Although the repository is 3.x compatible (1b97dc8) and is stated as such in the plugin README, the current version on PyPi does not have these changes.

It would be nice if you could push the latest version to PyPi so the module installed via pip is 3.x compatible ๐Ÿ˜„.

SetMute and ToggleMute in event does not work

I have checked the same code on switching scenes and it has no issues, muting any source does not seem to work.
The snippet connects to obs, print success msg, and does not toggle "myname" in obs.
Example:

host = "localhost"
port = 4444
password = "1"

ws = obsws(host, port, password)
ws.connect()

try:
    req = ws.call(requests.ToggleMute("myname"))

ws.disconnect()

Custom functions

I have added a new SysTray button "Start Procedure" to my OBS Studio which is similar to "Start Recording". However when i add it as a class to requests.py and try to access it using obs-websocket-py , i get an error saying "invalid request type" . Could you please assist as to what may be the problem? Thanks in advance.
obs

Lack of parameters in 'SetSceneItemProperties'

Hello again,

I am trying to make a source move animation. However I could not find the way of setting the following parameters:

'height'
'width'
'sourceHeight'
'sourceWidth'

(Also less important/meaningless: 'itemId', 'name')

Maybe it is currently possible but I spent a lot of time trying to set 'height', 'width', 'sourceHeight' and 'sourceWidth' but I could not find the way.

On the other hand, when running the move animation (video attached) the 'ws.call' takes a lot of time between steps because of callback, so the animation it is not smooth enought. I tried to use 'ws.send' but it gives me an error. Any advice?

Thank you in advance. Best regards.

2021-01-03.20-41-06.mp4

New obs-websocket features not supported

Hello Elektordi,

First of all, thank you so much for your awesome work, I really appreciate it.

Recently, obs-websocket has been updated with new features (and also will introduce some more in next release) which are not supported buy obs-websocket-py. For example CreateScene #576. I also wanted to use new feature OpenProjector but I neither could. Will be possible to use them in the future? I am learning programming and my skill is not very good right now, otherwise I would help you to do it.

Thank you for your time.
Best regards.

Python process hangs if disconnect() not called

Running events sample with ws.disconnect() commented out...

[elektordi@gg8 samples]$ python events.py 
INFO:obswebsocket.core:Connecting...
INFO:obswebsocket.core:Connected!
OK
^C^C^C^C^C^\Quitter (core dumped)
[elektordi@gg8 samples]$ 

(Had to SIGKILL it to exit.)

Users are supposed to call disconnect() before exiting, but if missed it should definitely not lock the python process!!!

Can't reproduce a command.

Sorry if this does not belong here... I want to change the opacity of a filter. I read in a obs-websocket issue that somebody uses SetSourceFilterSettings:

// camera
    await obs.send(
      "SetSourceFilterSettings", {
        sourceName: "SRC_Cam_1",
        filterName: "Color Correction",
        filterSettings: {
          opacity: opacity
        }
      });

I would like to do the same with obs-websocket-py. As in Protocol says this:

filterSettings | Object | New settings. These will be merged to the current filter settings.

... I tried sending that "Object" as a dict:

(...)
ws.call(requests.SetSourceFilterSettings(sourceName='Source_001', filterName="Color Correction", filterSettings={"opacity": 50}))

... but it didn't work. In Protocol says its an "Object"... How to know what to send? Should I create that "Object" before?

Invalid message on disconnecting

I'm getting the following message

Invalid message:  (Expecting value: line 1 column 1 (char 0))

When I call disconnect on my obsws instance. It happens because the socket closes and self.ws.recv() returns an empty string[1].

The library should probably check if self.running is False once again OR check if the received string is empty.

Instead it tries to JSON it.

Possible solution (the whole run function):

    def run(self):
        while self.running:
            try:
                message = self.ws.recv()
                if not self.running:
                    return

                if not message:
                    raise self.core.reconnect()

                result = json.loads(message)

                if 'update-type' in result:
                    LOG.debug("Got message: %r"%(result))
                    obj = self.buildEvent(result)
                    self.core.eventmanager.trigger(obj)

                elif 'message-id' in result:
                    LOG.debug("Got answer for id %s: %r"%(result['message-id'], result))
                    self.core.answers[result['message-id']] = result

                else:
                    LOG.warning("Unknow message: %r"%(result))

            except websocket.WebSocketConnectionClosedException:
                if self.running:
                    self.core.reconnect()

            except (ValueError, exceptions.ObjectError) as e:
                LOG.warning("Invalid message: %s (%s)"%(message, e))

        LOG.debug("RecvThread ended.")

Notes

[1] websocket.WebSocketConnectionClosedException is only raised if you try to call recv when the socket is already closed. It's not raised if you close the socket while you're already waiting for recv to return - instead the recv call will just return an empty string.

Ignores 'with_transition_name'

Quite likely I'm doing something wrong. Calling TransitionToProgram works, but uses whatever transition is set in OBS, not what I specify

Connect to ngrok tunnel using obs-websocket-py

Hello.
I have tunneled the obs websocket port (4444) using ngrok.
I am able to access obs studio remotely using http://obs-web.niek.tv/.
But im not able to connect using obs-websocket-py using a python script.
How to provide the (host, port) to this library so i can connect remotely using python.
Thanks in advance.

WebSocket Connection / Websocket client disconnected Message

I'm relatively new to using the obs-websocket-py and should quickly admit that I might easily be missing something. That said, however, I've written a very simple scene change process that is as follows;

import sys
import obswebsocket
import obswebsocket.requests

def main():
client = obswebsocket.obsws("localhost", 4444)
client.connect()
scene = sys.argv[1]
response = client.call(obswebsocket.requests.SetCurrentScene(scene))
client.disconnect()
return 0

if name == "main":
main()

When I run this code I get a message box twice when I call ths procedure; one message that says "New Websocket connection /n Client [::1]:xxxxx connected" and then another message shortly after reading "Web client disconnected /n Client unknown disconnected"

Firstly, I'm wondering if there is some way to turn off or hide these messages?

I'm also wondering if I truly need to connect and disconnect as part of the scene change process. Could I, for example, connect once and then only disconnect when I'm totally done, which may be an hour or more later? I'm wonderingalso if that would help to improve the throughput of the scenechange() process as I've programmed it.

Your thoughts and suggestions are very much appreciated.

How to use GetRecordingFolder() ?

obswebsocket.requests.GetRecordingFolder() returns <GetRecordingFolder request ({}) waiting>.
obswebsocket.requests.GetRecordingFolder().getRecFolder() returns None.

I cannot change Position

Im trying to change an image position inside obs but i cant

print(ws.call(requests.GetSceneItemProperties(
'imagen',
scene_name='programacion'
)))

print(ws.call(requests.SetSceneItemProperties(
'imagen',
scene_name='programacion',
position_x=250,
position_y=300,
)))

print(ws.call(requests.GetSceneItemProperties(
'imagen',
scene_name='programacion'
)))

<GetSceneItemProperties request ({'item': 'imagen', 'scene-name': 'programacion'}) called: success ({'bounds': {'alignment': 0, 'type': 'OBS_BOUNDS_NONE', 'x': 0.0, 'y': 0.0}, 'crop': {'bottom': 0, 'left': 0, 'right': 0, 'top': 0}, 'height': 509.0, 'itemId': 11, 'locked': False, 'name': 'imagen', 'position': {'alignment': 5, 'x': 89.0, 'y': 114.0}, 'rotation': 0.0, 'scale': {'x': 1.0, 'y': 1.0}, 'sourceHeight': 509, 'sourceWidth': 1188, 'visible': True, 'width': 1188.0})>
<SetSceneItemProperties request ({'item': 'imagen', 'scene-name': 'programacion', 'position.x': 250, 'position.y': 300, 'position.alignment': None, 'rotation': None, 'scale.x': None, 'scale.y': None, 'crop.top': None, 'crop.bottom': None, 'crop.left': None, 'crop.right': None, 'visible': None, 'locked': None, 'bounds.type': None, 'bounds.alignment': None, 'bounds.x': None, 'bounds.y': None}) called: success ({})>
<GetSceneItemProperties request ({'item': 'imagen', 'scene-name': 'programacion'}) called: success ({'bounds': {'alignment': 0, 'type': 'OBS_BOUNDS_NONE', 'x': 0.0, 'y': 0.0}, 'crop': {'bottom': 0, 'left': 0, 'right': 0, 'top': 0}, 'height': 509.0, 'itemId': 11, 'locked': False, 'name': 'imagen', 'position': {'alignment': 5, 'x': 89.0, 'y': 114.0}, 'rotation': 0.0, 'scale': {'x': 1.0, 'y': 1.0}, 'sourceHeight': 509, 'sourceWidth': 1188, 'visible': True, 'width': 1188.0})>

Samples do not work after install.

pip install obs-websocket-py
python samples/events.py

Traceback (most recent call last):
  File "/home/shawn/.virtualenvs/TEC/lib/python3.8/site-packages/obswebsocket/core.py", line 68, in connect
    self.ws.connect("ws://{}:{}".format(self.host, self.port))
  File "/home/shawn/.virtualenvs/TEC/lib/python3.8/site-packages/websocket/_core.py", line 222, in connect
    self.sock, addrs = connect(url, self.sock_opt, proxy_info(**options),
  File "/home/shawn/.virtualenvs/TEC/lib/python3.8/site-packages/websocket/_http.py", line 121, in connect
    sock = _open_socket(addrinfo_list, options.sockopt, options.timeout)
  File "/home/shawn/.virtualenvs/TEC/lib/python3.8/site-packages/websocket/_http.py", line 201, in _open_socket
    raise err
  File "/home/shawn/.virtualenvs/TEC/lib/python3.8/site-packages/websocket/_http.py", line 176, in _open_socket
    sock.connect(address)
ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "events.py", line 29, in <module>
    ws.connect()
  File "/home/shawn/.virtualenvs/TEC/lib/python3.8/site-packages/obswebsocket/core.py", line 73, in connect
    raise exceptions.ConnectionFailure(str(e))
obswebsocket.exceptions.ConnectionFailure: [Errno 111] Connection refused

I'm on Pop!_OS 20.10 python3.8 as you can see.

OBS 26.1.1 which is running and recording as I run the script.

Thank you! It will be awesome to have ws access to OBS.

Updates for obs-websocket 4.8 functions

Awesome project. I'm making great use of this library.

I'm noticing some warnings about some events that are not recognized by obx-websocket-py but that I see documented in obx-websocket 4.8.

A two that are filling me with the most warnings are:

TransitionVideoEnd
TransitionEnd

I don't know if this is in-progress or if there's a process for adding more events to the code.

Change __init__ wrapper

Replace wrapper in __init__.py with imports (as seen in others libs)
It seems to be a best practice in python

PROTOCOL.md cannot be parsed automatically

Message

My whole message of this issue is "PROTOCOL.md cannot be parsed automatically".

Why?

Because given the complexity of matter it tries to declare, it needs more accurate description. PROTOCOL.md is full of typos and doesn't represent their protocol correctly.

generate_classes.py

Even if PROTOCOL.md was perfect, current architecture of obs-websocket-py (particularly generate_classes.py) doesn't support creating requests like StartStreaming. Let's have a look at that request:


Request fields :

  • "stream" (object; optional) : If specified allows for special configuration of the stream

The 'stream' object has the following fields:

  • "settings" (object; optional) : The settings for the stream
  • "type" (string; optional) : If specified ensures the type of the stream matches the given type (usually 'rtmp_custom' or 'rtmp_common'). If the currently configured stream type does not match the given stream type, all settings must be specified in the 'settings' object or an error will occur starting the stream.
  • "metadata" (object; optional) : Adds the given object parameters as encoded query string parameters to the 'key' of the RTMP stream. Used to pass data to the RTMP service about the stream.

The 'settings' object has the following fields:

  • "server" (string; optional) : The publish URL
  • "key" (string; optional) : The publish key of the stream
  • "use-auth" (bool; optional) : should authentication be used when connecting to the streaming server
  • "username" (string; optional) : if authentication is enabled, the username for access to the streaming server. Ignored if 'use-auth' is not specified as 'true'.
  • "password" (string; optional) : if authentication is enabled, the password for access to the streaming server. Ignored if 'use-auth' is not specified as 'true'.

The 'metadata' object supports passing any string, numeric or boolean field.

Response : Error if streaming is already active, OK otherwise. No additional fields.


So there's only one field to that request. And it's an object that has (besides other fields) two more object fields - settings and metadata.
Plus there's this metadata object that is unique accross protocol in sense that it can inlude arbitrary fields.

Time to look at the class generated by the generate_classes.py:

class StartStreaming(base_classes.BaseRequest):
    def __init__(self, stream, settings, type, metadata, server, key, use_auth, username, password):
        base_classes.BaseRequest.__init__(self)
        self.name = "StartStreaming"
        self.dataout["stream"] = stream
        self.dataout["settings"] = settings
        self.dataout["type"] = type
        self.dataout["metadata"] = metadata
        self.dataout["server"] = server
        self.dataout["key"] = key
        self.dataout["use-auth"] = use_auth
        self.dataout["username"] = username
        self.dataout["password"] = password

All fields are inserted directly into request. That is wrong and doesn't work. Also all fields are required, no opportunity to skip any of them (while PROTOCOL.md declares all of them as optional).

Maybe a better parser could solve this?

Doubt it. Look at the StartStopRecording request. Its only field (stream) is not even declared there - we're just told to look it up in another request. We'd need an AI parser to handle all these cases in PROTOCOL.md. MOREOVER, I suspect that stream property doesn't even belong there - it's likely for StartStopStreaming request, just was misplaced accidentally in PROTOCOL.md. Huh.

What do you propose?

It's simple, we, err, handle the stuff manually.

As a part of my Python 3.5+ asyncio-based client to obs-websocket plugin, I tried to carefully build a usable representation of their protocol.

I provide information of all protocol types (like StreamSettings type etc), their fields, types of their fields and their "pythonic" fields (authRequired's pythonic one is auth_required; use-auth's pythonic one is use_auth). Then I provide information of all requests, their responses and all events.

Guess what? I've failed as soon as I received a response for the GetAuthRequired request. The fact that challenge and salt fields are optional (they're sent only if the auth is enabled) is mentioned in the request description, but not anywhere near the fields themselves (usually they detone such fields as "optional" explicitly).

It just confirms the fact that a maintaining is needed, you can't just convert PROTOCOL.md to anything useful.

I've already seen a few events that don't provide their "required" fields (probably they forgot to mention those were optional, again), but I'm going to do more tests, and finally build an accurate, usable description of the protocol v4.1.

Feel free to use it. My client builds all classes during runtime, but it's still possible to use that file to build classes offline, too.

Error on IronPython 2.7

First of all, i want to ask, is compatible with ironpython? almost all libraries of python are compatible,
If it is when i try to connect to the server i get an error:
obswebsocket.exceptions.ConnectionFailure: [Errno 10044] The support for the specified socket type does not exist in this address family
You may ask. Why i'm using IronPython and not Python, the answer is simple, i need load some .DLLs and the Pythonnet lib dosnt work on python because the stupid NTFS security thing of windows

C:\Windows\system32>ipy
IronPython 2.7.9 (2.7.9.0) on .NET 4.0.30319.42000 (64-bit)
Type "help", "copyright", "credits" or "license" for more information.

import sys
import time
import logging
logging.basicConfig(level=logging.INFO)
from obswebsocket import obsws, requests
host = 'localhost'
port = 4444
password = "test"
ws = obsws(host, port, password)
ws.connect()
INFO:obswebsocket.core:Connecting...
Traceback (most recent call last):
File "", line 1, in
File "C:\Program Files\IronPython 2.7\Lib\site-packages\obswebsocket\core.py", line 72, in connect
obswebsocket.exceptions.ConnectionFailure: [Errno 10044] The support for the specified socket type does not exist in this address family

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.