GithubHelp home page GithubHelp logo

dnaka91 / obws Goto Github PK

View Code? Open in Web Editor NEW
99.0 1.0 11.0 1.35 MB

The obws (obvious) remote control library for OBS

License: MIT License

Rust 99.66% Just 0.34%
rust obs-websocket obs remote-control hacktoberfest async-await

obws's Introduction

OBWS - The obws (obvious) remote control library for OBS

Build Status Repository Documentation Code Coverage

Remote control OBS with the obs-websocket plugin from Rust ๐Ÿฆ€.

Usage

Add obws to your project with cargo add [email protected] or add it manually to your Cargo.toml:

[dependencies]
obws = "0.12.0"

In addition, you will need to use the latest tokio runtime to use this library as it makes heavy use of async/await and is bound to this runtime.

Example

Here we connect to a OBS instance, get some version information and log in to access the whole API and lastly print out a list of available scenes.

For more usage instructions see the docs or check out the examples.

use anyhow::Result;
use obws::Client;

#[tokio::main]
async fn main() -> Result<()> {
    // Connect to the OBS instance through obs-websocket.
    let client = Client::connect("localhost", 4455, Some("password")).await?;

    // Get and print out version information of OBS and obs-websocket.
    let version = client.general().version().await?;
    println!("{version:#?}");

    // Get a list of available scenes and print them out.
    let scene_list = client.scenes().list().await?;
    println!("{scene_list:#?}");

    Ok(())
}

License

