60 lines
1.1 KiB
JavaScript
60 lines
1.1 KiB
JavaScript
const { Readable, PassThrough } = require("stream");
|
|
const { spawn } = require("child_process");
|
|
|
|
class FFMPEG {
|
|
constructor(data) {
|
|
this.data = data; // Can be Readable or Buffer
|
|
this.isBuffer = data instanceof Buffer;
|
|
}
|
|
|
|
convert() {
|
|
return new Promise((resolve, reject) => {
|
|
const ffmpegArgs = [
|
|
"-i",
|
|
"pipe:0",
|
|
"-c:v",
|
|
"libx264",
|
|
"-profile:v",
|
|
"high",
|
|
"-level",
|
|
"4.1",
|
|
"-c:a",
|
|
"aac",
|
|
"-crf",
|
|
"26",
|
|
"-preset",
|
|
"medium",
|
|
"-movflags",
|
|
"+frag_keyframe+empty_moov+default_base_moof",
|
|
"-f",
|
|
"mp4",
|
|
"pipe:1",
|
|
];
|
|
|
|
const ff = spawn("ffmpeg", ffmpegArgs);
|
|
|
|
const inputStream = this.isBuffer ? Readable.from(this.data) : this.data;
|
|
|
|
inputStream.pipe(ff.stdin);
|
|
|
|
const output = new PassThrough();
|
|
ff.stdout.pipe(output);
|
|
|
|
let errData = "";
|
|
ff.stderr.on("data", (chunk) => (errData += chunk.toString()));
|
|
|
|
ff.on("close", (code) => {
|
|
if (code !== 0) {
|
|
reject(new Error(`FFMPEG exited with code ${code}\n${errData}`));
|
|
}
|
|
});
|
|
|
|
ff.on("error", reject);
|
|
|
|
resolve(output);
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = FFMPEG;
|