132 lines
3.1 KiB
JavaScript
132 lines
3.1 KiB
JavaScript
const defaultArgs = require('./constants/defaultArgs');
|
|
const { setLogging, log } = require('./utils/log');
|
|
const resolvePaths = require('./utils/resolvePaths');
|
|
const parseProgress = require('./utils/parseProgress');
|
|
const stringList2pointer = require('./utils/stringList2pointer');
|
|
const parseArgs = require('./utils/parseArgs');
|
|
const {
|
|
defaultOptions,
|
|
getModule,
|
|
fetchFile,
|
|
} = require('./node');
|
|
|
|
const NO_LOAD = Error('FFmpeg.js is not ready, make sure you have completed load().');
|
|
const NO_MULTIPLE_RUN = Error('FFmpeg.js can only run one command at a time');
|
|
let Module = null;
|
|
let ffmpeg = null;
|
|
|
|
module.exports = (_options = {}) => {
|
|
let runResolve = null;
|
|
let running = false;
|
|
const {
|
|
log: logging,
|
|
logger,
|
|
progress,
|
|
...options
|
|
} = resolvePaths({
|
|
...defaultOptions,
|
|
..._options,
|
|
});
|
|
const detectCompletion = ({ message, type }) => {
|
|
if (type === 'ffmpeg-stdout'
|
|
&& message === 'FFMPEG_END'
|
|
&& runResolve !== null) {
|
|
runResolve();
|
|
runResolve = null;
|
|
running = false;
|
|
}
|
|
};
|
|
|
|
setLogging(logging);
|
|
|
|
const load = async () => {
|
|
if (Module === null) {
|
|
log('info', 'load ffmpeg-core');
|
|
Module = await getModule(options);
|
|
Module.setLogger((_log) => {
|
|
detectCompletion(_log);
|
|
parseProgress(_log, progress);
|
|
logger(_log);
|
|
log(_log.type, _log.message);
|
|
});
|
|
if (ffmpeg === null) {
|
|
ffmpeg = Module.cwrap('proxy_main', 'number', ['number', 'number']);
|
|
}
|
|
log('info', 'ffmpeg-core loaded');
|
|
}
|
|
};
|
|
|
|
const FS = (method, args) => {
|
|
if (Module === null) {
|
|
throw NO_LOAD;
|
|
} else {
|
|
log('info', `FS.${method} ${args[0]}`);
|
|
return Module.FS[method](...args);
|
|
}
|
|
};
|
|
|
|
const write = async (path, data) => (
|
|
FS('writeFile', [path, await fetchFile(data)])
|
|
);
|
|
|
|
const writeText = (path, text) => (
|
|
FS('writeFile', [path, text])
|
|
);
|
|
|
|
const read = (path) => (
|
|
FS('readFile', [path])
|
|
);
|
|
|
|
const remove = (path) => (
|
|
FS('unlink', [path])
|
|
);
|
|
|
|
const ls = (path) => (
|
|
FS('readdir', [path])
|
|
);
|
|
|
|
const run = (_args) => {
|
|
if (ffmpeg === null) {
|
|
throw NO_LOAD;
|
|
} else if (running) {
|
|
throw NO_MULTIPLE_RUN;
|
|
} else {
|
|
running = true;
|
|
return new Promise((resolve) => {
|
|
const args = [...defaultArgs, ...parseArgs(_args)].filter((s) => s.length !== 0);
|
|
log('info', `ffmpeg command: ${args.join(' ')}`);
|
|
runResolve = resolve;
|
|
ffmpeg(args.length, stringList2pointer(Module, args));
|
|
});
|
|
}
|
|
};
|
|
|
|
const transcode = (input, output, opts = '') => (
|
|
run(`-i ${input} ${opts} ${output}`)
|
|
);
|
|
|
|
const trim = (input, output, from, to, opts = '') => (
|
|
run(`-i ${input} -ss ${from} -to ${to} ${opts} ${output}`)
|
|
);
|
|
|
|
const concatDemuxer = (input, output, opts = '') => {
|
|
const text = input.reduce((acc, path) => `${acc}\nfile ${path}`, '');
|
|
writeText('concat_list.txt', text);
|
|
return run(`-f concat -safe 0 -i concat_list.txt ${opts} ${output}`);
|
|
};
|
|
|
|
return {
|
|
load,
|
|
FS,
|
|
write,
|
|
writeText,
|
|
read,
|
|
remove,
|
|
ls,
|
|
run,
|
|
transcode,
|
|
trim,
|
|
concatDemuxer,
|
|
};
|
|
};
|