Added ffprobe functionality. On UI side, enable and disable buttons via class to prevent user error
This commit is contained in:
parent
53bf156d10
commit
d3f0a27f30
|
@ -39,31 +39,47 @@ class Client {
|
|||
case 'close' :
|
||||
this.receiveCameraClose();
|
||||
break;
|
||||
|
||||
case 'select' :
|
||||
this.receiveSelect(msg);
|
||||
break;
|
||||
default:
|
||||
console.warn(`No command ${msg.cmd}`);
|
||||
console.warn(`No command "${msg.cmd}"`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public disableClass (className : string) {
|
||||
document.querySelectorAll(`.${className}`).forEach((el : HTMLButtonElement) => {
|
||||
el.disabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
public enableClass (className : string) {
|
||||
document.querySelectorAll(`.${className}`).forEach((el : HTMLButtonElement) => {
|
||||
el.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
public sendCameraOpen () {
|
||||
console.log('send camera open');
|
||||
this.disableClass('manualCtrl');
|
||||
this.client.send(JSON.stringify({ cmd : 'open' }));
|
||||
}
|
||||
|
||||
private receiveCameraOpen () {
|
||||
console.log('got camera open');
|
||||
this.enableClass('manualCtrl');
|
||||
}
|
||||
|
||||
public sendCameraClose () {
|
||||
console.log('send camera close');
|
||||
this.disableClass('manualCtrl');
|
||||
this.client.send(JSON.stringify({ cmd : 'close' }));
|
||||
}
|
||||
|
||||
private receiveCameraClose () {
|
||||
console.log('got camera close');
|
||||
this.enableClass('manualCtrl');
|
||||
}
|
||||
|
||||
public sendSelect () {
|
||||
|
@ -79,7 +95,8 @@ class Client {
|
|||
}
|
||||
|
||||
private receiveSelect (msg : Message) {
|
||||
|
||||
console.log('got select');
|
||||
console.dir(msg)
|
||||
}
|
||||
|
||||
public fullscreen () {
|
||||
|
|
|
@ -5,6 +5,8 @@ export declare class Display {
|
|||
private display;
|
||||
private offset;
|
||||
constructor(width: number, height: number);
|
||||
setOffsetX(x: number): void;
|
||||
setOffsetY(y: number): void;
|
||||
setSource(width: number, height: number): void;
|
||||
getDimensions(): fdOutgoingPosition;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,12 @@ class Display {
|
|||
this.screen = new Dimensions(width, height);
|
||||
this.offset = { x: 0, y: 0 };
|
||||
}
|
||||
setOffsetX(x) {
|
||||
this.offset.x = x;
|
||||
}
|
||||
setOffsetY(y) {
|
||||
this.offset.y = y;
|
||||
}
|
||||
setSource(width, height) {
|
||||
this.source = new Dimensions(width, height);
|
||||
if (this.source.getRatio() > this.screen.getRatio()) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/display/index.ts"],"names":[],"mappings":";;;AAEA,MAAM,UAAU;IAIf,YAAa,KAAc,EAAE,MAAe;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAEM,QAAQ;QACd,OAAO,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,CAAC;CACD;AAOD,MAAa,OAAO;IAQnB,YAAa,KAAc,EAAE,MAAe;QAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAA;IAC9B,CAAC;IAEM,SAAS,CAAE,KAAc,EAAE,MAAe;QAChD,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrD,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChG,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAA;IAC5D,CAAC;IAEM,aAAa;QACnB,OAAO;YACN,CAAC,EAAG,IAAI,CAAC,OAAO,CAAC,KAAK;YACtB,CAAC,EAAG,IAAI,CAAC,OAAO,CAAC,MAAM;YACvB,CAAC,EAAG,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,CAAC,EAAG,IAAI,CAAC,MAAM,CAAC,CAAC;SACjB,CAAA;IACF,CAAC;CACD;AA/BD,0BA+BC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,OAAO,EAAE,CAAC"}
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/display/index.ts"],"names":[],"mappings":";;;AAEA,MAAM,UAAU;IAIf,YAAa,KAAc,EAAE,MAAe;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAEM,QAAQ;QACd,OAAO,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,CAAC;CACD;AAOD,MAAa,OAAO;IAQnB,YAAa,KAAc,EAAE,MAAe;QAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAA;IAC9B,CAAC;IAEM,UAAU,CAAE,CAAU;QAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAEM,UAAU,CAAE,CAAU;QAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAEM,SAAS,CAAE,KAAc,EAAE,MAAe;QAChD,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrD,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChG,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAA;IAC5D,CAAC;IAEM,aAAa;QACnB,OAAO;YACN,CAAC,EAAG,IAAI,CAAC,OAAO,CAAC,KAAK;YACtB,CAAC,EAAG,IAAI,CAAC,OAAO,CAAC,MAAM;YACvB,CAAC,EAAG,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,CAAC,EAAG,IAAI,CAAC,MAAM,CAAC,CAAC;SACjB,CAAA;IACF,CAAC;CACD;AAvCD,0BAuCC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,OAAO,EAAE,CAAC"}
|
|
@ -0,0 +1,33 @@
|
|||
/** @module lib/ffprobe */
|
||||
/**
|
||||
* Class representing all ffprobe features.
|
||||
*/
|
||||
export declare class FFPROBE {
|
||||
private bin;
|
||||
private log;
|
||||
constructor(bin?: string);
|
||||
exists(path: string): Promise<boolean>;
|
||||
/**
|
||||
* Parse the fps entry into a float representing the fps of a video
|
||||
**/
|
||||
private parseFps;
|
||||
/**
|
||||
* Get info on a video in json format. Use for filmout.
|
||||
*
|
||||
* @param {string} video Path to video
|
||||
*
|
||||
* @returns {object} Video info in an object
|
||||
**/
|
||||
info(video: string): Promise<any>;
|
||||
private exec;
|
||||
/**
|
||||
* Count the number of frames in the video using one of two methods.
|
||||
* The first uses -select_streams and is very fast. The second uses
|
||||
* -count_frames and is VERY slow.
|
||||
*
|
||||
* @param {string} video Path to video
|
||||
*
|
||||
* @returns {integer} Number of frames in video
|
||||
**/
|
||||
frames(video: string): Promise<any>;
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FFPROBE = void 0;
|
||||
const promises_1 = require("fs/promises");
|
||||
const path_1 = require("path");
|
||||
const shell_1 = require("../shell");
|
||||
const log_1 = require("../log");
|
||||
/** @module lib/ffprobe */
|
||||
/**
|
||||
* Class representing all ffprobe features.
|
||||
*/
|
||||
class FFPROBE {
|
||||
constructor(bin = 'ffprobe') {
|
||||
this.bin = bin;
|
||||
this.log = (0, log_1.createLog)('ffprobe2');
|
||||
}
|
||||
async exists(path) {
|
||||
try {
|
||||
await (0, promises_1.access)(path);
|
||||
return true;
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parse the fps entry into a float representing the fps of a video
|
||||
**/
|
||||
parseFps(fpsStr) {
|
||||
let fps = 30.0;
|
||||
let parts;
|
||||
if (fpsStr.indexOf('/') !== -1) {
|
||||
parts = fpsStr.split('/');
|
||||
fps = parseFloat(parts[0]) / parseFloat(parts[1]);
|
||||
}
|
||||
else {
|
||||
fps = parseFloat(fpsStr);
|
||||
}
|
||||
return fps;
|
||||
}
|
||||
/**
|
||||
* Get info on a video in json format. Use for filmout.
|
||||
*
|
||||
* @param {string} video Path to video
|
||||
*
|
||||
* @returns {object} Video info in an object
|
||||
**/
|
||||
async info(video) {
|
||||
const cmd = [
|
||||
this.bin,
|
||||
'-v', 'quiet',
|
||||
'-print_format', 'json',
|
||||
'-show_format',
|
||||
'-show_streams',
|
||||
video
|
||||
];
|
||||
let fileExists;
|
||||
let raw;
|
||||
let json;
|
||||
let vid; //whether video has stream with video data
|
||||
try {
|
||||
fileExists = await this.exists(video);
|
||||
}
|
||||
catch (err) {
|
||||
this.log.error(`Error checking if ${video} exists`, err);
|
||||
}
|
||||
if (!fileExists) {
|
||||
this.log.error(new Error(`File ${video} does not exist`));
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
raw = await this.exec(cmd);
|
||||
}
|
||||
catch (err) {
|
||||
this.log.error('Error getting info', err);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
json = JSON.parse(raw);
|
||||
}
|
||||
catch (err) {
|
||||
this.log.error('Error parsing stdout', err);
|
||||
this.log.error(raw);
|
||||
return raw;
|
||||
}
|
||||
if (json.format && json.format.duration) {
|
||||
json.seconds = parseFloat(json.format.duration);
|
||||
}
|
||||
if (json && json.streams) {
|
||||
vid = json.streams.find((stream) => {
|
||||
if (stream.width && stream.height)
|
||||
return stream;
|
||||
});
|
||||
}
|
||||
if (vid) {
|
||||
json.width = vid.width;
|
||||
json.height = vid.height;
|
||||
json.fps = this.parseFps(vid.r_frame_rate);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
async exec(cmd) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
function after(lines) {
|
||||
return resolve(lines);
|
||||
}
|
||||
const child = new shell_1.Shell(cmd, null, null, after, true);
|
||||
await child.execute();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Count the number of frames in the video using one of two methods.
|
||||
* The first uses -select_streams and is very fast. The second uses
|
||||
* -count_frames and is VERY slow.
|
||||
*
|
||||
* @param {string} video Path to video
|
||||
*
|
||||
* @returns {integer} Number of frames in video
|
||||
**/
|
||||
async frames(video) {
|
||||
const ext = (0, path_1.extname)(video.toLowerCase());
|
||||
let cmd = [
|
||||
this.bin,
|
||||
'-v', 'error',
|
||||
'-select_streams', 'v:0',
|
||||
'-show_entries', 'stream=nb_frames',
|
||||
'-of', 'default=nokey=1:noprint_wrappers=1',
|
||||
video
|
||||
];
|
||||
let backup_cmd = [
|
||||
this.bin,
|
||||
'-v', 'error',
|
||||
'-count_frames',
|
||||
'-select_streams', 'v:0',
|
||||
'-show_entries', 'stream=nb_read_frames',
|
||||
'-of', 'default=nokey=1:noprint_wrappers=1',
|
||||
video
|
||||
];
|
||||
let fileExists;
|
||||
let raw;
|
||||
let frames;
|
||||
try {
|
||||
fileExists = await this.exists(video);
|
||||
}
|
||||
catch (err) {
|
||||
this.log.error('Error checking if file exists', err);
|
||||
return false;
|
||||
}
|
||||
if (!fileExists) {
|
||||
this.log.error(new Error(`File ${video} does not exist`));
|
||||
return false;
|
||||
}
|
||||
if (ext === '.mkv') {
|
||||
cmd = backup_cmd;
|
||||
}
|
||||
try {
|
||||
raw = await this.exec(cmd);
|
||||
}
|
||||
catch (err) {
|
||||
this.log.error(err);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
frames = parseInt(raw.stdout);
|
||||
}
|
||||
catch (err) {
|
||||
return raw.stdout;
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
}
|
||||
exports.FFPROBE = FFPROBE;
|
||||
/*
|
||||
function map (obj : any) {
|
||||
console.dir(obj);
|
||||
}
|
||||
*/
|
||||
module.exports = { FFPROBE };
|
||||
//# sourceMappingURL=index.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ffprobe/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;AAEb,0CAAqC;AACrC,+BAA+B;AAC/B,oCAAiC;AACjC,gCAAmC;AAGnC,0BAA0B;AAE1B;;GAEG;AAEH,MAAa,OAAO;IAInB,YAAa,MAAe,SAAS;QACpC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,GAAG,GAAG,IAAA,eAAS,EAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IAEM,KAAK,CAAC,MAAM,CAAE,IAAa;QACjC,IAAI,CAAC;YACJ,MAAM,IAAA,iBAAM,EAAC,IAAI,CAAC,CAAC;YACnB,OAAO,IAAI,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED;;QAEI;IACI,QAAQ,CAAE,MAAe;QAChC,IAAI,GAAG,GAAY,IAAI,CAAC;QACxB,IAAI,KAAgB,CAAC;QACrB,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAChC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1B,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACP,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,GAAG,CAAA;IACX,CAAC;IACD;;;;;;QAMI;IACG,KAAK,CAAC,IAAI,CAAE,KAAc;QAChC,MAAM,GAAG,GAAc;YACtB,IAAI,CAAC,GAAG;YACR,IAAI,EAAE,OAAO;YACb,eAAe,EAAE,MAAM;YACvB,cAAc;YACd,eAAe;YACd,KAAK;SACN,CAAC;QACF,IAAI,UAAoB,CAAC;QACzB,IAAI,GAAS,CAAC;QACd,IAAI,IAAU,CAAC;QACf,IAAI,GAAS,CAAC,CAAC,0CAA0C;QAEzD,IAAI,CAAC;YACJ,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,qBAAqB,KAAK,SAAS,EAAE,GAAG,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,iBAAiB,CAAC,CAAC,CAAC;YAC1D,OAAO,KAAK,CAAA;QACb,CAAC;QAED,IAAI,CAAC;YACJ,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;YAC1C,OAAO,KAAK,CAAA;QACb,CAAC;QAED,IAAI,CAAC;YACJ,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;YAC5C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACpB,OAAO,GAAG,CAAC;QACZ,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACzC,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC1B,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAY,EAAE,EAAE;gBACxC,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM;oBAAE,OAAO,MAAM,CAAC;YAClD,CAAC,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YACvB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YACzB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QAC3C,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,IAAI,CAAE,GAAc;QACjC,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,OAAkB,EAAE,MAAiB,EAAE,EAAE;YAClE,SAAS,KAAK,CAAE,KAAc;gBAC7B,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;YACD,MAAM,KAAK,GAAW,IAAI,aAAK,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YAC9D,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC,CAAC,CAAC;IAEJ,CAAC;IACD;;;;;;;;QAQI;IACG,KAAK,CAAC,MAAM,CAAE,KAAc;QAClC,MAAM,GAAG,GAAY,IAAA,cAAO,EAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;QAClD,IAAI,GAAG,GAAc;YACpB,IAAI,CAAC,GAAG;YACR,IAAI,EAAE,OAAO;YACb,iBAAiB,EAAE,KAAK;YACxB,eAAe,EAAE,kBAAkB;YACnC,KAAK,EAAE,oCAAoC;YAC3C,KAAK;SACL,CAAC;QACF,IAAI,UAAU,GAAc;YAC3B,IAAI,CAAC,GAAG;YACR,IAAI,EAAE,OAAO;YACb,eAAe;YACf,iBAAiB,EAAE,KAAK;YACxB,eAAe,EAAE,uBAAuB;YACxC,KAAK,EAAE,oCAAoC;YAC3C,KAAK;SACL,CAAC;QACF,IAAI,UAAoB,CAAC;QACzB,IAAI,GAAS,CAAC;QACd,IAAI,MAAe,CAAC;QAEpB,IAAI,CAAC;YACJ,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;YACrD,OAAO,KAAK,CAAA;QACb,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,iBAAiB,CAAC,CAAC,CAAC;YAC1D,OAAO,KAAK,CAAC;QACd,CAAC;QAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACpB,GAAG,GAAG,UAAU,CAAC;QAClB,CAAC;QAED,IAAI,CAAC;YACJ,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACpB,OAAO,KAAK,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,OAAO,GAAG,CAAC,MAAM,CAAC;QACnB,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;CACD;AAzKD,0BAyKC;AAED;;;;EAIE;AAEF,MAAM,CAAC,OAAO,GAAG,EAAE,OAAO,EAAE,CAAC"}
|
|
@ -88,7 +88,7 @@ class Files {
|
|||
return videos;
|
||||
}
|
||||
static async enumerateSequence(path) {
|
||||
const dirs = [];
|
||||
const imgs = [];
|
||||
let all;
|
||||
let stats;
|
||||
let filePath;
|
||||
|
@ -104,7 +104,7 @@ class Files {
|
|||
try {
|
||||
stats = await (0, promises_1.lstat)(filePath);
|
||||
if (stats.isFile() && imageExtensions.indexOf((0, path_1.extname)((0, path_1.basename)(elem).toLowerCase())) !== -1) {
|
||||
dirs.push({
|
||||
imgs.push({
|
||||
path: filePath,
|
||||
hash: hash_1.Hashes.stringHash(filePath),
|
||||
name: (0, path_1.basename)(filePath)
|
||||
|
@ -115,7 +115,7 @@ class Files {
|
|||
//
|
||||
}
|
||||
}
|
||||
return dirs;
|
||||
return imgs;
|
||||
}
|
||||
}
|
||||
exports.Files = Files;
|
||||
|
|
|
@ -37,6 +37,7 @@ const log_1 = require("./log");
|
|||
const files_1 = require("./files");
|
||||
const display_1 = require("./display");
|
||||
const ffmpeg_1 = require("./ffmpeg");
|
||||
const ffprobe_1 = require("./ffprobe");
|
||||
const camera_1 = require("./camera");
|
||||
const sequence_1 = require("./sequence");
|
||||
const log = (0, log_1.createLog)('fm');
|
||||
|
@ -45,6 +46,7 @@ let wss;
|
|||
let fd;
|
||||
let display;
|
||||
let ffmpeg;
|
||||
let ffprobe;
|
||||
let camera;
|
||||
let sequence;
|
||||
let index;
|
||||
|
@ -221,10 +223,11 @@ async function main() {
|
|||
await settings();
|
||||
index = await createTemplate('./views/index.hbs');
|
||||
ffmpeg = new ffmpeg_1.FFMPEG(process.env['FFMPEG']);
|
||||
ffprobe = new ffprobe_1.FFPROBE();
|
||||
camera = new camera_1.Camera();
|
||||
display = new display_1.Display(width, height);
|
||||
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
|
||||
sequence = new sequence_1.Sequence(camera, fd, display);
|
||||
sequence = new sequence_1.Sequence(camera, fd, display, ffprobe);
|
||||
app.listen(port, async () => {
|
||||
log.info(`filmout_manager HTTP server running on port ${port}`);
|
||||
});
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2,17 +2,19 @@ import type { SequenceObject } from '../files';
|
|||
import type { FD } from '../fd';
|
||||
import type { Camera } from '../camera';
|
||||
import type { Display } from '../display';
|
||||
import type { FFPROBE } from '../ffprobe';
|
||||
export declare class Sequence {
|
||||
private log;
|
||||
private current;
|
||||
private images;
|
||||
private camera;
|
||||
private display;
|
||||
private ffprobe;
|
||||
private fd;
|
||||
private running;
|
||||
private progress;
|
||||
private frames;
|
||||
constructor(camera: Camera, fd: FD, display: Display);
|
||||
constructor(camera: Camera, fd: FD, display: Display, ffprobe: FFPROBE);
|
||||
start(): void;
|
||||
stop(): void;
|
||||
isRunning(): boolean;
|
||||
|
|
|
@ -4,13 +4,14 @@ exports.Sequence = void 0;
|
|||
const files_1 = require("../files");
|
||||
const log_1 = require("../log");
|
||||
class Sequence {
|
||||
constructor(camera, fd, display) {
|
||||
constructor(camera, fd, display, ffprobe) {
|
||||
this.current = null;
|
||||
this.images = [];
|
||||
this.log = (0, log_1.createLog)('seq');
|
||||
this.camera = camera;
|
||||
this.fd = fd;
|
||||
this.display = display;
|
||||
this.ffprobe = ffprobe;
|
||||
}
|
||||
start() {
|
||||
this.running = true;
|
||||
|
@ -38,6 +39,9 @@ class Sequence {
|
|||
return;
|
||||
}
|
||||
this.log.info(`Sequence ${this.current.name} contains ${this.images.length} image${this.images.length === 1 ? '' : 's'}`);
|
||||
if (this.images.length > 0) {
|
||||
console.dir(await this.ffprobe.info(this.images[0].path));
|
||||
}
|
||||
}
|
||||
unload() {
|
||||
this.current = null;
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sequence/index.ts"],"names":[],"mappings":";;;AAAA,oCAAiC;AACjC,gCAAkC;AAOlC,MAAa,QAAQ;IAWpB,YAAa,MAAe,EAAE,EAAO,EAAE,OAAgB;QAT/C,YAAO,GAAoB,IAAI,CAAC;QAChC,WAAM,GAAmB,EAAE,CAAC;QASnC,IAAI,CAAC,GAAG,GAAG,IAAA,eAAS,EAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IAEM,KAAK;QACX,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACrB,CAAC;IAEM,IAAI;QACV,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAEM,SAAS;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEM,IAAI,CAAE,GAAoB;QAChC,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,IAAI,CAAC,SAAS,EAAE,CAAC;IAClB,CAAC;IAEO,KAAK,CAAC,SAAS;QACtB,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,EAAG,CAAC;YAC5B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;YAClE,OAAO;QACR,CAAC;QAED,IAAI,CAAC;YACJ,IAAI,CAAC,MAAM,GAAG,MAAM,aAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,yCAAyC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;YAClF,OAAO;QACR,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,MAAM,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3H,CAAC;IAEM,MAAM;QACZ,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IAClB,CAAC;IAEM,QAAQ;QACd,OAAO;YACN,IAAI,EAAG,IAAI,CAAC,OAAO,CAAC,IAAI;YACxB,IAAI,EAAG,IAAI,CAAC,OAAO,CAAC,IAAI;YACxB,QAAQ,EAAG,IAAI,CAAC,QAAQ;SACxB,CAAA;IACF,CAAC;CACD;AA/DD,4BA+DC"}
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sequence/index.ts"],"names":[],"mappings":";;;AAAA,oCAAiC;AACjC,gCAAkC;AAQlC,MAAa,QAAQ;IAYpB,YAAa,MAAe,EAAE,EAAO,EAAE,OAAgB,EAAE,OAAiB;QAVlE,YAAO,GAAoB,IAAI,CAAC;QAChC,WAAM,GAAmB,EAAE,CAAC;QAUnC,IAAI,CAAC,GAAG,GAAG,IAAA,eAAS,EAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IAEM,KAAK;QACX,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACrB,CAAC;IAEM,IAAI;QACV,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAEM,SAAS;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEM,IAAI,CAAE,GAAoB;QAChC,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,IAAI,CAAC,SAAS,EAAE,CAAC;IAClB,CAAC;IAEO,KAAK,CAAC,SAAS;QACtB,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,EAAG,CAAC;YAC5B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;YAClE,OAAO;QACR,CAAC;QAED,IAAI,CAAC;YACJ,IAAI,CAAC,MAAM,GAAG,MAAM,aAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,yCAAyC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;YAClF,OAAO;QACR,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,MAAM,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAE1H,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3D,CAAC;IACF,CAAC;IAEM,MAAM;QACZ,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IAClB,CAAC;IAEM,QAAQ;QACd,OAAO;YACN,IAAI,EAAG,IAAI,CAAC,OAAO,CAAC,IAAI;YACxB,IAAI,EAAG,IAAI,CAAC,OAAO,CAAC,IAAI;YACxB,QAAQ,EAAG,IAAI,CAAC,QAAQ;SACxB,CAAA;IACF,CAAC;CACD;AArED,4BAqEC"}
|
|
@ -32,6 +32,14 @@ export class Display {
|
|||
this.offset = { x: 0, y : 0 }
|
||||
}
|
||||
|
||||
public setOffsetX (x : number) {
|
||||
this.offset.x = x;
|
||||
}
|
||||
|
||||
public setOffsetY (y : number) {
|
||||
this.offset.y = y;
|
||||
}
|
||||
|
||||
public setSource (width : number, height : number) {
|
||||
this.source = new Dimensions(width, height);
|
||||
if (this.source.getRatio() > this.screen.getRatio()) {
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
'use strict';
|
||||
|
||||
import { access } from 'fs/promises';
|
||||
import { extname } from 'path';
|
||||
import { Shell } from '../shell';
|
||||
import { createLog } from '../log';
|
||||
import type { Logger } from 'winston';
|
||||
|
||||
/** @module lib/ffprobe */
|
||||
|
||||
/**
|
||||
* Class representing all ffprobe features.
|
||||
*/
|
||||
|
||||
export class FFPROBE {
|
||||
private bin : string;
|
||||
private log : Logger;
|
||||
|
||||
constructor (bin : string = 'ffprobe') {
|
||||
this.bin = bin;
|
||||
this.log = createLog('ffprobe2');
|
||||
}
|
||||
|
||||
public async exists (path : string) : Promise<boolean> {
|
||||
try {
|
||||
await access(path);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the fps entry into a float representing the fps of a video
|
||||
**/
|
||||
private parseFps (fpsStr : string) {
|
||||
let fps : number = 30.0;
|
||||
let parts : string[];
|
||||
if (fpsStr.indexOf('/') !== -1) {
|
||||
parts = fpsStr.split('/');
|
||||
fps = parseFloat(parts[0]) / parseFloat(parts[1]);
|
||||
} else {
|
||||
fps = parseFloat(fpsStr);
|
||||
}
|
||||
return fps
|
||||
}
|
||||
/**
|
||||
* Get info on a video in json format. Use for filmout.
|
||||
*
|
||||
* @param {string} video Path to video
|
||||
*
|
||||
* @returns {object} Video info in an object
|
||||
**/
|
||||
public async info (video : string) {
|
||||
const cmd : string[] = [
|
||||
this.bin,
|
||||
'-v', 'quiet',
|
||||
'-print_format', 'json',
|
||||
'-show_format',
|
||||
'-show_streams',
|
||||
video
|
||||
];
|
||||
let fileExists : boolean;
|
||||
let raw : any;
|
||||
let json : any;
|
||||
let vid : any; //whether video has stream with video data
|
||||
|
||||
try {
|
||||
fileExists = await this.exists(video);
|
||||
} catch (err) {
|
||||
this.log.error(`Error checking if ${video} exists`, err);
|
||||
}
|
||||
if (!fileExists) {
|
||||
this.log.error(new Error(`File ${video} does not exist`));
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
raw = await this.exec(cmd);
|
||||
} catch (err) {
|
||||
this.log.error('Error getting info', err);
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
json = JSON.parse(raw);
|
||||
} catch (err) {
|
||||
this.log.error('Error parsing stdout', err);
|
||||
this.log.error(raw);
|
||||
return raw;
|
||||
}
|
||||
|
||||
if (json.format && json.format.duration) {
|
||||
json.seconds = parseFloat(json.format.duration);
|
||||
}
|
||||
|
||||
if (json && json.streams) {
|
||||
vid = json.streams.find((stream : any) => {
|
||||
if (stream.width && stream.height) return stream;
|
||||
});
|
||||
}
|
||||
|
||||
if (vid) {
|
||||
json.width = vid.width;
|
||||
json.height = vid.height;
|
||||
json.fps = this.parseFps(vid.r_frame_rate)
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
private async exec (cmd : string[]) : Promise<string> {
|
||||
return new Promise(async (resolve : Function, reject : Function) => {
|
||||
function after (lines : string) {
|
||||
return resolve(lines);
|
||||
}
|
||||
const child : Shell = new Shell(cmd, null, null, after, true);
|
||||
await child.execute();
|
||||
});
|
||||
|
||||
}
|
||||
/**
|
||||
* Count the number of frames in the video using one of two methods.
|
||||
* The first uses -select_streams and is very fast. The second uses
|
||||
* -count_frames and is VERY slow.
|
||||
*
|
||||
* @param {string} video Path to video
|
||||
*
|
||||
* @returns {integer} Number of frames in video
|
||||
**/
|
||||
public async frames (video : string) {
|
||||
const ext : string = extname(video.toLowerCase());
|
||||
let cmd : string[] = [
|
||||
this.bin,
|
||||
'-v', 'error',
|
||||
'-select_streams', 'v:0',
|
||||
'-show_entries', 'stream=nb_frames',
|
||||
'-of', 'default=nokey=1:noprint_wrappers=1',
|
||||
video
|
||||
];
|
||||
let backup_cmd : string[] = [
|
||||
this.bin,
|
||||
'-v', 'error',
|
||||
'-count_frames',
|
||||
'-select_streams', 'v:0',
|
||||
'-show_entries', 'stream=nb_read_frames',
|
||||
'-of', 'default=nokey=1:noprint_wrappers=1',
|
||||
video
|
||||
];
|
||||
let fileExists : boolean;
|
||||
let raw : any;
|
||||
let frames : number;
|
||||
|
||||
try {
|
||||
fileExists = await this.exists(video);
|
||||
} catch (err) {
|
||||
this.log.error('Error checking if file exists', err);
|
||||
return false
|
||||
}
|
||||
if (!fileExists) {
|
||||
this.log.error(new Error(`File ${video} does not exist`));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ext === '.mkv') {
|
||||
cmd = backup_cmd;
|
||||
}
|
||||
|
||||
try {
|
||||
raw = await this.exec(cmd);
|
||||
} catch (err) {
|
||||
this.log.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
frames = parseInt(raw.stdout);
|
||||
} catch (err) {
|
||||
return raw.stdout;
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
function map (obj : any) {
|
||||
console.dir(obj);
|
||||
}
|
||||
*/
|
||||
|
||||
module.exports = { FFPROBE };
|
|
@ -113,7 +113,7 @@ export class Files {
|
|||
}
|
||||
|
||||
public static async enumerateSequence (path : string) : Promise<ImageObject[]> {
|
||||
const dirs : ImageObject[] = [];
|
||||
const imgs : ImageObject[] = [];
|
||||
let all : string[];
|
||||
let stats : Stats;
|
||||
let filePath : string;
|
||||
|
@ -131,7 +131,7 @@ export class Files {
|
|||
try {
|
||||
stats = await lstat(filePath);
|
||||
if (stats.isFile() && imageExtensions.indexOf(extname(basename(elem).toLowerCase())) !== -1) {
|
||||
dirs.push({
|
||||
imgs.push({
|
||||
path : filePath,
|
||||
hash : Hashes.stringHash(filePath),
|
||||
name : basename(filePath)
|
||||
|
@ -142,7 +142,7 @@ export class Files {
|
|||
}
|
||||
}
|
||||
|
||||
return dirs;
|
||||
return imgs;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import { TestImage } from './testimage';
|
|||
import { FD } from './fd';
|
||||
import { Display } from './display';
|
||||
import { FFMPEG } from './ffmpeg';
|
||||
import { FFPROBE } from './ffprobe';
|
||||
import { Camera } from './camera';
|
||||
import { Sequence } from './sequence';
|
||||
|
||||
|
@ -33,6 +34,7 @@ let wss : Server;
|
|||
let fd : FD;
|
||||
let display : Display;
|
||||
let ffmpeg : FFMPEG;
|
||||
let ffprobe : FFPROBE;
|
||||
let camera : Camera;
|
||||
let sequence : Sequence;
|
||||
let index : HandlebarsTemplateDelegate<any>;
|
||||
|
@ -215,10 +217,11 @@ async function main () {
|
|||
await settings();
|
||||
index = await createTemplate('./views/index.hbs');
|
||||
ffmpeg = new FFMPEG(process.env['FFMPEG']);
|
||||
ffprobe = new FFPROBE();
|
||||
camera = new Camera();
|
||||
display = new Display(width, height);
|
||||
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
|
||||
sequence = new Sequence(camera, fd, display);
|
||||
sequence = new Sequence(camera, fd, display, ffprobe);
|
||||
|
||||
app.listen(port, async () => {
|
||||
log.info(`filmout_manager HTTP server running on port ${port}`);
|
||||
|
|
|
@ -5,6 +5,7 @@ import type { SequenceObject, ImageObject } from '../files';
|
|||
import type { FD } from '../fd';
|
||||
import type { Camera } from '../camera';
|
||||
import type { Display } from '../display';
|
||||
import type { FFPROBE } from '../ffprobe';
|
||||
|
||||
export class Sequence {
|
||||
private log : Logger;
|
||||
|
@ -12,16 +13,18 @@ export class Sequence {
|
|||
private images : ImageObject[] = [];
|
||||
private camera : Camera;
|
||||
private display : Display;
|
||||
private ffprobe : FFPROBE;
|
||||
private fd : FD;
|
||||
private running : boolean;
|
||||
private progress : number;
|
||||
private frames : number;
|
||||
|
||||
constructor (camera : Camera, fd : FD, display: Display) {
|
||||
constructor (camera : Camera, fd : FD, display: Display, ffprobe : FFPROBE) {
|
||||
this.log = createLog('seq');
|
||||
this.camera = camera;
|
||||
this.fd = fd;
|
||||
this.display = display;
|
||||
this.ffprobe = ffprobe;
|
||||
}
|
||||
|
||||
public start () {
|
||||
|
@ -55,6 +58,10 @@ export class Sequence {
|
|||
}
|
||||
|
||||
this.log.info(`Sequence ${this.current.name} contains ${this.images.length} image${this.images.length === 1 ? '' : 's'}`);
|
||||
|
||||
if (this.images.length > 0) {
|
||||
console.dir(await this.ffprobe.info(this.images[0].path));
|
||||
}
|
||||
}
|
||||
|
||||
public unload () {
|
||||
|
|
|
@ -7,6 +7,8 @@ declare class Client {
|
|||
private onOpen;
|
||||
private setSequence;
|
||||
private cmd;
|
||||
disableClass(className: string): void;
|
||||
enableClass(className: string): void;
|
||||
sendCameraOpen(): void;
|
||||
private receiveCameraOpen;
|
||||
sendCameraClose(): void;
|
||||
|
|
|
@ -35,24 +35,39 @@ class Client {
|
|||
break;
|
||||
case 'select':
|
||||
this.receiveSelect(msg);
|
||||
break;
|
||||
default:
|
||||
console.warn(`No command ${msg.cmd}`);
|
||||
console.warn(`No command "${msg.cmd}"`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
disableClass(className) {
|
||||
document.querySelectorAll(`.${className}`).forEach((el) => {
|
||||
el.disabled = true;
|
||||
});
|
||||
}
|
||||
enableClass(className) {
|
||||
document.querySelectorAll(`.${className}`).forEach((el) => {
|
||||
el.disabled = false;
|
||||
});
|
||||
}
|
||||
sendCameraOpen() {
|
||||
console.log('send camera open');
|
||||
this.disableClass('manualCtrl');
|
||||
this.client.send(JSON.stringify({ cmd: 'open' }));
|
||||
}
|
||||
receiveCameraOpen() {
|
||||
console.log('got camera open');
|
||||
this.enableClass('manualCtrl');
|
||||
}
|
||||
sendCameraClose() {
|
||||
console.log('send camera close');
|
||||
this.disableClass('manualCtrl');
|
||||
this.client.send(JSON.stringify({ cmd: 'close' }));
|
||||
}
|
||||
receiveCameraClose() {
|
||||
console.log('got camera close');
|
||||
this.enableClass('manualCtrl');
|
||||
}
|
||||
sendSelect() {
|
||||
const sequence = document.getElementById('sequence').value;
|
||||
|
@ -66,6 +81,8 @@ class Client {
|
|||
this.client.send(JSON.stringify(msg));
|
||||
}
|
||||
receiveSelect(msg) {
|
||||
console.log('got select');
|
||||
console.dir(msg);
|
||||
}
|
||||
fullscreen() {
|
||||
if (!document.fullscreenElement) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../browser/index.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../browser/index.ts"],"names":[],"mappings":"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"}
|
|
@ -46,8 +46,15 @@
|
|||
<button id="select" onclick="client.sendSelect();">Select</button>
|
||||
</div>
|
||||
<div>
|
||||
<button id="open" onclick="client.sendCameraOpen()">Open Gate</button>
|
||||
<button id="close" onclick="client.sendCameraClose()">Close Gate</button>
|
||||
<button id="start" class="sequenceCtrl" disabled>Start</button>
|
||||
<button id="stop" class="sequenceCtrl" disabled>Stop</button>
|
||||
<button id="pause" class="sequenceCtrl" disabled>Pause</button>
|
||||
</div>
|
||||
<div>
|
||||
<button id="open" class="manualCtrl" onclick="client.sendCameraOpen()">Open Gate</button>
|
||||
<button id="close" class="manualCtrl" onclick="client.sendCameraClose()">Close Gate</button>
|
||||
<button id="focus" class="manualCtrl" onclick="">Focus</button>
|
||||
<button id="framing" class="manualCtrl" onclick="">Framing</button>
|
||||
</div>
|
||||
<div class="status-bar" id="status">
|
||||
<p class="status-bar-field">Idle</p>
|
||||
|
|
Loading…
Reference in New Issue