Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
});
opts.inputPath = await muteProcess;
}
return convert(opts.outputPath, opts, [
'-i', opts.inputPath,
'-r', opts.fps,
'-s', `${makeEven(opts.width)}x${makeEven(opts.height)}`,
'-ss', opts.startTime,
'-to', opts.endTime,
opts.outputPath
]);
});
const convertToWebm = PCancelable.fn(async (opts, onCancel) => {
if (opts.isMuted) {
const muteProcess = mute(opts.inputPath);
onCancel(() => {
muteProcess.cancel();
});
opts.inputPath = await muteProcess;
}
return convert(opts.outputPath, opts, [
'-i', opts.inputPath,
// http://wiki.webmproject.org/ffmpeg
// https://trac.ffmpeg.org/wiki/Encode/VP9
'-threads', Math.max(os.cpus().length - 1, 1),
'-deadline', 'good', // `best` is twice as slow and only slighty better
// Should be similiar to the Gif generation
const convertToApng = opts => {
return convert(opts.outputPath, opts, [
'-i', opts.inputPath,
'-vf', `fps=${opts.fps},scale=${opts.width}:${opts.height}:flags=lanczos[x]`,
// Strange for APNG instead of -loop it uses -plays see: https://stackoverflow.com/questions/43795518/using-ffmpeg-to-create-looping-apng
'-plays', opts.loop === true ? '0' : '1', // 0 == forever; 1 == no loop
'-ss', opts.startTime,
'-to', opts.endTime,
opts.outputPath
]);
};
// `time ffmpeg -i original.mp4 -vf fps=30,scale=480:-1::flags=lanczos,palettegen palette.png`
// `time ffmpeg -i original.mp4 -i palette.png -filter_complex 'fps=30,scale=-1:-1:flags=lanczos[x]; [x][1:v]paletteuse' palette.gif`
const convertToGif = PCancelable.fn(async (opts, onCancel) => {
const palettePath = tmp.tmpNameSync({postfix: '.png'});
const paletteProcessor = execa(ffmpegPath, [
'-ss', opts.startTime,
'-to', opts.endTime,
'-i', opts.inputPath,
'-vf', `fps=${opts.fps},scale=${opts.width}:${opts.height}:flags=lanczos,palettegen`,
palettePath
]);
onCancel(() => {
paletteProcessor.kill();
});
await paletteProcessor;
return convert(opts.outputPath, opts, [
import Cancelable, { CancelError } from 'p-cancelable'
import Queue from 'p-queue'
import timeout from 'p-timeout'
import globals from '../utils/globals'
import promisify from '../utils/promisify'
const CONCURRENCY = 10
const queue = new Queue({ concurrency: CONCURRENCY })
const request = promisify(globals.wx.request)
export default Cancelable.fn((onCancel, options = {}) => {
let job, isCanceled
onCancel(() => {
if (job) {
job.cancel()
} else {
isCanceled = true
}
})
return queue.add(() => {
if (isCanceled) {
return Promise.reject(new CancelError())
}
job = request(options)
if (options.timeout) {
job = timeout(job, options.timeout)
}
'-i', inputPath,
'-an',
'-vcodec', 'copy',
mutedPath
]);
onCancel(() => {
converter.kill();
});
await converter;
return mutedPath;
});
const convertToMp4 = PCancelable.fn(async (opts, onCancel) => {
if (opts.isMuted) {
const muteProcess = mute(opts.inputPath);
onCancel(() => {
muteProcess.cancel();
});
opts.inputPath = await muteProcess;
}
return convert(opts.outputPath, opts, [
'-i', opts.inputPath,
'-r', opts.fps,
'-s', `${makeEven(opts.width)}x${makeEven(opts.height)}`,
'-ss', opts.startTime,
'-to', opts.endTime,
converter.on('exit', code => {
if (code === 0) {
track('file/export/convert/completed');
resolve(outputPath);
} else {
track('file/export/convert/failed');
reject(new Error(`ffmpeg exited with code: ${code}\n\n${stderr}`));
}
});
converter.catch(reject);
});
};
const mute = PCancelable.fn(async (inputPath, onCancel) => {
const mutedPath = tmp.tmpNameSync({postfix: path.extname(inputPath)});
const converter = execa(ffmpegPath, [
'-i', inputPath,
'-an',
'-vcodec', 'copy',
mutedPath
]);
onCancel(() => {
converter.kill();
});
await converter;
return mutedPath;
});
return queue.add(() => {
if (isCanceled) {
return Promise.reject(new CancelError())
}
job = request(options)
if (options.timeout) {
job = timeout(job, options.timeout)
}
return job
})
})