This project is licensed under MIT License (or http://opensource.org/licenses/MIT).

obws's People

Contributors

715209 avatar dnaka91 avatar nchechulin avatar peterw-lwl 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

Watchers

 avatar

obws's Issues

Relax obs version requirement?

Currently the library requires OBS 26.1.2, however that is a macOS hotfix and the OBS repositories for Ubuntu LTS haven't bumped the version, staying at 26.1.1. Can the version requirement be relaxed?

ERROR obws::client: failed handling message error=UnexpectedMessage(Event)

When I run iter_scenes I get a repeating error message.

cargo run --example iter_scenes
    Finished dev [unoptimized + debuginfo] target(s) in 0.27s
     Running `target\debug\examples\iter_scenes.exe`
2023-09-02T19:25:15.832848Z DEBUG obws::client::connection: identified against obs-websocket rpc_version=1
2023-09-02T19:25:15.839105Z ERROR obws::client: failed handling message error=UnexpectedMessage(Event)
2023-09-02T19:25:16.164942Z ERROR obws::client: failed handling message error=UnexpectedMessage(Event)
2023-09-02T19:25:16.166915Z ERROR obws::client: failed handling message error=UnexpectedMessage(Event)
Version {
    obs_version: Version {
        major: 29,
        minor: 1,
        patch: 3,
    },
    obs_web_socket_version: Version {
        major: 5,
        minor: 2,
        patch: 3,
    },

The other sample events and simple are working;
The screenshot example also gave me the same UnexpectedMessage(Event) after creating the 'OBWS-TEST-Scene' required.

2023-09-02T19:32:14.431542Z ERROR obws::client: failed handling message error=UnexpectedMessage(Event

simple knows how it return the list of scenes.

[
    Scene {
        name: "Scene 4",
        index: 0,
    },
    Scene {
        name: "Scene 3",
        index: 1,
    },
    Scene {
        name: "Scene 2",
        index: 2,
    },
    Scene {
        name: "Scene",
        index: 3,
    },
]

Connection timeout duration

I'm using obws as part of a web server that allows configuration of the remote OBS connection details, and I'd like to be able to set a timeout duration in case the remote OBS is not currently running. As it stands, awaiting on the connection appears to wait indefinitely with no timeout -- is there a way to do this or is this something that would be feasible to add as a new feature?

Error::NoPassword is useless ?

When connecting to a server that requires password authentification, with

let pw: Option<String> = None;
let client_res = Client::connect("localhost", 4455, pw).await();
...

it fails with

Handshake(ConnectionClosed(Some(CloseDetails { code: Library(4009), reason: "Your payload's data is missing an `authentication` string, however authentication is required." })))

I would have expected a Error::NoPassword error for this case.
Furthermore, I found no references to this error variant in the obws code base. Is it indeed unused ?

Add Serialize to Event structs

I'm currently trying to use obws with serde_json but there's the Serialize derive missing on some of the structs to easily use it with json!() etc.. Preliminary tests just adding the derive seemed to be fine but I'm not 100% sure if there's anything else needed. If there's some contribution guidelines I'd be happy to implement it myself. :)

Unable to connect - deserialize error

OS: Fedora 36
OBS version: 27.2.4 flatpak
obs-websocket version: 5.0.0-beta1
obws version: efd6170 (aka latest for v5 api)

Full error:

Error: the response message could not be deserialized

Caused by:
    missing field `platform`

Happens immediatelly when calling collect, so I can't test further API endpoints.

obs-websocket sends two notifications: "client identified" and "client disconnected"

Can provide further help with debugging as this is 100% reproducible

Hard requiring the absolute latest OBS is annoying

Chasing the latest version for an application is great! I absolutely support updating as much as possible. That said, for a variety of reasons (e.g. Unix vendors not keeping up with packaging), requiring the latest version makes working with this crate difficult. I understand that new versions of OBS introduce new websockets APIs, and making them available is a priority for this crate. This is an entirely reasonable thing to do! But I think a more graceful system which only provides those features the running OBS supports would be more friendly to the end user. Are there any websockets APIs introduced in version 27?

Just can't get the example in the readme to compile in my own project.

Example in the readme doesn't compile

Gives the following error.

Any idea what is wrong?

error: The default runtime flavor is `multi_thread`, but the `rt-multi-thread` feature is disabled.
 --> src\main.rs:4:1
  |
4 | #[tokio::main]
  | ^^^^^^^^^^^^^^
  |
  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

warning: unused import: `obws::Client`
 --> src\main.rs:1:5
  |
1 | use obws::Client;
  |     ^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused import: `anyhow::Result`
 --> src\main.rs:2:5
  |
2 | use anyhow::Result;
  |     ^^^^^^^^^^^^^^

error[E0601]: `main` function not found in crate `obs_test`
  --> src\main.rs:1:1
   |
1  | / use obws::Client;
2  | | use anyhow::Result;
3  | |
4  | | #[tokio::main]
...  |
20 | |   Ok(())
21 | | }
   | |_^ consider adding a `main` function to `src\main.rs`        

error: aborting due to 2 previous errors; 2 warnings emitted       

For more information about this error, try `rustc --explain E0601`.
error: could not compile `obs_test`

Serde not properly serializing the EventSubscription bitflags

Hi! I seem to have encountered an issue when using reidentify.

Digging in to the code it seems to be an issue where Serde is not calling the bits() function, which instead just changes it to send the struct names.

image

So changing this to use the bits() function, gives me the expected results.

image

image

Error decoding into `response::TextGdiPlusProperties`

In my OBS (v27.2.1) with obs-websocket (v4.9.1) the response to a GetTextGDIPlusProperties request can not be deserialized by this library. "the response message could not be deserialized"

The response that is send from obs-websocket is here (formatted for readability):

{
    "align": "center",
    "antialiasing": true,
    "bk_color": 4286513152,
    "bk_opacity": 0,
    "chatlog": false,
    "chatlog_lines": 6,
    "color": 16777215,
    "extents": false,
    "extents_cx": 100,
    "extents_cy": 100,
    "extents_wrap": true,
    "font": {
        "face": "Beon",
        "flags": 0,
        "size": 256,
        "style": "Medium"
    },
    "gradient_color": 16777215,
    "gradient_dir": 90.0,
    "gradient_opacity": 100,
    "message-id": "4",
    "opacity": 100,
    "outline": true,
    "outline_color": 4278190165,
    "outline_opacity": 100,
    "outline_size": 10,
    "source": "Multiplayer Code",
    "status": "ok",
    "text": "Lobby: 1yd5r",
    "transform": 0,
    "valign": "bottom"
}

How to get/set source settings for Xcomposite source

I am trying to alter settings for my Xcomposite window capture source and first trying to get them, but I keep acing the issue of type inside \async` block must be known in this contextwith theget_source_settings()` function.

[Suggestion] API to set coordinates of projector by numbers when opening

Since the obws::requests::Projector.geometry field only supports base64-encoded Qt geometry format, it may be hard to use that API when you know the arbitrary coordinates you want, but not how to represent them in Qt geometry.

So, it may be easier to have an integrated API that accepts proper coordinates and converts them internally into base64. Because Qt's saveGeometry API has versioning, it shouldn't be very hard to maintain.

In my own application I've implemented it like this:

`qt_geometry.rs`
pub struct QtRect {
    x1: i32,
    y1: i32,
    x2: i32,
    y2: i32,
}

pub struct QtGeom {
    frame: QtRect,
    normal: QtRect,
    screen_no: i32,
    is_maximized: u8,
    is_fullscreen: u8,
    screen_width: i32,
    client_rect: QtRect,
}


impl QtGeom {
    pub fn new(left: i32, top: i32, width: i32, height: i32) -> Self {
        Self {
            frame: QtRect {
                x1: left, y1: top,
                x2: left+width, y2: top+height
            },
            normal: QtRect {
                x1: left, y1: top,
                x2: left+width, y2: top+height
            },
            screen_no: 0,
            is_maximized: 0,
            is_fullscreen: 0,
            screen_width: 0,
            client_rect: QtRect {
                x1: left, y1: top,
                x2: left+width, y2: top+height
            },
       }
    }
}

pub fn rect_to_geometry_str(geometry: QtGeom) -> String {
    //! Creates geometry base64 as of QT5.12 (geometry 3.0)
    //! https://code.woboq.org/data/symbol.html?root=../qt5/&ref=_ZNK7QWidget12saveGeometryEv

    use std::mem::transmute;
    let mut header: Vec<u8> = vec![
        0x01, 0xD9, 0xD0, 0xCB, // magic
        0x00, 0x03, 0x00, 0x00, // maj.+min version
    ];

    fn get_i32(i: i32) -> [u8; 4] {
        let o: [u8; 4] = unsafe { transmute(i.to_be()) };
        o
    }

    header.extend_from_slice( &get_i32(geometry.frame.x1) );
    header.extend_from_slice( &get_i32(geometry.frame.y1));
    header.extend_from_slice( &get_i32(geometry.frame.x2));
    header.extend_from_slice( &get_i32(geometry.frame.y2));

    
    header.extend_from_slice( &get_i32(geometry.normal.x1));
    header.extend_from_slice( &get_i32(geometry.normal.y1));
    header.extend_from_slice( &get_i32(geometry.normal.x2));
    header.extend_from_slice( &get_i32(geometry.normal.y2));

    header.extend_from_slice( &get_i32(geometry.screen_no));

    header.extend_from_slice( &[geometry.is_maximized, geometry.is_fullscreen]);

    header.extend_from_slice( &get_i32(geometry.screen_width));

    header.extend_from_slice( &get_i32(geometry.client_rect.x1));
    header.extend_from_slice( &get_i32(geometry.client_rect.y1));
    header.extend_from_slice( &get_i32(geometry.client_rect.x2));
    header.extend_from_slice( &get_i32(geometry.client_rect.y2));

    base64::encode(header)
}

Example usage:

                let geom = QtGeom::new(0, 0, 1280, 720);
                let devices = block_on(sock_mem.as_ref().unwrap().general().open_projector(obws::requests::Projector {
                    ty: Some(obws::requests::ProjectorType::Preview),
                    monitor: None,
                    geometry: Some( &rect_to_geometry_str(geom) ),
                    name: None
                }));
               // -> will open a Projector at the top left  corner of display with 1280x720 size

Method to get whether recording or streaming is paused?

I've been looking for a way to determine if the recording or stream is currently paused. The methods to pause and unpause these functions will perform the action or return an error. It would be helpful to query whether we are currently paused so the appropriate method may be called (or ignored).

Does this feature exist in the OBS Websocket API?

Upgrade to obs-websocket 4.9.0

obs-websocket 4.9.0 was just released with lots of new requests and events and should be added to the API.

Maybe the requests to add new scenes and sources can help to make the integration tests setup a bit easier.

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.