room vids
This commit is contained in:
1
conf/rooms.json
Normal file
1
conf/rooms.json
Normal file
File diff suppressed because one or more lines are too long
@@ -48,5 +48,8 @@
|
||||
"auwChance": 25,
|
||||
"defaultSRVolume": 75,
|
||||
"vodConfigFile": "./conf/vods.json",
|
||||
"roomConfigFile": "./conf/rooms.json",
|
||||
"roomVidsBasePath": "Y:\\media\\videos\\ALttP\\my-vids\\room-vids",
|
||||
"roomVidPlaytime": 60,
|
||||
"debug": false
|
||||
}
|
||||
18
fgfm.TODO
18
fgfm.TODO
@@ -1,15 +1,25 @@
|
||||
TODO:
|
||||
☐ Room vid requests / import
|
||||
☐ Importing
|
||||
- Read the Y:\media\videos\ALttP\my-vids\room-vids directory
|
||||
- Go through each folder and get all the .mp4 files
|
||||
- Store the following as metadata:
|
||||
- root folder name
|
||||
- original file name
|
||||
- keywords
|
||||
- dungeon (parse from root folder name)
|
||||
- room ID
|
||||
- video length
|
||||
☐ Support viewer skip voting
|
||||
☐ 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)
|
||||
☐ support for $pause
|
||||
☐ Command to stop video rotation / timers (shutdown)
|
||||
☐ Restrict # of requests a user can have in the queue at once
|
||||
☐ Start/stop stream automation
|
||||
☐ Stream alerts for chat
|
||||
☐ remove currently playing video from vote choices
|
||||
☐ restrict # of requests a user can have in the queue at once
|
||||
☐ Support for $pause -- not sure how to pull this off
|
||||
☐ Add cooldowns
|
||||
☐ Tool to output list of video ID's / descriptions
|
||||
☐ Stream alerts for chat
|
||||
☐ Rotating background images (leftside)
|
||||
|
||||
Ideas:
|
||||
|
||||
36
fgfm.js
36
fgfm.js
@@ -11,6 +11,7 @@ const GHOBS = require('./lib/ghobs');
|
||||
// Read internal configuration
|
||||
let config = require('./config.json');
|
||||
config.vods = require(config.vodConfigFile);
|
||||
config.rooms = require(config.roomConfigFile);
|
||||
let snesGames = require('./conf/snesgames.json');
|
||||
|
||||
// Set up initial state
|
||||
@@ -104,6 +105,23 @@ const streamInit = (config, twitch) => {
|
||||
.catch(console.error);
|
||||
};
|
||||
|
||||
const addRoomVideo = room => {
|
||||
let loops = Math.floor(config.roomVidPlaytime / room.videoData.length);
|
||||
console.log(`Adding ${loops} instances of room video for ${room.dungeonName} - ${room.roomName} to the queue`);
|
||||
|
||||
let video = {
|
||||
"filePath": `${config.roomVidsBasePath}${room.winPath}`,
|
||||
"sceneItem": (room.videoData.width === 960) ? "4x3ph" : "16x9ph",
|
||||
"length": room.videoData.length,
|
||||
"label": room.roomName,
|
||||
"chatName": room.roomName
|
||||
};
|
||||
|
||||
for (var i = 0; i < loops; i++) {
|
||||
state.videoQueue.push(video);
|
||||
}
|
||||
};
|
||||
|
||||
// Picks the next video in the queue (shuffles if empty)
|
||||
// Also handles "commercial breaks" if enabled
|
||||
const nextVideo = () => {
|
||||
@@ -247,6 +265,24 @@ const streamInit = (config, twitch) => {
|
||||
|
||||
obs.toggleVisible(sceneItem).catch(console.error);
|
||||
|
||||
// ROOM VIDS
|
||||
} else if (commandNoPrefix === 'room') {
|
||||
let roomId = commandParts[1] || false;
|
||||
if (roomId.length !== 4) {
|
||||
twitch.botChat.say(to, `Please provide a 4-digit room ID!`);
|
||||
return;
|
||||
}
|
||||
|
||||
let roomIndex = config.rooms.findIndex(e => e.dungeonId === roomId.substring(0,2) && e.roomId === roomId.substring(2,4));
|
||||
if (roomIndex === -1) {
|
||||
twitch.botChat.say(to, `No room found matching that ID!`);
|
||||
return;
|
||||
}
|
||||
|
||||
let room = config.rooms[roomIndex];
|
||||
addRoomVideo(room);
|
||||
twitch.botChat.say(to, `Added ${room.dungeonName} - ${room.roomName} to the queue!`);
|
||||
|
||||
// EVERYBODY WOW
|
||||
} else if (commandNoPrefix === 'auw') {
|
||||
state.commercialPlaying = true;
|
||||
|
||||
121
package-lock.json
generated
121
package-lock.json
generated
@@ -198,11 +198,6 @@
|
||||
"safer-buffer": "2.1.2"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
@@ -223,6 +218,15 @@
|
||||
"resolved": "https://registry.npmjs.org/ffmpeg-binaries/-/ffmpeg-binaries-3.2.2.tgz",
|
||||
"integrity": "sha1-Nw8wIO9rTbpipVGkJcY01sdaOiE="
|
||||
},
|
||||
"fluent-ffmpeg": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
|
||||
"integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=",
|
||||
"requires": {
|
||||
"async": "2.6.1",
|
||||
"which": "1.3.1"
|
||||
}
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
@@ -289,28 +293,6 @@
|
||||
"resolved": "https://registry.npmjs.org/irc-colors/-/irc-colors-1.4.3.tgz",
|
||||
"integrity": "sha512-VeAnFC9fkb4nB/s6UtTNf3BH2wOk/sSBSzIzCpFwrgoFxVl6J5sov7FXXA0kmbk/mVAZQXfXAsQFjWnGPf4cRg=="
|
||||
},
|
||||
"ircv3": {
|
||||
"version": "0.8.12",
|
||||
"resolved": "https://registry.npmjs.org/ircv3/-/ircv3-0.8.12.tgz",
|
||||
"integrity": "sha512-q4WrRzbUPfN8FNunnv7zdQXAdguRr1uJg6F2P6fxBcrhu92u+QcfRXacDRTX03BGaxd+D1nQe9jkmP5T9c/4sw==",
|
||||
"requires": {
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"universal-websocket-client": "1.0.2",
|
||||
"ws": "3.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
|
||||
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
|
||||
"requires": {
|
||||
"async-limiter": "1.0.0",
|
||||
"safe-buffer": "5.1.2",
|
||||
"ultron": "1.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-buffer": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||
@@ -329,6 +311,11 @@
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
@@ -613,24 +600,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"request-promise-core": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
|
||||
"integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=",
|
||||
"requires": {
|
||||
"lodash": "4.17.11"
|
||||
}
|
||||
},
|
||||
"request-promise-native": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz",
|
||||
"integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=",
|
||||
"requires": {
|
||||
"request-promise-core": "1.1.1",
|
||||
"stealthy-require": "1.1.1",
|
||||
"tough-cookie": "2.4.3"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
@@ -676,11 +645,6 @@
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"stealthy-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
|
||||
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
@@ -690,11 +654,6 @@
|
||||
"punycode": "1.4.1"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
|
||||
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
@@ -709,50 +668,6 @@
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
},
|
||||
"twitch": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/twitch/-/twitch-1.0.0.tgz",
|
||||
"integrity": "sha512-LRg7SwtwKPEtdXcKgQHh55YdT+oI2nqHKCBs+4coxK2Mtc5btwrQjaSbulEXwZaypEW1yyWT6x6g+Bo6IX3FBw==",
|
||||
"requires": {
|
||||
"request": "2.88.0",
|
||||
"request-promise-native": "1.0.5",
|
||||
"tslib": "1.9.3"
|
||||
}
|
||||
},
|
||||
"twitch-chat-client": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/twitch-chat-client/-/twitch-chat-client-1.1.0.tgz",
|
||||
"integrity": "sha512-5BfGHhDtxvlvLJ2samqYzb9EPRTpTvZ5J5eXfZOWmqdGix8TgDELgsptIcrVLI7llACI0kpN6wgyLG/4OlXUhQ==",
|
||||
"requires": {
|
||||
"ircv3": "0.8.12",
|
||||
"tslib": "1.9.3"
|
||||
}
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
|
||||
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
|
||||
},
|
||||
"universal-websocket-client": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/universal-websocket-client/-/universal-websocket-client-1.0.2.tgz",
|
||||
"integrity": "sha512-Pi6BdJtEAISb77GTbOLBLIWdYGezXgnJejrVBYKXxzNTsLcjJS+mWIJ2BRZElSlOG/wc7+yfOe5y30bzTu3Qqg==",
|
||||
"requires": {
|
||||
"ws": "3.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
|
||||
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
|
||||
"requires": {
|
||||
"async-limiter": "1.0.0",
|
||||
"safe-buffer": "5.1.2",
|
||||
"ultron": "1.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
@@ -768,6 +683,14 @@
|
||||
"extsprintf": "1.3.0"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||
"requires": {
|
||||
"isexe": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"async": "^2.6.1",
|
||||
"discord.js": "^11.4.2",
|
||||
"ffmpeg-binaries": "^3.2.2",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"irc": "^0.5.2",
|
||||
"md5": "^2.2.1",
|
||||
"memcache": "^0.3.0",
|
||||
|
||||
67
room-vid-import.js
Executable file
67
room-vid-import.js
Executable file
@@ -0,0 +1,67 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const util = require('./lib/util');
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
|
||||
let roomVidPath = `/var/hypnoadmin/media/videos/ALttP/my-vids/room-vids`;
|
||||
|
||||
const getAllFiles = dir =>
|
||||
fs.readdirSync(dir).reduce((files, file) => {
|
||||
const name = path.join(dir, file);
|
||||
const isDirectory = fs.statSync(name).isDirectory();
|
||||
return isDirectory ? [...files, ...getAllFiles(name)] : [...files, name];
|
||||
}, []);
|
||||
|
||||
let roomVidFiles = getAllFiles(roomVidPath);
|
||||
|
||||
populateDatabase();
|
||||
|
||||
async function populateDatabase() {
|
||||
let database = [];
|
||||
await util.asyncForEach(roomVidFiles, async (file) => {
|
||||
// @TODO: ignore anything that's not an mp4
|
||||
let shortPath = file.replace(roomVidPath, '');
|
||||
if (!/\.mp4$/.test(shortPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let entry = {
|
||||
shortPath: shortPath,
|
||||
winPath: shortPath.replace(/\//g, '\\')
|
||||
};
|
||||
|
||||
// chop up the short path and extract metadata
|
||||
let matches = shortPath.match(/^\/([0-9]{2})-([a-z]+)\/([0-9]{2})-(.+)\.mp4/);
|
||||
if (matches) {
|
||||
entry.dungeonId = matches[1];
|
||||
entry.dungeonName = matches[2];
|
||||
entry.roomId = matches[3];
|
||||
entry.roomName = matches[4];
|
||||
}
|
||||
|
||||
entry.videoData = await getVideoMetadata(file);
|
||||
database.push(entry);
|
||||
console.log('added entry', entry);
|
||||
});
|
||||
|
||||
fs.writeFile('conf/rooms.json', JSON.stringify(database), 'utf8', () => {console.log('done')});
|
||||
}
|
||||
|
||||
function getVideoMetadata(videoPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
ffmpeg.ffprobe(videoPath, (err, metadata) => {
|
||||
// find the video stream
|
||||
let stream = metadata.streams.find(e => e.codec_type === "video");
|
||||
if (!stream) {
|
||||
resolve(false);
|
||||
}
|
||||
|
||||
resolve({
|
||||
width: stream.width,
|
||||
height: stream.height,
|
||||
fps: parseInt(stream.r_frame_rate.replace('/1', '')),
|
||||
length: stream.duration
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user