Skip to content

Commit

Permalink
Update to obs-websocket-js v5
Browse files Browse the repository at this point in the history
  • Loading branch information
zoton2 committed Jul 13, 2024
1 parent 4bf63c2 commit 2728bba
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 58 deletions.
5 changes: 5 additions & 0 deletions .eslintrc.extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ module.exports = {
ts: 'never',
tsx: 'never',
}],

// Additional rules not from the template.
'require-await': 'off', // May not be needed but including for safety
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/no-floating-promises': 'error',
},

// Overrides for types.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@nodecg/types": "^2.1.12",
"module-alias": "^2.2.3",
"needle": "^3.3.1",
"obs-websocket-js": "^4.0.3",
"obs-websocket-js": "^5.0.5",
"socket.io-client": "^4.7.5",
"speedcontrol-util": "github:speedcontrol/speedcontrol-util.git#build"
},
Expand Down
64 changes: 38 additions & 26 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions src/extension/commercial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ sc.on('timerReset', () => {
async function playBreakCommercials(): Promise<void> {
try {
// If we're no longer on an appropriate scene, stop trying to play non-run commercials.
const scene = await obs.send('GetCurrentScene');
const isSceneNonRun = !!nonRunCommercialScenes.find((s) => scene.name.startsWith(s));
const scene = await obs.call('GetCurrentProgramScene');
const isSceneNonRun = !!nonRunCommercialScenes.find((s) => scene.sceneName.startsWith(s));
if (!isSceneNonRun) {
if (intermissionCommercialTO) {
clearTimeout(intermissionCommercialTO);
Expand Down Expand Up @@ -164,13 +164,13 @@ async function playBreakCommercials(): Promise<void> {
}

// Trigger a Twitch commercial when on the relevant scene.
obs.on('SwitchScenes', async (data) => {
if (data['scene-name'].startsWith(config.obs.nonRunCommercialTriggerScene)
obs.on('CurrentProgramSceneChanged', (data) => {
if (data.sceneName.startsWith(config.obs.nonRunCommercialTriggerScene)
&& !intermissionCommercialTO && !intermissionCommercials.specialLogic) {
playBreakCommercials();
playBreakCommercials().catch(() => {});
}

const isSceneNonRun = !!nonRunCommercialScenes.find((s) => data['scene-name'].startsWith(s));
const isSceneNonRun = !!nonRunCommercialScenes.find((s) => data.sceneName.startsWith(s));

// Only used by esa-layouts so we can continue playing commercials once our intermission player
// ones have finished. Once we've switched to a relevant scene, skips the first (and second)
Expand Down
2 changes: 1 addition & 1 deletion src/extension/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ async function changeTwitchMetadata(title?: string, gameId?: string): Promise<vo
}

// eslint-disable-next-line import/prefer-default-export
export async function setup(): Promise<void> {
export function setup(): void {
if (!config.server.enabled) return;
nodecg().log.info('[Server] Setting up');

Expand Down
60 changes: 38 additions & 22 deletions src/extension/util/obs.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,59 @@
import OBSWebSocketJS from 'obs-websocket-js';
import OBSWebSocket, { EventSubscription, OBSWebSocketError } from 'obs-websocket-js';
import { get as nodecg } from './nodecg';

const config = nodecg().bundleConfig.obs;

const obs = new OBSWebSocketJS();
const obs = new OBSWebSocket();
let obsStreaming = false;
const settings = {
address: config.address,
password: config.password,
};

async function connect(): Promise<void> {
try {
await obs.connect(settings);
const streamingStatus = await obs.send('GetStreamingStatus');
obsStreaming = streamingStatus.streaming;
nodecg().log.info('[OBS] Connection successful');
const {
obsWebSocketVersion,
rpcVersion,
} = await obs.connect(
config.address,
config.password,
{
// eslint-disable-next-line no-bitwise
eventSubscriptions: EventSubscription.MediaInputs | EventSubscription.Transitions,
},
);
nodecg().log.debug(
'[OBS] Connected (version: %s, RPC: %s)',
obsWebSocketVersion,
rpcVersion,
);
const data = await obs.call('GetStreamStatus');
obsStreaming = data.outputActive;
} catch (err) {
nodecg().log.warn('[OBS] Connection error');
nodecg().log.debug('[OBS] Connection error:', err);
try {
await obs.disconnect();
} catch { /* ignore errors */ }
nodecg().log.warn(
'[OBS] Connection error (reason: %s - %s)',
(err as OBSWebSocketError).code ?? 'N/A',
(err as OBSWebSocketError).message || 'N/A',
);
}
}

if (config.enabled) {
nodecg().log.info('[OBS] Setting up connection');
connect();
obs.on('StreamStarted', () => { obsStreaming = true; });
obs.on('StreamStopped', () => { obsStreaming = false; });
obs.on('ConnectionClosed', () => {
nodecg().log.warn('[OBS] Connection lost, retrying in 5 seconds');
connect().catch(() => {});
obs.on('StreamStateChanged', (data) => { obsStreaming = data.outputActive; });
obs.on('ConnectionClosed', (data) => {
nodecg().log.warn(
'[OBS] Connection closed (reason: %s - %s)',
data.code ?? 'N/A',
data.message || 'N/A',
);
setTimeout(connect, 5000);
});
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Pretty sure this emits an error.
obs.on('error', (err) => {
nodecg().log.warn('[OBS] Connection error');
nodecg().log.debug('[OBS] Connection error:', err);
obs.on('ConnectionError', (err) => {
nodecg().log.warn('[OBS] Connection error (reason: %s - %s):', err.code, err.message);
});

export function isStreaming(): boolean {
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.browser.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
"noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
"noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
Expand Down

0 comments on commit 2728bba

Please sign in to comment.