obs-websocket-community-projects / obs-websocket-js

Consumes https://github.com/obsproject/obs-websocket
MIT License
661 stars 95 forks source link

obs-websocket-js doesn’t seem to work with the new Request Type ‘ExecuteBatch’ introduced in obs-websocket 4.9 #223

Closed leafac closed 3 years ago

leafac commented 3 years ago

Description:

doesnt-work.js

const OBSWebSocket = require("obs-websocket-js");

(async () => {
  const obs = new OBSWebSocket();
  await obs.connect({ address: "localhost:4444" });
  console.log(
    JSON.stringify(
      await obs.send("ExecuteBatch", [
        { "request-type": "GetStreamingStatus" },
      ]),
      undefined,
      2
    )
  ); // We never seem to get past this line; the connection is left open without an answer.
  await obs.disconnect();
})();

works.js

const WebSocket = require("ws");

const ws = new WebSocket("ws://localhost:4444");
ws.on("open", () => {
  ws.send(
    JSON.stringify({
      "request-type": "ExecuteBatch",
      "message-id": "1",
      requests: [{ "request-type": "GetStreamingStatus" }],
    })
  );
});

ws.on("message", (data) => {
  console.log(data);
  ws.close();
});

Versions Used (if applicable):

zoton2 commented 3 years ago

It took me some debugging before I realised the reason it isn't working is because you have written the initial script wrong.

If you change...

await obs.send("ExecuteBatch", [
  { "request-type": "GetStreamingStatus" },
]),

To the correct usage (which you are also using in the 2nd example)...

await obs.send("ExecuteBatch", {
  requests: [ { "request-type": "GetStreamingStatus" } ]
}),

...it executes correctly.

I did find out while testing this that the typings appear to be broken though for anything that expects an array of objects, but that's unrelated to the issue here.

It would be nice if the library returned an error though. It expects the argument to be an object, but in your case you are supplying an array which breaks it. A simple "is this an object" test should work. It's also weird because if you make this error in the 2nd example, you do get an error back from the obs-websocket plugin.

EDIT: I see why it hangs, it's because the message to send becomes very abnormal and stringifies into an object that has no message-id so there's no way to listen for it's error. So a check that you have supplied an object before sending anything is probably the best.

leafac commented 3 years ago

It took me some debugging before I realised the reason it isn't working is because you have written the initial script wrong.

If you change...

await obs.send("ExecuteBatch", [
  { "request-type": "GetStreamingStatus" },
]),

To the correct usage (which you are also using in the 2nd example)...

await obs.send("ExecuteBatch", {
  requests: [ { "request-type": "GetStreamingStatus" } ]
}),

...it executes correctly.

Ooops! Yeah, you’re right. I changed the first script and it worked. Thanks for correcting me.

I did find out while testing this that the typings appear to be broken though for anything that expects an array of objects, but that's unrelated to the issue here.

It would be nice if the library returned an error though. It expects the argument to be an object, but in your case you are supplying an array which breaks it. A simple "is this an object" test should work. It's also weird because if you make this error in the 2nd example, you do get an error back from the obs-websocket plugin.

EDIT: I see why it hangs, it's because the message to send becomes very abnormal and stringifies into an object that has no message-id so there's no way to listen for it's error. So a check that you have supplied an object before sending anything is probably the best.

Sounds good. Of course, it’s better if obs-websocket-js throws instead of hanging. Also, do you think having some sort of timeout as a last resort would be advantageous?

zoton2 commented 3 years ago

Yeah that might be a good idea too, obviously I'm not a maintainer of this project but I did already do a PR for the change I mentioned above.