12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- const ChildProcess = require('child_process');
- const { Duplex } = require('stream');
- let FFMPEG_COMMAND = null;
- class FFmpegTransform extends Duplex {
- constructor(options) {
- super();
- this.process = createFFmpeg(options);
- const EVENTS = {
- readable: this._reader,
- data: this._reader,
- end: this._reader,
- unpipe: this._reader,
- finish: this._writer,
- drain: this._writer,
- };
- this._readableState = this._reader._readableState;
- this._writableState = this._writer._writableState;
- this._copy(['write', 'end'], this._writer);
- this._copy(['read', 'setEncoding', 'pipe', 'unpipe'], this._reader);
- for (const method of ['on', 'once', 'removeListener', 'removeListeners', 'listeners']) {
- this[method] = (ev, fn) => EVENTS[ev] ? EVENTS[ev][method](ev, fn) : Duplex.prototype[method].call(this, ev, fn);
- }
- const processError = error => this.emit('error', error);
- this._reader.on('error', processError);
- this._writer.on('error', processError);
- }
- get _reader() { return this.process.stdout; }
- get _writer() { return this.process.stdin; }
- _copy(methods, target) {
- for (const method of methods) {
- this[method] = target[method].bind(target);
- }
- }
- _destroy(err, cb) {
- super._destroy(err, cb);
- this.process.kill('SIGKILL');
- }
- }
- module.exports = FFmpegTransform;
- function createFFmpeg(options) {
- let args = options.args || [];
- if (!options.args.includes('-i')) args = ['-i', '-'].concat(args);
- return ChildProcess.spawn(selectFFmpegCommand(), args.concat(['pipe:1']));
- }
- function selectFFmpegCommand() {
- if (FFMPEG_COMMAND) return FFMPEG_COMMAND;
- try {
- FFMPEG_COMMAND = require('ffmpeg-binaries').ffmpegPath();
- return FFMPEG_COMMAND;
- } catch (err) {
- for (const command of ['ffmpeg', 'avconv', './ffmpeg', './avconv']) {
- if (!ChildProcess.spawnSync(command, ['-h']).error) {
- FFMPEG_COMMAND = command;
- return FFMPEG_COMMAND;
- }
- }
- throw new Error('FFMPEG not found');
- }
- }
|