2024-08-09 20:20:07 +00:00
|
|
|
'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");
|
|
|
|
/**
|
|
|
|
* 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`));
|
2024-08-15 02:43:02 +00:00
|
|
|
return null;
|
2024-08-09 20:20:07 +00:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
raw = await this.exec(cmd);
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
this.log.error('Error getting info', err);
|
2024-08-15 02:43:02 +00:00
|
|
|
return null;
|
2024-08-09 20:20:07 +00:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
2024-11-04 20:13:59 +00:00
|
|
|
const child = new shell_1.Shell(cmd, null, null, null, after, true);
|
2024-08-09 20:20:07 +00:00
|
|
|
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
|