erp
This commit is contained in:
10
fgfm.TODO
10
fgfm.TODO
@@ -1,5 +1,13 @@
|
|||||||
|
- Ability to control stream from web or twitch
|
||||||
|
- The OBS "director" and its state need to be accessible from both
|
||||||
|
- How to accomplish this? Websocket?
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
✔ Add cooldowns @done (18-10-02 10:16)
|
✔ Add cooldowns @done (18-10-02 10:16)
|
||||||
|
☐ Fix commercial playing issue (switches back to scene early)
|
||||||
|
☐ Change $auw and $meme to queue up the videos just like the others (don't switch scenes)
|
||||||
|
☐ Don't auto-init GHOBS or FGFM, make them on-demand
|
||||||
|
☐ Decouple twitch chat from GHOBS
|
||||||
☐ Move anything that calls director.state from app into fgfm lib
|
☐ Move anything that calls director.state from app into fgfm lib
|
||||||
☐ Restrict # of requests a user can have in the queue at once
|
☐ Restrict # of requests a user can have in the queue at once
|
||||||
☐ Move vrmode timer to this bot, delete from SLCB
|
☐ Move vrmode timer to this bot, delete from SLCB
|
||||||
@@ -9,7 +17,7 @@ TODO:
|
|||||||
☐ Web interface? Twitch extension?
|
☐ Web interface? Twitch extension?
|
||||||
☐ Improvements
|
☐ Improvements
|
||||||
☐ When playing a room back, loop it at slower speeds for a few iterations
|
☐ When playing a room back, loop it at slower speeds for a few iterations
|
||||||
☐ Support viewer skip voting
|
☐ Support viewer $skip voting
|
||||||
☐ Remove currently playing video from vote choices
|
☐ Remove currently playing video from vote choices
|
||||||
☐ Command to add sets of videos to the queue at once (like the entire ttas or all gold segments)
|
☐ Command to add sets of videos to the queue at once (like the entire ttas or all gold segments)
|
||||||
☐ Command to stop video rotation / timers (shutdown)
|
☐ Command to stop video rotation / timers (shutdown)
|
||||||
|
|||||||
100
lib/ghobs.js
100
lib/ghobs.js
@@ -10,76 +10,76 @@ function GHOBS(config) {
|
|||||||
this.websocket.connect({ address: this.config.obs.websocket.address, password: this.config.obs.websocket.password })
|
this.websocket.connect({ address: this.config.obs.websocket.address, password: this.config.obs.websocket.password })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log(`Success! We're connected to OBS!`);
|
console.log(`Success! We're connected to OBS!`);
|
||||||
this.websocket.getCurrentScene().then(res => this.currentScene = res.name);
|
this.websocket.getCurrentScene().then(currentScene => this.currentScene = currentScene.name);
|
||||||
this.websocket.onSwitchScenes(data => {
|
this.websocket.onSwitchScenes(newScene => this.currentScene = newScene.sceneName);
|
||||||
//console.log(`New Active Scene: ${data.sceneName}`);
|
|
||||||
this.currentScene = data.sceneName;
|
|
||||||
});
|
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
|
|
||||||
// Listen for errors from OBS
|
// Listen for errors from OBS
|
||||||
|
// @TODO: Handle socket disconnect gracefully
|
||||||
|
/** { status: 'error',
|
||||||
|
description: 'There is no Socket connection available.',
|
||||||
|
code: 'NOT_CONNECTED',
|
||||||
|
error: 'There is no Socket connection available.' }*/
|
||||||
this.websocket.on('error', err => {
|
this.websocket.on('error', err => {
|
||||||
console.error(`OBS websocket error: ${JSON.stringify(err)}`);
|
console.error(`OBS websocket error: ${JSON.stringify(err)}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// @TODO: pass any unrecognized commands to the websocket
|
// Plays a video in the current scene and hides when finished
|
||||||
|
this.playVideo = (video, callback) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// @TODO Validation of video
|
||||||
|
|
||||||
|
// set the file path on the source
|
||||||
|
let sourceSettings = {
|
||||||
|
local_file: video.filePath,
|
||||||
|
looping: (typeof video.loops !== 'undefined' && video.loops > 1)
|
||||||
|
};
|
||||||
|
sourceSettings.loop = sourceSettings.looping;
|
||||||
|
|
||||||
|
this.websocket.setSourceSettings({"sourceName": video.sceneItem, "sourceSettings": sourceSettings})
|
||||||
|
// show the video scene item
|
||||||
|
.then(() => this.websocket.setSceneItemProperties({"item": video.sceneItem, "visible": true}))
|
||||||
|
// when the video is over, hide it and trigger the user callback, but resolve promise immediately with the timer
|
||||||
|
.then(() => {
|
||||||
|
// if this video is being looped, adjust timeout length to allow the requested number of loops to complete
|
||||||
|
if (sourceSettings.loop === true) {
|
||||||
|
video.length *= video.loops;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve Promise with a timer of when the video will finish playback
|
||||||
|
// trigger user callback when the video finishes
|
||||||
|
resolve(setTimeout(() => {
|
||||||
|
this.websocket.setSceneItemProperties({"item": video.sceneItem, "visible": false});
|
||||||
|
if (typeof callback !== 'undefined') {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}, parseInt(video.length*1000)))
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Shows a video in the given scene/item and then hides it and switches back to the original scene when finished
|
// Shows a video in the given scene/item and then hides it and switches back to the original scene when finished
|
||||||
this.playVideoInScene = (video, scene, callback) => {
|
this.playVideoInScene = (video, scene, callback) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
video.scene = scene;
|
||||||
let originalScene = this.currentScene || false;
|
let originalScene = this.currentScene || false;
|
||||||
//console.log(`Changing scene from ${originalScene} to ${scene}`);
|
let handleVideoEnd = () => {
|
||||||
this.websocket.setCurrentScene({"scene-name": scene})
|
if (originalScene !== false) {
|
||||||
.then(res => {
|
|
||||||
// set the file path on the source
|
|
||||||
//console.log(`Setting file path to: ${video.filePath}`);
|
|
||||||
let sourceSettings = {
|
|
||||||
"local_file": video.filePath,
|
|
||||||
"looping": (typeof video.loops !== 'undefined' && video.loops > 1)
|
|
||||||
};
|
|
||||||
sourceSettings.loop = sourceSettings.looping;
|
|
||||||
|
|
||||||
// @TODO loop room vids at a slower speed for a few iterations
|
|
||||||
// @TODO support any sourceSetting?
|
|
||||||
//
|
|
||||||
/*{ close_when_inactive: true,
|
|
||||||
local_file: 'Y:\\media\\videos\\ALttP\\my-vids\\room-vids\\11-mire\\38-wizzpot-rta-hook-610.mp4',
|
|
||||||
loop: true,
|
|
||||||
looping: false,
|
|
||||||
restart_on_activate: false,
|
|
||||||
speed_percent: 100 }*/
|
|
||||||
|
|
||||||
//this.websocket.getSourceSettings({"sourceName": video.sceneItem}).then(console.log);
|
|
||||||
|
|
||||||
this.websocket.setSourceSettings({"sourceName": video.sceneItem, "sourceSettings": sourceSettings})
|
|
||||||
// show the video scene item
|
|
||||||
.then(() => this.websocket.setSceneItemProperties({"item": video.sceneItem, "scene-name": scene, "visible": true}))
|
|
||||||
// when the video is over, hide it and trigger the user callback, but resolve promise immediately with the timer
|
|
||||||
.then(data => {
|
|
||||||
// adjust timeout length to allow the requested number of loops to complete
|
|
||||||
if (sourceSettings.loop === true) {
|
|
||||||
video.length *= video.loops;
|
|
||||||
console.log(`Video is set to loop, adjusted length to ${video.length}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(setTimeout(() => {
|
|
||||||
//console.log(`Hiding ${video.sceneItem}`);
|
|
||||||
this.websocket.setSceneItemProperties({"item": video.sceneItem, "scene-name": scene, "visible": false});
|
|
||||||
if (originalScene) {
|
|
||||||
//console.log(`Switching scene back to ${originalScene}`);
|
|
||||||
this.websocket.setCurrentScene({"scene-name": originalScene});
|
this.websocket.setCurrentScene({"scene-name": originalScene});
|
||||||
}
|
}
|
||||||
if (typeof callback !== 'undefined') {
|
if (typeof callback !== 'undefined') {
|
||||||
//console.log('Triggering user callback');
|
callback();
|
||||||
callback(data);
|
|
||||||
}
|
}
|
||||||
}, parseInt(video.length*1000)))
|
};
|
||||||
});
|
|
||||||
})
|
this.websocket.setCurrentScene({"scene-name": scene})
|
||||||
|
.then(() => this.playVideo(video, handleVideoEnd))
|
||||||
|
.then(timer => resolve)
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user