Add ffmpeg list demux types feature. Add websocket basic server. Add browser build project with stub websocket.

This commit is contained in:
mmcwilliams 2024-05-15 17:29:59 -04:00
parent b0c1431bd6
commit 9aaf9a215d
18 changed files with 210 additions and 21 deletions

21
browser/index.ts Normal file
View File

@ -0,0 +1,21 @@
class Client {
private client : WebSocket;
private connected : boolean = false;
constructor () {
let uri : string = 'ws://localhost:8082';
this.client = new WebSocket(uri);
this.client.onopen = this.onOpen.bind(this);
this.client.onmessage = this.onMessage.bind(this);
}
private onMessage (event : any) {
console.log(event.data);
}
private onOpen (event : any) {
console.log('Connected');
this.connected = true;
}
}
new Client();

View File

@ -5,6 +5,7 @@ WS_PORT=8081
WIDTH=2560
HEIGHT=1600
FD=../filmout_display/build/bin/fd
FFMPEG=ffmpeg
FD_HOST=localhost
FD_PORT=8081
VIDEOS=/home/users/VIDEOS

View File

@ -46,7 +46,7 @@ class FFMPEG {
if (row.startsWith(' DE ')) {
key = row.substring(4, row.length - 1).split(' ')[0];
description = row.replace(key, '').trim();
this.log.info(key);
//this.log.info(key);
/*try {
this.log.info(await this.demuxerInfo(key));
} catch (err) {
@ -60,7 +60,7 @@ class FFMPEG {
else if (row.startsWith(' D ')) {
key = row.substring(4, row.length - 1).split(' ')[0];
description = row.replace(key, '').trim();
this.log.info(key);
//this.log.info(key);
/*try {
this.log.info(await this.demuxerInfo(key));
} catch (err) {

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ffmpeg/index.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ffmpeg/index.ts"],"names":[],"mappings":"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"}

23
dist/files/index.js vendored
View File

@ -7,7 +7,7 @@ exports.Files = void 0;
const promises_1 = __importDefault(require("fs/promises"));
const hash_1 = require("../hash");
const path_1 = require("path");
const fileExtension = [
const fileExtensions = [
'.mp4',
'.mkv',
'.mov'
@ -53,6 +53,27 @@ class Files {
const videos = [];
let all;
let stats;
try {
all = await promises_1.default.readdir(path);
}
catch (err) {
throw err;
}
for (let elem of all) {
try {
stats = await promises_1.default.lstat(elem);
if (stats.isFile() && fileExtensions.indexOf((0, path_1.extname)((0, path_1.basename)(elem))) !== -1) {
videos.push({
path: elem,
hash: hash_1.Hashes.stringHash(elem),
name: (0, path_1.basename)(elem)
});
}
}
catch (err) {
//
}
}
return videos;
}
}

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/files/index.ts"],"names":[],"mappings":";;;;;;AAAA,2DAA6B;AAE7B,kCAAiC;AACjC,+BAAyC;AAczC,MAAM,aAAa,GAAc;IAChC,MAAM;IACN,MAAM;IACN,MAAM;CACN,CAAC;AAEF,MAAa,KAAK;IACV,MAAM,CAAC,KAAK,CAAC,MAAM,CAAE,IAAa;QACxC,IAAI,CAAC;YACJ,MAAM,kBAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,OAAO,IAAI,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAE,IAAa;QACpD,MAAM,IAAI,GAAsB,EAAE,CAAC;QACnC,IAAI,GAAc,CAAC;QACnB,IAAI,KAAa,CAAC;QAClB,IAAI,CAAC;YACJ,GAAG,GAAG,MAAM,kBAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,GAAG,CAAC;QACX,CAAC;QAED,KAAK,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC;gBACJ,KAAK,GAAG,MAAM,kBAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC;wBACT,IAAI,EAAG,IAAI;wBACX,IAAI,EAAG,aAAM,CAAC,UAAU,CAAC,IAAI,CAAC;wBAC9B,IAAI,EAAG,IAAA,eAAQ,EAAC,IAAI,CAAC;qBACrB,CAAC,CAAC;gBACJ,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,EAAE;YACH,CAAC;QACF,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,eAAe,CAAE,IAAa;QACjD,MAAM,MAAM,GAAmB,EAAE,CAAC;QAClC,IAAI,GAAc,CAAC;QACnB,IAAI,KAAa,CAAC;QAElB,OAAO,MAAM,CAAC;IACf,CAAC;CACD;AA7CD,sBA6CC;AAGD,MAAM,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/files/index.ts"],"names":[],"mappings":";;;;;;AAAA,2DAA6B;AAE7B,kCAAiC;AACjC,+BAAyC;AAczC,MAAM,cAAc,GAAc;IACjC,MAAM;IACN,MAAM;IACN,MAAM;CACN,CAAC;AAEF,MAAa,KAAK;IACV,MAAM,CAAC,KAAK,CAAC,MAAM,CAAE,IAAa;QACxC,IAAI,CAAC;YACJ,MAAM,kBAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,OAAO,IAAI,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAE,IAAa;QACpD,MAAM,IAAI,GAAsB,EAAE,CAAC;QACnC,IAAI,GAAc,CAAC;QACnB,IAAI,KAAa,CAAC;QAClB,IAAI,CAAC;YACJ,GAAG,GAAG,MAAM,kBAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,GAAG,CAAC;QACX,CAAC;QAED,KAAK,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC;gBACJ,KAAK,GAAG,MAAM,kBAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC;wBACT,IAAI,EAAG,IAAI;wBACX,IAAI,EAAG,aAAM,CAAC,UAAU,CAAC,IAAI,CAAC;wBAC9B,IAAI,EAAG,IAAA,eAAQ,EAAC,IAAI,CAAC;qBACrB,CAAC,CAAC;gBACJ,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,EAAE;YACH,CAAC;QACF,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,eAAe,CAAE,IAAa;QACjD,MAAM,MAAM,GAAmB,EAAE,CAAC;QAClC,IAAI,GAAc,CAAC;QACnB,IAAI,KAAa,CAAC;QAElB,IAAI,CAAC;YACJ,GAAG,GAAG,MAAM,kBAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,GAAG,CAAC;QACX,CAAC;QAED,KAAK,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC;gBACJ,KAAK,GAAG,MAAM,kBAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,cAAc,CAAC,OAAO,CAAC,IAAA,cAAO,EAAC,IAAA,eAAQ,EAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;oBAC9E,MAAM,CAAC,IAAI,CAAC;wBACX,IAAI,EAAG,IAAI;wBACX,IAAI,EAAG,aAAM,CAAC,UAAU,CAAC,IAAI,CAAC;wBAC9B,IAAI,EAAG,IAAA,eAAQ,EAAC,IAAI,CAAC;qBACrB,CAAC,CAAC;gBACJ,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,EAAE;YACH,CAAC;QACF,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;CACD;AAlED,sBAkEC;AAGD,MAAM,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC"}

40
dist/index.js vendored
View File

@ -30,16 +30,20 @@ require("dotenv/config");
const express_1 = __importDefault(require("express"));
const promises_1 = __importDefault(require("fs/promises"));
const body_parser_1 = __importDefault(require("body-parser"));
const uuid_1 = require("uuid");
const Handlebars = __importStar(require("handlebars"));
const ws_1 = require("ws");
const log_1 = require("./log");
const files_1 = require("./files");
const ffmpeg_1 = require("./ffmpeg");
const log = (0, log_1.createLog)('fm');
const app = (0, express_1.default)();
let wss;
let fd;
let ffmpeg;
let index;
let port;
let wsPort;
let sequences;
let videos;
let width;
@ -47,6 +51,7 @@ let height;
log.info('Starting filmout_manager...');
app.use(body_parser_1.default.json());
app.use(body_parser_1.default.urlencoded({ extended: true }));
app.use('/static', express_1.default.static('./static'));
async function createTemplate(filePath) {
let tmpl;
try {
@ -68,6 +73,13 @@ async function settings() {
else {
log.info(`FD=${process.env['FD']}`);
}
if (typeof process.env['FFMPEG'] === 'undefined') {
log.error('Please include an FFMPEG value containing the path to your ffmpeg binary in .env');
process.exit(1);
}
else {
log.info(`FFMPEG=${process.env['FFMPEG']}`);
}
if (typeof process.env['WIDTH'] === 'undefined') {
log.error('Please include a WIDTH value containing the width of the screen you are using in .env');
process.exit(2);
@ -106,6 +118,14 @@ async function settings() {
port = parseInt(process.env['PORT']);
log.info(`PORT=${port}`);
}
if (typeof process.env['WS_PORT'] === 'undefined') {
log.error('Please include a WSPORT value with the port that the WebSocket web process is hosted on in .env');
process.exit(6);
}
else {
wsPort = parseInt(process.env['WS_PORT']);
log.info(`WS_PORT=${port}`);
}
if (typeof process.env['SEQUENCES'] === 'undefined') {
log.error('Please include a SEQUENCES directory where the image sequences will be located in .env');
process.exit(7);
@ -133,20 +153,32 @@ async function settings() {
log.info(`VIDEOS=${videos}`);
}
}
function onWssConnection(ws, req) {
let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
if (ip.substr(0, 7) === "::ffff:")
ip = ip.substr(7);
log.info(`Client ${ip} connected to WebSocket server`);
ws.ip = ip;
ws.session = (0, uuid_1.v4)();
}
app.get('/', async (req, res, next) => {
const dirs = await files_1.Files.enumerateSequences(sequences);
const html = index({ dirs, width, height });
const sequencesArr = await files_1.Files.enumerateSequences(sequences);
const videosArr = await files_1.Files.enumerateVideos(videos);
const html = index({ sequences: sequencesArr, videos: videosArr, width, height });
res.send(html);
});
async function main() {
await settings();
index = await createTemplate('./views/index.hbs');
ffmpeg = new ffmpeg_1.FFMPEG();
ffmpeg = new ffmpeg_1.FFMPEG(process.env['FFMPEG']);
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
app.listen(port, async () => {
log.info(`filmout_manager HTTP server running on port ${port}`);
});
log.info(await ffmpeg.listFormats());
wss = new ws_1.Server({ port: wsPort, clientTracking: true });
wss.on('connection', onWssConnection);
log.info(`filmout_manager WebSocket server running on port ${wsPort}`);
ffmpeg.listFormats();
}
main();
//# sourceMappingURL=index.js.map

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,9 @@
"main": "dist/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"compile": "./node_modules/.bin/tsc -p tsconfig.json"
"compile": "npm run compile_node && npm run compile_browser",
"compile_node" : "./node_modules/.bin/tsc -p tsconfig.json",
"compile_browser" : "./node_modules/.bin/tsc -p tsconfig-browser.json"
},
"author": "",
"license": "MIT",

View File

@ -56,7 +56,7 @@ export class FFMPEG {
if (row.startsWith(' DE ')) {
key = row.substring(4, row.length - 1).split(' ')[0];
description = row.replace(key, '').trim();
this.log.info(key);
//this.log.info(key);
/*try {
this.log.info(await this.demuxerInfo(key));
} catch (err) {
@ -69,7 +69,7 @@ export class FFMPEG {
} else if (row.startsWith(' D ')) {
key = row.substring(4, row.length - 1).split(' ')[0];
description = row.replace(key, '').trim();
this.log.info(key);
//this.log.info(key);
/*try {
this.log.info(await this.demuxerInfo(key));
} catch (err) {

View File

@ -15,7 +15,7 @@ interface VideoObject {
name : string
}
const fileExtension : string[] = [
const fileExtensions : string[] = [
'.mp4',
'.mkv',
'.mov'
@ -64,6 +64,27 @@ export class Files {
let all : string[];
let stats : Stats;
try {
all = await fs.readdir(path)
} catch (err) {
throw err;
}
for (let elem of all) {
try {
stats = await fs.lstat(elem);
if (stats.isFile() && fileExtensions.indexOf(extname(basename(elem))) !== -1) {
videos.push({
path : elem,
hash : Hashes.stringHash(elem),
name : basename(elem)
});
}
} catch (err) {
//
}
}
return videos;
}
}

View File

@ -12,6 +12,7 @@ import getType from 'mime';
import type { Logger } from 'winston';
import * as Handlebars from 'handlebars';
import { Server } from 'ws';
import type { WebSocket } from 'ws';
import { createLog } from './log'
import { sendMail } from './mail';
@ -24,11 +25,13 @@ import { FFMPEG } from './ffmpeg';
const log : Logger = createLog('fm');
const app : Express = express();
let wss : Server;
let fd : FD;
let ffmpeg : FFMPEG;
let index : HandlebarsTemplateDelegate<any>;
let port : number;
let wsPort : number;
let sequences : string;
let videos : string;
let width : number;
@ -39,6 +42,13 @@ log.info('Starting filmout_manager...');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use('/static', express.static('./static'));
interface WebSocketExtended extends WebSocket {
ip? : string,
session? : string
}
async function createTemplate (filePath : string) : Promise<HandlebarsTemplateDelegate<any>> {
let tmpl : string;
try {
@ -59,6 +69,12 @@ async function settings () {
} else {
log.info(`FD=${process.env['FD']}`);
}
if (typeof process.env['FFMPEG'] === 'undefined') {
log.error('Please include an FFMPEG value containing the path to your ffmpeg binary in .env');
process.exit(1);
} else {
log.info(`FFMPEG=${process.env['FFMPEG']}`);
}
if (typeof process.env['WIDTH'] === 'undefined') {
log.error('Please include a WIDTH value containing the width of the screen you are using in .env');
process.exit(2);
@ -92,6 +108,13 @@ async function settings () {
port = parseInt(process.env['PORT']);
log.info(`PORT=${port}`);
}
if (typeof process.env['WS_PORT'] === 'undefined') {
log.error('Please include a WSPORT value with the port that the WebSocket web process is hosted on in .env');
process.exit(6);
} else {
wsPort = parseInt(process.env['WS_PORT']);
log.info(`WS_PORT=${port}`);
}
if (typeof process.env['SEQUENCES'] === 'undefined') {
log.error('Please include a SEQUENCES directory where the image sequences will be located in .env');
process.exit(7);
@ -118,21 +141,35 @@ async function settings () {
}
}
function onWssConnection (ws : WebSocketExtended, req : Request) {
let ip : string = req.headers['x-forwarded-for'] as string || req.connection.remoteAddress;
if (ip.substr(0, 7) === "::ffff:") ip = ip.substr(7)
log.info(`Client ${ip} connected to WebSocket server`);
ws.ip = ip;
ws.session = uuid();
}
app.get('/', async (req : Request, res : Response, next : NextFunction) => {
const dirs : SequenceObject[] = await Files.enumerateSequences(sequences);
const html : string = index({ dirs, width, height });
const sequencesArr : SequenceObject[] = await Files.enumerateSequences(sequences);
const videosArr : VideoObject[] = await Files.enumerateVideos(videos);
const html : string = index({ sequences : sequencesArr, videos : videosArr, width, height });
res.send(html);
});
async function main () {
await settings();
index = await createTemplate('./views/index.hbs');
ffmpeg = new FFMPEG();
ffmpeg = new FFMPEG(process.env['FFMPEG']);
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
app.listen(port, async () => {
log.info(`filmout_manager HTTP server running on port ${port}`);
});
log.info(await ffmpeg.listFormats());
wss = new Server({ port : wsPort, clientTracking : true });
wss.on('connection', onWssConnection);
log.info(`filmout_manager WebSocket server running on port ${wsPort}`);
ffmpeg.listFormats();
}

7
static/js/index.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
declare class Client {
private client;
private connected;
constructor();
private onMessage;
private onOpen;
}

18
static/js/index.js Normal file
View File

@ -0,0 +1,18 @@
class Client {
constructor() {
this.connected = false;
let uri = 'ws://localhost:8082';
this.client = new WebSocket(uri);
this.client.onopen = this.onOpen.bind(this);
this.client.onmessage = this.onMessage.bind(this);
}
onMessage(event) {
console.log(event.data);
}
onOpen(event) {
console.log('Connected');
this.connected = true;
}
}
new Client();
//# sourceMappingURL=index.js.map

1
static/js/index.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../browser/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM;IAGV;QADQ,cAAS,GAAa,KAAK,CAAC;QAElC,IAAI,GAAG,GAAY,qBAAqB,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;IAEO,SAAS,CAAE,KAAW;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAEO,MAAM,CAAE,KAAW;QACzB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;CACF;AAED,IAAI,MAAM,EAAE,CAAC"}

21
tsconfig-browser.json Normal file
View File

@ -0,0 +1,21 @@
{
"compilerOptions": {
"module": "amd",
"lib" : ["es2015", "dom", "es5", "es6"],
"esModuleInterop": true,
"target": "ES2020",
"noImplicitAny": true,
"moduleResolution": "node",
"sourceMap": true,
"removeComments" : true,
"baseUrl" : "static/js",
"outDir": "./static/js",
"rootDir" : "./browser/",
"declaration": true,
"paths" : {
}
},
"exclude" : [
"./dist", "./src", "./static"
]
}

View File

@ -15,6 +15,6 @@
}
},
"exclude" : [
"./dist"
"./dist", "./browser", "./static"
]
}

View File

@ -5,11 +5,18 @@
</head>
<body>
<div>Screen Resolution : {{width}}x{{height}}</div>
<select>
<select name="sequence" id="sequence">
<option> - Select Image Sequence - </option>
{{#each dirs}}
{{#each sequences}}
<option value="{{this.hash}}">{{this.name}}</option>
{{/each}}
</select>
<select name="video" id="video">
<option> - Select Video - </option>
{{#each videos}}
<option value="{{this.hash}}">{{this.name}}</option>
{{/each}}
</select>
<script src="/static/js/index.js"></script>
</body>
</html>