framo
Version:
Glorious media processing right in your browser with Typescript support
127 lines • 5.81 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FrameExtractorService = void 0;
const tslib_1 = require("tslib");
const utility_1 = require("../utility/utility");
const ffmpeg_service_1 = require("./ffmpeg.service");
const outputFilePrefix = "out";
const outputFileDigits = 6;
class FrameExtractorService {
constructor() {
this.ffmpegService = ffmpeg_service_1.FfmpegService.getInstance();
this.extractFrames = (config) => tslib_1.__awaiter(this, void 0, void 0, function* () {
try {
const fileBlob = yield this.ffmpegService.fetchFile(config.filename, config.file);
const { parameters, outputFilenames } = yield this.getParameters(config, fileBlob);
yield this.ffmpegService.ffmpeg.run(...parameters);
const blobs = outputFilenames.map((filename) => {
const data = this.ffmpegService.ffmpeg.FS("readFile", filename);
return new Blob([data.buffer]);
});
return blobs;
}
catch (error) {
throw new Error(error);
}
});
}
static getInstance() {
if (!FrameExtractorService.instance) {
FrameExtractorService.instance = new FrameExtractorService();
}
return FrameExtractorService.instance;
}
getParameters(config, fileBlob) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const auxillaryParameters = ["-y"];
let parametersResponse = {
parameters: [],
outputFilenames: [],
};
if (config.timePoints) {
parametersResponse = this.getTimeBasedParameters(config);
}
else if (config.timeInterval) {
parametersResponse = yield this.getIntervalBasedParameters(config, fileBlob);
}
const response = {
parameters: [...parametersResponse.parameters, ...auxillaryParameters],
outputFilenames: parametersResponse.outputFilenames,
};
return response;
});
}
getTimeBasedParameters(config) {
var _a;
const inParameters = [];
const outParameters = [];
const outputFilenames = [];
const scale = config.resolution ? utility_1.Utility.getScale(config.resolution) : '';
(_a = config.timePoints) === null || _a === void 0 ? void 0 : _a.forEach((timePoint, index) => {
inParameters.push(...this.getSingleTimeBasedParameter(timePoint, config.filename));
const outputFilename = utility_1.Utility.getOutputFilename(index, config.outputExtension);
outputFilenames.push(outputFilename);
outParameters.push(...this.getOutputMappingParameter(index, outputFilename, scale));
});
const response = {
parameters: [...inParameters, ...outParameters],
outputFilenames,
};
return response;
}
getSingleTimeBasedParameter(time, filename) {
return ["-ss", `${time}`, "-i", filename];
}
getOutputMappingParameter(index, outputFilename, scale) {
const outputMapping = ["-map", `${index}:v`, "-frames:v", "1"];
if (scale) {
outputMapping.push(...['-vf', scale]);
}
outputMapping.push(outputFilename);
return outputMapping;
}
getIntervalBasedParameters(config, fileBlob) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const mediainfo = yield this.ffmpegService.getMediaInfo(fileBlob);
const videoDuration = utility_1.Utility.getVideoDuration(mediainfo);
const frameCount = utility_1.Utility.getFrameCount(mediainfo);
console.log(frameCount);
const interval = config.timeInterval;
const rate = (1 / (interval !== null && interval !== void 0 ? interval : 1)).toFixed(2);
const scale = config.resolution ? utility_1.Utility.getScale(config.resolution) : '';
const inParameters = this.getInParametersForIntervalBasedExtraction(config.filename, rate, scale);
const outParameters = [`out_%0${outputFileDigits}d.${config.outputExtension}`];
const outputFilenames = [];
for (let i = interval, j = 1; i <= videoDuration; i += interval, j++) {
const outputFilename = utility_1.Utility.getFilenameWithPadding(j, 'out', outputFileDigits, config.outputExtension);
outputFilenames.push(outputFilename);
}
const response = {
parameters: [...inParameters, ...outParameters],
outputFilenames,
};
return response;
});
}
getOutputFilenamesForIntervalBasedParameters(interval, videoDuration, extension) {
const filenames = [];
const numberOfFrames = videoDuration / interval;
for (let i = 1; i <= numberOfFrames; i++) {
const filenumber = i.toString().padStart(outputFileDigits, "0");
filenames.push(`${outputFilePrefix}_${filenumber}.${extension}`);
}
return filenames;
}
getInParametersForIntervalBasedExtraction(filename, rate, scale) {
const inParameters = ['-i', filename, '-vf'];
if (scale) {
inParameters.push(`fps=${rate},${scale}`);
}
else {
inParameters.push(`fps=${rate}`);
}
return inParameters;
}
}
exports.FrameExtractorService = FrameExtractorService;
//# sourceMappingURL=frame-extractor.service.js.map