Compare commits
No commits in common. "9aaf9a215d2cca0e99850eac7090c3b80353d6e6" and "76322453328a32a32b1e81a9413bd4d26085a6a9" have entirely different histories.
9aaf9a215d
...
7632245332
|
@ -1,21 +0,0 @@
|
||||||
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();
|
|
|
@ -5,7 +5,6 @@ WS_PORT=8081
|
||||||
WIDTH=2560
|
WIDTH=2560
|
||||||
HEIGHT=1600
|
HEIGHT=1600
|
||||||
FD=../filmout_display/build/bin/fd
|
FD=../filmout_display/build/bin/fd
|
||||||
FFMPEG=ffmpeg
|
|
||||||
FD_HOST=localhost
|
FD_HOST=localhost
|
||||||
FD_PORT=8081
|
FD_PORT=8081
|
||||||
VIDEOS=/home/users/VIDEOS
|
VIDEOS=/home/users/VIDEOS
|
||||||
|
|
|
@ -12,17 +12,14 @@ declare enum Mode {
|
||||||
RGB_CHANNELS = 4,
|
RGB_CHANNELS = 4,
|
||||||
INVERT_CHANNELS = 5
|
INVERT_CHANNELS = 5
|
||||||
}
|
}
|
||||||
export interface fdOutgoingPosition {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
w: number;
|
|
||||||
h: number;
|
|
||||||
}
|
|
||||||
export interface fdOutgoingMessage {
|
export interface fdOutgoingMessage {
|
||||||
action: Action;
|
action: Action;
|
||||||
image: string;
|
image: string;
|
||||||
mode?: Mode;
|
mode?: Mode;
|
||||||
position?: fdOutgoingPosition;
|
x?: number;
|
||||||
|
y?: number;
|
||||||
|
w?: number;
|
||||||
|
h?: number;
|
||||||
exposure?: number[];
|
exposure?: number[];
|
||||||
}
|
}
|
||||||
export interface fdIncomingMessage {
|
export interface fdIncomingMessage {
|
||||||
|
@ -55,9 +52,8 @@ export declare class FD {
|
||||||
private send;
|
private send;
|
||||||
private receive;
|
private receive;
|
||||||
load(image: string, x: number, y: number, w: number, h: number): Promise<fdResult>;
|
load(image: string, x: number, y: number, w: number, h: number): Promise<fdResult>;
|
||||||
display(image: string, exposure?: number[]): Promise<fdResult>;
|
display(image: string, exposure: number[]): Promise<fdResult>;
|
||||||
stop(image: string): Promise<fdResult>;
|
stop(image: string): Promise<fdResult>;
|
||||||
isConnected(): boolean;
|
isConnected(): boolean;
|
||||||
private test;
|
|
||||||
}
|
}
|
||||||
export {};
|
export {};
|
||||||
|
|
|
@ -38,7 +38,6 @@ class FD {
|
||||||
this.shell = new shell_1.Shell([this.bin, `${this.width}`, `${this.height}`, `${this.port}`], this.logstd.bind(this), this.logsterr.bind(this), null, true);
|
this.shell = new shell_1.Shell([this.bin, `${this.width}`, `${this.height}`, `${this.port}`], this.logstd.bind(this), this.logsterr.bind(this), null, true);
|
||||||
this.startDisplay();
|
this.startDisplay();
|
||||||
this.startClient();
|
this.startClient();
|
||||||
this.test();
|
|
||||||
}
|
}
|
||||||
async startDisplay() {
|
async startDisplay() {
|
||||||
this.log.info(`Launching fd binary ${this.bin}`);
|
this.log.info(`Launching fd binary ${this.bin}`);
|
||||||
|
@ -60,28 +59,15 @@ class FD {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
this.client.on('close', () => {
|
this.client.on('close', () => {
|
||||||
this.log.info('Closing connection');
|
this.log.info('Closing connection');
|
||||||
this.socketConnected = false;
|
|
||||||
});
|
});
|
||||||
this.client.on('error', (err) => {
|
this.client.on('error', (err) => {
|
||||||
this.log.error('Error in socket client', err);
|
this.log.error('Error:', err);
|
||||||
this.socketConnected = false;
|
|
||||||
this.shell.kill();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
logstd(data) {
|
logstd(data) {
|
||||||
let parsed = null;
|
this.log.info(`[shell] ${data}`);
|
||||||
try {
|
if (data.indexOf('TCP server listening on port') !== -1 && data.indexOf(`${this.port}`) !== -1) {
|
||||||
parsed = JSON.parse(data);
|
this.socketAvailable = true;
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.log.error(`Error parsing line ${data}`, err);
|
|
||||||
}
|
|
||||||
if (parsed !== null) {
|
|
||||||
this.log.info(`[shell] ${data}`);
|
|
||||||
if (typeof parsed['listening'] !== 'undefined' && parsed['listening'] === true
|
|
||||||
&& typeof parsed['port'] !== 'undefined' && parsed['port'] === this.port) {
|
|
||||||
this.socketAvailable = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logsterr(data) {
|
logsterr(data) {
|
||||||
|
@ -104,12 +90,10 @@ class FD {
|
||||||
const msg = {
|
const msg = {
|
||||||
action: Action.LOAD,
|
action: Action.LOAD,
|
||||||
image,
|
image,
|
||||||
position: {
|
x,
|
||||||
x,
|
y,
|
||||||
y,
|
w,
|
||||||
w,
|
h
|
||||||
h
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const startTime = +new Date();
|
const startTime = +new Date();
|
||||||
const promise = new Promise(function (resolve, reject) {
|
const promise = new Promise(function (resolve, reject) {
|
||||||
|
@ -128,9 +112,9 @@ class FD {
|
||||||
};
|
};
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
this.send(msg);
|
this.send(msg);
|
||||||
return await promise;
|
return promise;
|
||||||
}
|
}
|
||||||
async display(image, exposure = []) {
|
async display(image, exposure) {
|
||||||
const msg = {
|
const msg = {
|
||||||
action: Action.DISPLAY,
|
action: Action.DISPLAY,
|
||||||
image,
|
image,
|
||||||
|
@ -153,7 +137,7 @@ class FD {
|
||||||
};
|
};
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
this.send(msg);
|
this.send(msg);
|
||||||
return await promise;
|
return promise;
|
||||||
}
|
}
|
||||||
async stop(image) {
|
async stop(image) {
|
||||||
const msg = {
|
const msg = {
|
||||||
|
@ -177,25 +161,11 @@ class FD {
|
||||||
};
|
};
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
this.send(msg);
|
this.send(msg);
|
||||||
return await promise;
|
return promise;
|
||||||
}
|
}
|
||||||
isConnected() {
|
isConnected() {
|
||||||
return this.socketConnected;
|
return this.socketConnected;
|
||||||
}
|
}
|
||||||
async test() {
|
|
||||||
const img = '/Users/matthewmcwilliams9/src/filmout_display/img/4kSnake.png';
|
|
||||||
await (0, delay_1.delay)(2000);
|
|
||||||
await this.load(img, 100, 200, 640, 640);
|
|
||||||
await (0, delay_1.delay)(2000);
|
|
||||||
await this.display(img, [4000]);
|
|
||||||
await (0, delay_1.delay)(8000);
|
|
||||||
await this.load(img, 100, 200, 640, 640);
|
|
||||||
await (0, delay_1.delay)(1000);
|
|
||||||
await this.display(img);
|
|
||||||
await (0, delay_1.delay)(2000);
|
|
||||||
await this.stop(img);
|
|
||||||
process.exit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
exports.FD = FD;
|
exports.FD = FD;
|
||||||
//# sourceMappingURL=index.js.map
|
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -1,11 +0,0 @@
|
||||||
export declare class FFMPEG {
|
|
||||||
private bin;
|
|
||||||
private log;
|
|
||||||
private shell;
|
|
||||||
private formats;
|
|
||||||
private formatsInfo;
|
|
||||||
constructor(bin?: string);
|
|
||||||
private rawList;
|
|
||||||
private demuxerInfo;
|
|
||||||
listFormats(): Promise<string[]>;
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.FFMPEG = void 0;
|
|
||||||
const log_1 = require("../log");
|
|
||||||
const shell_1 = require("../shell");
|
|
||||||
const os_1 = require("os");
|
|
||||||
class FFMPEG {
|
|
||||||
constructor(bin = 'ffmpeg') {
|
|
||||||
this.formats = [];
|
|
||||||
this.formatsInfo = {};
|
|
||||||
this.bin = bin;
|
|
||||||
this.log = (0, log_1.createLog)('ffmpeg');
|
|
||||||
}
|
|
||||||
async rawList() {
|
|
||||||
const cmd = [this.bin, '-formats'];
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
this.shell = new shell_1.Shell(cmd, null, null, resolve, true);
|
|
||||||
await this.shell.execute();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async demuxerInfo(demuxer) {
|
|
||||||
const cmd = [this.bin, `ffmpeg -h demuxer=${demuxer}`];
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
this.shell = new shell_1.Shell(cmd, null, null, resolve, true);
|
|
||||||
await this.shell.execute();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async listFormats() {
|
|
||||||
let list = null;
|
|
||||||
let rows;
|
|
||||||
let key;
|
|
||||||
let description;
|
|
||||||
let info;
|
|
||||||
this.formats = [];
|
|
||||||
this.formatsInfo = {};
|
|
||||||
try {
|
|
||||||
list = await this.rawList();
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.log.error('Error listing formats', err);
|
|
||||||
}
|
|
||||||
if (list !== null) {
|
|
||||||
rows = list.split(os_1.EOL);
|
|
||||||
for (let row of rows) {
|
|
||||||
//this.log.info(`"${row}"`);
|
|
||||||
if (row.startsWith(' DE ')) {
|
|
||||||
key = row.substring(4, row.length - 1).split(' ')[0];
|
|
||||||
description = row.replace(key, '').trim();
|
|
||||||
//this.log.info(key);
|
|
||||||
/*try {
|
|
||||||
this.log.info(await this.demuxerInfo(key));
|
|
||||||
} catch (err) {
|
|
||||||
this.log.error(err);
|
|
||||||
}*/
|
|
||||||
this.formats.push(key);
|
|
||||||
this.formatsInfo[key] = {
|
|
||||||
description
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (row.startsWith(' D ')) {
|
|
||||||
key = row.substring(4, row.length - 1).split(' ')[0];
|
|
||||||
description = row.replace(key, '').trim();
|
|
||||||
//this.log.info(key);
|
|
||||||
/*try {
|
|
||||||
this.log.info(await this.demuxerInfo(key));
|
|
||||||
} catch (err) {
|
|
||||||
this.log.error(err);
|
|
||||||
}*/
|
|
||||||
this.formats.push(key);
|
|
||||||
this.formatsInfo[key] = {
|
|
||||||
description
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.formats;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.FFMPEG = FFMPEG;
|
|
||||||
module.exports = { FFMPEG };
|
|
||||||
//# sourceMappingURL=index.js.map
|
|
|
@ -1 +0,0 @@
|
||||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ffmpeg/index.ts"],"names":[],"mappings":";;;AACA,gCAAkC;AAClC,oCAAiC;AAEjC,2BAAyB;AAEzB,MAAa,MAAM;IAOlB,YAAa,MAAc,QAAQ;QAH3B,YAAO,GAAc,EAAE,CAAC;QACxB,gBAAW,GAAS,EAAE,CAAC;QAG9B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,GAAG,GAAG,IAAA,eAAS,EAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAEO,KAAK,CAAC,OAAO;QACpB,MAAM,GAAG,GAAc,CAAE,IAAI,CAAC,GAAG,EAAE,UAAU,CAAE,CAAC;QAChD,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,OAAkB,EAAE,MAAiB,EAAE,EAAE;YAClE,IAAI,CAAC,KAAK,GAAG,IAAI,aAAK,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YACvD,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,WAAW,CAAE,OAAgB;QAC1C,MAAM,GAAG,GAAc,CAAE,IAAI,CAAC,GAAG,EAAE,qBAAqB,OAAO,EAAE,CAAE,CAAC;QACpE,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,OAAkB,EAAE,MAAiB,EAAE,EAAE;YAClE,IAAI,CAAC,KAAK,GAAG,IAAI,aAAK,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YACvD,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW;QAEhB,IAAI,IAAI,GAAY,IAAI,CAAC;QACzB,IAAI,IAAe,CAAC;QACpB,IAAI,GAAY,CAAC;QACjB,IAAI,WAAoB,CAAC;QACzB,IAAI,IAAa,CAAC;QAElB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QAEtB,IAAI,CAAC;YACJ,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACnB,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAG,CAAC,CAAC;YACvB,KAAK,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;gBACtB,4BAA4B;gBAC5B,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC5B,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBACrD,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC1C,qBAAqB;oBACrB;;;;uBAIG;oBACH,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACvB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG;wBACvB,WAAW;qBACX,CAAC;gBACH,CAAC;qBAAM,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBACnC,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBACrD,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC1C,qBAAqB;oBACrB;;;;uBAIG;oBACH,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACvB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG;wBACvB,WAAW;qBACX,CAAC;gBACH,CAAC;YACF,CAAC;QACF,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;CACD;AAjFD,wBAiFC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,MAAM,EAAE,CAAC"}
|
|
|
@ -3,14 +3,8 @@ interface SequenceObject {
|
||||||
hash: string;
|
hash: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
interface VideoObject {
|
|
||||||
path: string;
|
|
||||||
hash: string;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
export declare class Files {
|
export declare class Files {
|
||||||
static exists(path: string): Promise<boolean>;
|
static exists(path: string): Promise<boolean>;
|
||||||
static enumerateSequences(path: string): Promise<SequenceObject[]>;
|
static enumerateSequences(path: string): Promise<SequenceObject[]>;
|
||||||
static enumerateVideos(path: string): Promise<VideoObject[]>;
|
|
||||||
}
|
}
|
||||||
export type { SequenceObject, VideoObject };
|
export type { SequenceObject };
|
||||||
|
|
|
@ -7,11 +7,6 @@ exports.Files = void 0;
|
||||||
const promises_1 = __importDefault(require("fs/promises"));
|
const promises_1 = __importDefault(require("fs/promises"));
|
||||||
const hash_1 = require("../hash");
|
const hash_1 = require("../hash");
|
||||||
const path_1 = require("path");
|
const path_1 = require("path");
|
||||||
const fileExtensions = [
|
|
||||||
'.mp4',
|
|
||||||
'.mkv',
|
|
||||||
'.mov'
|
|
||||||
];
|
|
||||||
class Files {
|
class Files {
|
||||||
static async exists(path) {
|
static async exists(path) {
|
||||||
try {
|
try {
|
||||||
|
@ -49,33 +44,6 @@ class Files {
|
||||||
}
|
}
|
||||||
return dirs;
|
return dirs;
|
||||||
}
|
}
|
||||||
static async enumerateVideos(path) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
exports.Files = Files;
|
exports.Files = Files;
|
||||||
module.exports = { Files };
|
module.exports = { Files };
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"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"}
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/files/index.ts"],"names":[],"mappings":";;;;;;AAAA,2DAA6B;AAE7B,kCAAiC;AACjC,+BAAgC;AAQhC,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;CACD;AArCD,sBAqCC;AAGD,MAAM,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC"}
|
|
@ -30,20 +30,14 @@ require("dotenv/config");
|
||||||
const express_1 = __importDefault(require("express"));
|
const express_1 = __importDefault(require("express"));
|
||||||
const promises_1 = __importDefault(require("fs/promises"));
|
const promises_1 = __importDefault(require("fs/promises"));
|
||||||
const body_parser_1 = __importDefault(require("body-parser"));
|
const body_parser_1 = __importDefault(require("body-parser"));
|
||||||
const uuid_1 = require("uuid");
|
|
||||||
const Handlebars = __importStar(require("handlebars"));
|
const Handlebars = __importStar(require("handlebars"));
|
||||||
const ws_1 = require("ws");
|
|
||||||
const log_1 = require("./log");
|
const log_1 = require("./log");
|
||||||
const files_1 = require("./files");
|
const files_1 = require("./files");
|
||||||
const ffmpeg_1 = require("./ffmpeg");
|
|
||||||
const log = (0, log_1.createLog)('fm');
|
const log = (0, log_1.createLog)('fm');
|
||||||
const app = (0, express_1.default)();
|
const app = (0, express_1.default)();
|
||||||
let wss;
|
|
||||||
let fd;
|
let fd;
|
||||||
let ffmpeg;
|
|
||||||
let index;
|
let index;
|
||||||
let port;
|
let port;
|
||||||
let wsPort;
|
|
||||||
let sequences;
|
let sequences;
|
||||||
let videos;
|
let videos;
|
||||||
let width;
|
let width;
|
||||||
|
@ -51,7 +45,6 @@ let height;
|
||||||
log.info('Starting filmout_manager...');
|
log.info('Starting filmout_manager...');
|
||||||
app.use(body_parser_1.default.json());
|
app.use(body_parser_1.default.json());
|
||||||
app.use(body_parser_1.default.urlencoded({ extended: true }));
|
app.use(body_parser_1.default.urlencoded({ extended: true }));
|
||||||
app.use('/static', express_1.default.static('./static'));
|
|
||||||
async function createTemplate(filePath) {
|
async function createTemplate(filePath) {
|
||||||
let tmpl;
|
let tmpl;
|
||||||
try {
|
try {
|
||||||
|
@ -73,13 +66,6 @@ async function settings() {
|
||||||
else {
|
else {
|
||||||
log.info(`FD=${process.env['FD']}`);
|
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') {
|
if (typeof process.env['WIDTH'] === 'undefined') {
|
||||||
log.error('Please include a WIDTH value containing the width of the screen you are using in .env');
|
log.error('Please include a WIDTH value containing the width of the screen you are using in .env');
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
|
@ -118,14 +104,6 @@ async function settings() {
|
||||||
port = parseInt(process.env['PORT']);
|
port = parseInt(process.env['PORT']);
|
||||||
log.info(`PORT=${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') {
|
if (typeof process.env['SEQUENCES'] === 'undefined') {
|
||||||
log.error('Please include a SEQUENCES directory where the image sequences will be located in .env');
|
log.error('Please include a SEQUENCES directory where the image sequences will be located in .env');
|
||||||
process.exit(7);
|
process.exit(7);
|
||||||
|
@ -153,32 +131,18 @@ async function settings() {
|
||||||
log.info(`VIDEOS=${videos}`);
|
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) => {
|
app.get('/', async (req, res, next) => {
|
||||||
const sequencesArr = await files_1.Files.enumerateSequences(sequences);
|
const dirs = await files_1.Files.enumerateSequences(sequences);
|
||||||
const videosArr = await files_1.Files.enumerateVideos(videos);
|
const html = index({ dirs, width, height });
|
||||||
const html = index({ sequences: sequencesArr, videos: videosArr, width, height });
|
|
||||||
res.send(html);
|
res.send(html);
|
||||||
});
|
});
|
||||||
async function main() {
|
async function main() {
|
||||||
await settings();
|
await settings();
|
||||||
index = await createTemplate('./views/index.hbs');
|
index = await createTemplate('./views/index.hbs');
|
||||||
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']));
|
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
|
||||||
app.listen(port, async () => {
|
app.listen(port, async () => {
|
||||||
log.info(`filmout_manager HTTP server running on port ${port}`);
|
log.info(`filmout_manager HTTP server running on port ${port}`);
|
||||||
});
|
});
|
||||||
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();
|
main();
|
||||||
//# sourceMappingURL=index.js.map
|
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -5,9 +5,7 @@
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"compile": "npm run compile_node && npm run compile_browser",
|
"compile": "./node_modules/.bin/tsc -p tsconfig.json"
|
||||||
"compile_node" : "./node_modules/.bin/tsc -p tsconfig.json",
|
|
||||||
"compile_browser" : "./node_modules/.bin/tsc -p tsconfig-browser.json"
|
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
@ -21,18 +21,14 @@ enum Mode {
|
||||||
INVERT_CHANNELS
|
INVERT_CHANNELS
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface fdOutgoingPosition {
|
|
||||||
x : number,
|
|
||||||
y : number,
|
|
||||||
w : number,
|
|
||||||
h : number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface fdOutgoingMessage {
|
export interface fdOutgoingMessage {
|
||||||
action : Action,
|
action : Action,
|
||||||
image : string,
|
image : string,
|
||||||
mode? : Mode,
|
mode? : Mode,
|
||||||
position? : fdOutgoingPosition,
|
x? : number,
|
||||||
|
y? : number,
|
||||||
|
w? : number,
|
||||||
|
h? : number,
|
||||||
exposure? : number[]
|
exposure? : number[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +68,6 @@ export class FD {
|
||||||
this.shell = new Shell([ this.bin, `${this.width}`, `${this.height}`, `${this.port}` ], this.logstd.bind(this), this.logsterr.bind(this), null, true);
|
this.shell = new Shell([ this.bin, `${this.width}`, `${this.height}`, `${this.port}` ], this.logstd.bind(this), this.logsterr.bind(this), null, true);
|
||||||
this.startDisplay();
|
this.startDisplay();
|
||||||
this.startClient();
|
this.startClient();
|
||||||
this.test();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async startDisplay () {
|
private async startDisplay () {
|
||||||
|
@ -98,29 +93,17 @@ export class FD {
|
||||||
|
|
||||||
this.client.on('close', () => {
|
this.client.on('close', () => {
|
||||||
this.log.info('Closing connection');
|
this.log.info('Closing connection');
|
||||||
this.socketConnected = false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.client.on('error', (err : Error) => {
|
this.client.on('error', (err : Error) => {
|
||||||
this.log.error('Error in socket client', err);
|
this.log.error('Error:', err);
|
||||||
this.socketConnected = false;
|
|
||||||
this.shell.kill();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private logstd (data : string ) {
|
private logstd (data : string ) {
|
||||||
let parsed : any = null;
|
this.log.info(`[shell] ${data}`);
|
||||||
try {
|
if (data.indexOf('TCP server listening on port') !== -1 && data.indexOf(`${this.port}`) !== -1) {
|
||||||
parsed = JSON.parse(data);
|
this.socketAvailable = true;
|
||||||
} catch (err) {
|
|
||||||
this.log.error(`Error parsing line ${data}`, err);
|
|
||||||
}
|
|
||||||
if (parsed !== null) {
|
|
||||||
this.log.info(`[shell] ${data}`);
|
|
||||||
if (typeof parsed['listening'] !== 'undefined' && parsed['listening'] === true
|
|
||||||
&& typeof parsed['port'] !== 'undefined' && parsed['port'] === this.port) {
|
|
||||||
this.socketAvailable = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,12 +130,10 @@ export class FD {
|
||||||
const msg : fdOutgoingMessage = {
|
const msg : fdOutgoingMessage = {
|
||||||
action : Action.LOAD,
|
action : Action.LOAD,
|
||||||
image,
|
image,
|
||||||
position : {
|
x,
|
||||||
x,
|
y,
|
||||||
y,
|
w,
|
||||||
w,
|
h
|
||||||
h
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const startTime : number = +new Date();
|
const startTime : number = +new Date();
|
||||||
const promise : Promise<fdResult> = new Promise(function (resolve : Function, reject : Function) {
|
const promise : Promise<fdResult> = new Promise(function (resolve : Function, reject : Function) {
|
||||||
|
@ -170,10 +151,10 @@ export class FD {
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
this.send(msg);
|
this.send(msg);
|
||||||
return await promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async display (image : string, exposure : number[] = []) : Promise<fdResult> {
|
public async display (image : string, exposure : number[]) : Promise<fdResult> {
|
||||||
const msg : fdOutgoingMessage = {
|
const msg : fdOutgoingMessage = {
|
||||||
action : Action.DISPLAY,
|
action : Action.DISPLAY,
|
||||||
image,
|
image,
|
||||||
|
@ -195,7 +176,7 @@ export class FD {
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
this.send(msg);
|
this.send(msg);
|
||||||
return await promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async stop (image : string) : Promise<fdResult> {
|
public async stop (image : string) : Promise<fdResult> {
|
||||||
|
@ -219,32 +200,11 @@ export class FD {
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
this.send(msg);
|
this.send(msg);
|
||||||
return await promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isConnected () : boolean {
|
public isConnected () : boolean {
|
||||||
return this.socketConnected;
|
return this.socketConnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async test () {
|
|
||||||
const img = '/Users/matthewmcwilliams9/src/filmout_display/img/4kSnake.png';
|
|
||||||
|
|
||||||
await delay(2000);
|
|
||||||
|
|
||||||
await this.load(img, 100, 200, 640, 640);
|
|
||||||
await delay(2000);
|
|
||||||
|
|
||||||
await this.display(img, [ 4000 ] );
|
|
||||||
await delay(8000);
|
|
||||||
|
|
||||||
await this.load(img, 100, 200, 640, 640);
|
|
||||||
await delay(1000);
|
|
||||||
|
|
||||||
await this.display (img);
|
|
||||||
await delay(2000);
|
|
||||||
await this.stop(img);
|
|
||||||
|
|
||||||
process.exit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
import type { Logger } from 'winston';
|
|
||||||
import { createLog } from '../log'
|
|
||||||
import { Shell } from '../shell';
|
|
||||||
import { delay } from '../delay';
|
|
||||||
import { EOL } from 'os';
|
|
||||||
|
|
||||||
export class FFMPEG {
|
|
||||||
private bin : string;
|
|
||||||
private log : Logger;
|
|
||||||
private shell : Shell;
|
|
||||||
private formats : string[] = [];
|
|
||||||
private formatsInfo : any = {};
|
|
||||||
|
|
||||||
constructor (bin: string = 'ffmpeg') {
|
|
||||||
this.bin = bin;
|
|
||||||
this.log = createLog('ffmpeg');
|
|
||||||
}
|
|
||||||
|
|
||||||
private async rawList () : Promise<string> {
|
|
||||||
const cmd : string[] = [ this.bin, '-formats' ];
|
|
||||||
return new Promise(async (resolve : Function, reject : Function) => {
|
|
||||||
this.shell = new Shell(cmd, null, null, resolve, true);
|
|
||||||
await this.shell.execute();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async demuxerInfo (demuxer : string) : Promise<string> {
|
|
||||||
const cmd : string[] = [ this.bin, `ffmpeg -h demuxer=${demuxer}` ];
|
|
||||||
return new Promise(async (resolve : Function, reject : Function) => {
|
|
||||||
this.shell = new Shell(cmd, null, null, resolve, true);
|
|
||||||
await this.shell.execute();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async listFormats () : Promise<string[]> {
|
|
||||||
|
|
||||||
let list : string = null;
|
|
||||||
let rows : string[];
|
|
||||||
let key : string;
|
|
||||||
let description : string;
|
|
||||||
let info : string;
|
|
||||||
|
|
||||||
this.formats = [];
|
|
||||||
this.formatsInfo = {};
|
|
||||||
|
|
||||||
try {
|
|
||||||
list = await this.rawList();
|
|
||||||
} catch (err) {
|
|
||||||
this.log.error('Error listing formats', err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list !== null) {
|
|
||||||
rows = list.split(EOL);
|
|
||||||
for (let row of rows) {
|
|
||||||
//this.log.info(`"${row}"`);
|
|
||||||
if (row.startsWith(' DE ')) {
|
|
||||||
key = row.substring(4, row.length - 1).split(' ')[0];
|
|
||||||
description = row.replace(key, '').trim();
|
|
||||||
//this.log.info(key);
|
|
||||||
/*try {
|
|
||||||
this.log.info(await this.demuxerInfo(key));
|
|
||||||
} catch (err) {
|
|
||||||
this.log.error(err);
|
|
||||||
}*/
|
|
||||||
this.formats.push(key);
|
|
||||||
this.formatsInfo[key] = {
|
|
||||||
description
|
|
||||||
};
|
|
||||||
} else if (row.startsWith(' D ')) {
|
|
||||||
key = row.substring(4, row.length - 1).split(' ')[0];
|
|
||||||
description = row.replace(key, '').trim();
|
|
||||||
//this.log.info(key);
|
|
||||||
/*try {
|
|
||||||
this.log.info(await this.demuxerInfo(key));
|
|
||||||
} catch (err) {
|
|
||||||
this.log.error(err);
|
|
||||||
}*/
|
|
||||||
this.formats.push(key);
|
|
||||||
this.formatsInfo[key] = {
|
|
||||||
description
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.formats;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { FFMPEG };
|
|
|
@ -1,7 +1,7 @@
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import type { Stats } from 'fs';
|
import type { Stats } from 'fs';
|
||||||
import { Hashes } from '../hash';
|
import { Hashes } from '../hash';
|
||||||
import { basename, extname } from 'path';
|
import { basename } from 'path';
|
||||||
|
|
||||||
interface SequenceObject {
|
interface SequenceObject {
|
||||||
path : string,
|
path : string,
|
||||||
|
@ -9,18 +9,6 @@ interface SequenceObject {
|
||||||
name : string
|
name : string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VideoObject {
|
|
||||||
path : string,
|
|
||||||
hash : string,
|
|
||||||
name : string
|
|
||||||
}
|
|
||||||
|
|
||||||
const fileExtensions : string[] = [
|
|
||||||
'.mp4',
|
|
||||||
'.mkv',
|
|
||||||
'.mov'
|
|
||||||
];
|
|
||||||
|
|
||||||
export class Files {
|
export class Files {
|
||||||
public static async exists (path : string) : Promise<boolean> {
|
public static async exists (path : string) : Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
|
@ -58,36 +46,7 @@ export class Files {
|
||||||
|
|
||||||
return dirs;
|
return dirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async enumerateVideos (path : string) : Promise<VideoObject[]> {
|
|
||||||
const videos : VideoObject[] = [];
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { SequenceObject, VideoObject };
|
export type { SequenceObject };
|
||||||
module.exports = { Files };
|
module.exports = { Files };
|
||||||
|
|
47
src/index.ts
47
src/index.ts
|
@ -12,26 +12,21 @@ import getType from 'mime';
|
||||||
import type { Logger } from 'winston';
|
import type { Logger } from 'winston';
|
||||||
import * as Handlebars from 'handlebars';
|
import * as Handlebars from 'handlebars';
|
||||||
import { Server } from 'ws';
|
import { Server } from 'ws';
|
||||||
import type { WebSocket } from 'ws';
|
|
||||||
|
|
||||||
import { createLog } from './log'
|
import { createLog } from './log'
|
||||||
import { sendMail } from './mail';
|
import { sendMail } from './mail';
|
||||||
import { Files } from './files';
|
import { Files } from './files';
|
||||||
import type { SequenceObject, VideoObject } from './files';
|
import type { SequenceObject } from './files';
|
||||||
import { Shell } from './shell';
|
import { Shell } from './shell';
|
||||||
import { delay } from './delay';
|
import { delay } from './delay';
|
||||||
import { FD } from './fd';
|
import { FD } from './fd';
|
||||||
import { FFMPEG } from './ffmpeg';
|
|
||||||
|
|
||||||
const log : Logger = createLog('fm');
|
const log : Logger = createLog('fm');
|
||||||
const app : Express = express();
|
const app : Express = express();
|
||||||
let wss : Server;
|
|
||||||
let fd : FD;
|
let fd : FD;
|
||||||
let ffmpeg : FFMPEG;
|
|
||||||
let index : HandlebarsTemplateDelegate<any>;
|
let index : HandlebarsTemplateDelegate<any>;
|
||||||
|
|
||||||
let port : number;
|
let port : number;
|
||||||
let wsPort : number;
|
|
||||||
let sequences : string;
|
let sequences : string;
|
||||||
let videos : string;
|
let videos : string;
|
||||||
let width : number;
|
let width : number;
|
||||||
|
@ -42,13 +37,6 @@ log.info('Starting filmout_manager...');
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
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>> {
|
async function createTemplate (filePath : string) : Promise<HandlebarsTemplateDelegate<any>> {
|
||||||
let tmpl : string;
|
let tmpl : string;
|
||||||
try {
|
try {
|
||||||
|
@ -69,12 +57,6 @@ async function settings () {
|
||||||
} else {
|
} else {
|
||||||
log.info(`FD=${process.env['FD']}`);
|
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') {
|
if (typeof process.env['WIDTH'] === 'undefined') {
|
||||||
log.error('Please include a WIDTH value containing the width of the screen you are using in .env');
|
log.error('Please include a WIDTH value containing the width of the screen you are using in .env');
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
|
@ -108,13 +90,6 @@ async function settings () {
|
||||||
port = parseInt(process.env['PORT']);
|
port = parseInt(process.env['PORT']);
|
||||||
log.info(`PORT=${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') {
|
if (typeof process.env['SEQUENCES'] === 'undefined') {
|
||||||
log.error('Please include a SEQUENCES directory where the image sequences will be located in .env');
|
log.error('Please include a SEQUENCES directory where the image sequences will be located in .env');
|
||||||
process.exit(7);
|
process.exit(7);
|
||||||
|
@ -141,35 +116,19 @@ 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) => {
|
app.get('/', async (req : Request, res : Response, next : NextFunction) => {
|
||||||
const sequencesArr : SequenceObject[] = await Files.enumerateSequences(sequences);
|
const dirs : SequenceObject[] = await Files.enumerateSequences(sequences);
|
||||||
const videosArr : VideoObject[] = await Files.enumerateVideos(videos);
|
const html : string = index({ dirs, width, height });
|
||||||
const html : string = index({ sequences : sequencesArr, videos : videosArr, width, height });
|
|
||||||
res.send(html);
|
res.send(html);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function main () {
|
async function main () {
|
||||||
await settings();
|
await settings();
|
||||||
index = await createTemplate('./views/index.hbs');
|
index = await createTemplate('./views/index.hbs');
|
||||||
ffmpeg = new FFMPEG(process.env['FFMPEG']);
|
|
||||||
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
|
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
|
||||||
app.listen(port, async () => {
|
app.listen(port, async () => {
|
||||||
log.info(`filmout_manager HTTP server running on port ${port}`);
|
log.info(`filmout_manager HTTP server running on port ${port}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
wss = new Server({ port : wsPort, clientTracking : true });
|
|
||||||
wss.on('connection', onWssConnection);
|
|
||||||
log.info(`filmout_manager WebSocket server running on port ${wsPort}`);
|
|
||||||
|
|
||||||
ffmpeg.listFormats();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
declare class Client {
|
|
||||||
private client;
|
|
||||||
private connected;
|
|
||||||
constructor();
|
|
||||||
private onMessage;
|
|
||||||
private onOpen;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
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 +0,0 @@
|
||||||
{"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"}
|
|
|
@ -1,21 +0,0 @@
|
||||||
{
|
|
||||||
"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"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -15,6 +15,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exclude" : [
|
"exclude" : [
|
||||||
"./dist", "./browser", "./static"
|
"./dist"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -5,18 +5,11 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div>Screen Resolution : {{width}}x{{height}}</div>
|
<div>Screen Resolution : {{width}}x{{height}}</div>
|
||||||
<select name="sequence" id="sequence">
|
<select>
|
||||||
<option> - Select Image Sequence - </option>
|
<option> - Select Image Sequence - </option>
|
||||||
{{#each sequences}}
|
{{#each dirs}}
|
||||||
<option value="{{this.hash}}">{{this.name}}</option>
|
<option value="{{this.hash}}">{{this.name}}</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</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>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue