From 90bf441a73461737665fa6b4eb23a4534a1458a9 Mon Sep 17 00:00:00 2001 From: Jocke4f <39942694+Jocke4f@users.noreply.github.com> Date: Sun, 18 Aug 2024 18:27:10 +0200 Subject: [PATCH] Websocket5 update Updated websocket5 and added support for nested scenes with Websocket5 for OBS. Support for groups is not added. --- package-lock.json | 89 ++++++++++++++++++++++++++++++---------------- package.json | 2 +- src/sources/OBS.ts | 52 +++++++++++++++++++++------ 3 files changed, 102 insertions(+), 41 deletions(-) diff --git a/package-lock.json b/package-lock.json index e6200ade..6a7d250f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,7 @@ "jspack": "^0.0.4", "node-emberplus": "^3.0.5", "obs-websocket-js": "npm:obs-websocket-js@^4.0.3", - "obs-websocket-js-5": "npm:obs-websocket-js@^5.0.2", + "obs-websocket-js-5": "npm:obs-websocket-js@^5.0.6", "osc": "^2.4.3", "rate-limiter-flexible": "^2.3.7", "reflect-metadata": "^0.1.13", @@ -4456,43 +4456,61 @@ }, "node_modules/obs-websocket-js-5": { "name": "obs-websocket-js", - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/obs-websocket-js/-/obs-websocket-js-5.0.2.tgz", - "integrity": "sha512-4XxWd5abIFOk0HjIHk+X/NwSXuOTPGsNnn7845g0UQZV0T3AtNk+dfp21zSjJVzuN/5oZR3UKjzEqg8pxMndCA==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/obs-websocket-js/-/obs-websocket-js-5.0.6.tgz", + "integrity": "sha512-tHRq8py1XrdlMhSV+N/KTGHqoRIcsBBXbjcA9ex21k128iQ7YXjxzNWs3s9gidP1tEcIyVuJu8FnPgrSBWGm0Q==", + "license": "MIT", "dependencies": { "@msgpack/msgpack": "^2.7.1", "crypto-js": "^4.1.1", "debug": "^4.3.2", - "eventemitter3": "^4.0.7", - "isomorphic-ws": "^4.0.1", - "type-fest": "^2.3.2", - "ws": "^8.2.2" + "eventemitter3": "^5.0.1", + "isomorphic-ws": "^5.0.0", + "type-fest": "^3.11.0", + "ws": "^8.13.0" }, "engines": { - "node": ">12.0" + "node": ">16.0" + } + }, + "node_modules/obs-websocket-js-5/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/obs-websocket-js-5/node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", + "peerDependencies": { + "ws": "*" } }, "node_modules/obs-websocket-js-5/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=12.20" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/obs-websocket-js-5/node_modules/ws": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", - "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -9743,28 +9761,39 @@ } }, "obs-websocket-js-5": { - "version": "npm:obs-websocket-js@5.0.2", - "resolved": "https://registry.npmjs.org/obs-websocket-js/-/obs-websocket-js-5.0.2.tgz", - "integrity": "sha512-4XxWd5abIFOk0HjIHk+X/NwSXuOTPGsNnn7845g0UQZV0T3AtNk+dfp21zSjJVzuN/5oZR3UKjzEqg8pxMndCA==", + "version": "npm:obs-websocket-js@5.0.6", + "resolved": "https://registry.npmjs.org/obs-websocket-js/-/obs-websocket-js-5.0.6.tgz", + "integrity": "sha512-tHRq8py1XrdlMhSV+N/KTGHqoRIcsBBXbjcA9ex21k128iQ7YXjxzNWs3s9gidP1tEcIyVuJu8FnPgrSBWGm0Q==", "requires": { "@msgpack/msgpack": "^2.7.1", "crypto-js": "^4.1.1", "debug": "^4.3.2", - "eventemitter3": "^4.0.7", - "isomorphic-ws": "^4.0.1", - "type-fest": "^2.3.2", - "ws": "^8.2.2" + "eventemitter3": "^5.0.1", + "isomorphic-ws": "^5.0.0", + "type-fest": "^3.11.0", + "ws": "^8.13.0" }, "dependencies": { + "eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "requires": {} + }, "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==" + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==" }, "ws": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", - "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "requires": {} } } diff --git a/package.json b/package.json index fa5f27f3..442f08b4 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "jspack": "^0.0.4", "node-emberplus": "^3.0.5", "obs-websocket-js": "npm:obs-websocket-js@^4.0.3", - "obs-websocket-js-5": "npm:obs-websocket-js@^5.0.2", + "obs-websocket-js-5": "npm:obs-websocket-js@^5.0.6", "osc": "^2.4.3", "rate-limiter-flexible": "^2.3.7", "reflect-metadata": "^0.1.13", diff --git a/src/sources/OBS.ts b/src/sources/OBS.ts index 29371ef6..5f97a985 100644 --- a/src/sources/OBS.ts +++ b/src/sources/OBS.ts @@ -422,19 +422,19 @@ export class OBSSource extends TallyInput { }); this.obsClient5.on("CurrentPreviewSceneChanged", (data) => { - this.scenes5.forEach((scene) => { - if(scene !== data.sceneName) this.removeBusFromAddress(scene, "preview"); - }); - this.setBussesForAddress(data.sceneName, ["preview"]); - this.sendTallyData(); + this.removeBusFromAllAddresses("preview"); + this.addBusToAddress(data.sceneName, "preview"); + this.processSceneChange5(data.sceneName, "preview"); + + //this.sendTallyData(); }); this.obsClient5.on("CurrentProgramSceneChanged", (data) => { - this.scenes5.forEach((scene) => { - if(scene !== data.sceneName) this.removeBusFromAddress(scene, "program"); - }); - this.setBussesForAddress(data.sceneName, ["program"]); - this.sendTallyData(); + this.removeBusFromAllAddresses("program"); + this.addBusToAddress(data.sceneName, "program"); + this.processSceneChange5(data.sceneName, "program"); + + // this.sendTallyData(); }); this.obsClient5.on("CurrentSceneCollectionChanged", (data) => { @@ -585,9 +585,11 @@ export class OBSSource extends TallyInput { } if(scene === data.currentPreviewSceneName) { this.setBussesForAddress(scene, ["preview"]); + this.processSceneChange5(scene, "preview"); } if(scene === data.currentProgramSceneName) { this.setBussesForAddress(scene, ["program"]); + this.processSceneChange5(scene, "program") } if(scene != data.currentPreviewSceneName && scene != data.currentProgramSceneName) { this.setBussesForAddress(scene, []); @@ -598,6 +600,7 @@ export class OBSSource extends TallyInput { }); } + /** Adds a bus to the scene, nested scenes and scene sources. * @param sceneName - Name of the scene. * @param sources - List of scene sources (SceneItem). @@ -618,6 +621,35 @@ export class OBSSource extends TallyInput { this.addBusToAddress(sceneName, bus); } + + /** Adds a bus for the scene, nested scenes and scene sources. + * @param sceneName - Name of the scene. + * @param bus - Bus to assign (preview/program). + */ + private processSceneChange5(sceneName: string, bus: string): void { + // No support for specific handling for Groups since Group usage is discouraged in OBS, see https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#getsceneitemlist + this.obsClient5.call("GetSceneItemList", { sceneName: sceneName}).then((sceneItems) => { + + let sceneSources = 0; + for (let i = 0; i < sceneItems.sceneItems.length; i++) { + // All scene source items to the bus + // Should a check be done for audio input if they are enabled? + this.addBusToAddress(sceneItems.sceneItems[i].sourceName as string, bus); + if (sceneItems.sceneItems[i].sourceType == "OBS_SOURCE_TYPE_INPUT") { + sceneSources++; + } else if (sceneItems.sceneItems[i].sourceType == "OBS_SOURCE_TYPE_SCENE") { + // Nested scene, dig deeper... + this.processSceneChange5(sceneItems.sceneItems[i].sourceName as string, bus); + } + } + + // If this scene doesn't contain a scene then we trigger this.sendTallyData(). + // The check is done to keep uncessary updates to a minimum. + if (sceneSources == sceneItems.sceneItems.length) {this.sendTallyData();} + }); + } + + /** Adds audio input to addresses, to the "audioInputs" list and change tally bus if it's not muted. */ private addAudioInput(input): void { if (this.obsProtocolVersion === 4) {