import path from "path" const ffmpeg = require("fluent-ffmpeg") const defaultParams = { audioBitrate: 128, videoBitrate: 1024, videoCodec: "libvpx", audioCodec: "libvorbis", format: "mp4", } const maxTasks = 5 export default (input, params = defaultParams) => { return new Promise((resolve, reject) => { if (!global.ffmpegTasks) { global.ffmpegTasks = [] } if (global.ffmpegTasks.length >= maxTasks) { return reject(new Error("Too many transcoding tasks")) } const outputFilename = `${path.basename(input).split(".")[0]}_ff.${params.format ?? "webm"}` const outputFilepath = `${path.dirname(input)}/${outputFilename}` console.debug(`[TRANSCODING] Transcoding ${input} to ${outputFilepath}`) const onEnd = async () => { console.debug( `[TRANSCODING] Finished transcode ${input} to ${outputFilepath}`, ) return resolve({ filename: outputFilename, filepath: outputFilepath, }) } const onError = (err) => { console.error( `[TRANSCODING] Transcoding ${input} to ${outputFilepath} failed`, err, ) return reject(err) } let exec = null const commands = { input: input, ...params, output: outputFilepath, outputOptions: ["-preset veryfast"], } // chain methods for (let key in commands) { if (exec === null) { exec = ffmpeg(commands[key]) continue } if (key === "extraOptions" && Array.isArray(commands[key])) { for (const option of commands[key]) { exec = exec.inputOptions(option) } continue } if (key === "outputOptions" && Array.isArray(commands[key])) { for (const option of commands[key]) { exec = exec.outputOptions(option) } continue } if (typeof exec[key] !== "function") { console.warn(`[TRANSCODING] Method ${key} is not a function`) return false } if (Array.isArray(commands[key])) { exec = exec[key](...commands[key]) } else { exec = exec[key](commands[key]) } continue } exec.on("error", onError).on("end", onEnd).run() }) }