summaryrefslogtreecommitdiff
path: root/node_modules/prism-media/src/transcoders/ffmpeg
diff options
context:
space:
mode:
author8cy <[email protected]>2020-04-03 02:37:42 -0700
committer8cy <[email protected]>2020-04-03 02:37:42 -0700
commit60867fb030bae582082340ead7dbc7efdc2f5398 (patch)
tree4c6a7356351be2e4914e15c4703172597c45656e /node_modules/prism-media/src/transcoders/ffmpeg
parentcommenting (diff)
downloads5nical-60867fb030bae582082340ead7dbc7efdc2f5398.tar.xz
s5nical-60867fb030bae582082340ead7dbc7efdc2f5398.zip
2020/04/03, 02:34, v1.2.0
Diffstat (limited to 'node_modules/prism-media/src/transcoders/ffmpeg')
-rw-r--r--node_modules/prism-media/src/transcoders/ffmpeg/Ffmpeg.js56
-rw-r--r--node_modules/prism-media/src/transcoders/ffmpeg/FfmpegProcess.js95
2 files changed, 151 insertions, 0 deletions
diff --git a/node_modules/prism-media/src/transcoders/ffmpeg/Ffmpeg.js b/node_modules/prism-media/src/transcoders/ffmpeg/Ffmpeg.js
new file mode 100644
index 0000000..b34dadc
--- /dev/null
+++ b/node_modules/prism-media/src/transcoders/ffmpeg/Ffmpeg.js
@@ -0,0 +1,56 @@
+const ChildProcess = require('child_process');
+const FfmpegProcess = require('./FfmpegProcess');
+
+class FfmpegTranscoder {
+ constructor(mediaTranscoder) {
+ this.mediaTranscoder = mediaTranscoder;
+ this.command = FfmpegTranscoder.selectFfmpegCommand();
+ this.processes = [];
+ }
+
+ static verifyOptions(options) {
+ if (!options) throw new Error('Options not provided!');
+ if (!options.media) throw new Error('Media must be provided');
+ if (!options.ffmpegArguments || !(options.ffmpegArguments instanceof Array)) {
+ throw new Error('FFMPEG Arguments must be an array');
+ }
+ if (options.ffmpegArguments.includes('-i')) return options;
+ if (typeof options.media === 'string') {
+ options.ffmpegArguments = ['-i', `${options.media}`].concat(options.ffmpegArguments).concat(['pipe:1']);
+ } else {
+ options.ffmpegArguments = ['-i', '-'].concat(options.ffmpegArguments).concat(['pipe:1']);
+ }
+ return options;
+ }
+
+ /**
+ * Transcodes an input using FFMPEG
+ * @param {FfmpegTranscoderOptions} options the options to use
+ * @returns {FfmpegProcess} the created FFMPEG process
+ * @throws {FFMPEGOptionsError}
+ */
+ transcode(options) {
+ if (!this.command) this.command = FfmpegTranscoder.selectFfmpegCommand();
+ const proc = new FfmpegProcess(this, FfmpegTranscoder.verifyOptions(options));
+ this.processes.push(proc);
+ return proc;
+ }
+
+ static selectFfmpegCommand() {
+ try {
+ const ffmpegStatic = require('ffmpeg-static');
+ return ffmpegStatic.path || ffmpegStatic;
+ } catch (err1) {
+ try {
+ return require('ffmpeg-binaries');
+ } catch (err2) {
+ for (const command of ['ffmpeg', 'avconv', './ffmpeg', './avconv']) {
+ if (!ChildProcess.spawnSync(command, ['-h']).error) return command;
+ }
+ throw new Error('FFMPEG not found');
+ }
+ }
+ }
+}
+
+module.exports = FfmpegTranscoder;
diff --git a/node_modules/prism-media/src/transcoders/ffmpeg/FfmpegProcess.js b/node_modules/prism-media/src/transcoders/ffmpeg/FfmpegProcess.js
new file mode 100644
index 0000000..c6561a9
--- /dev/null
+++ b/node_modules/prism-media/src/transcoders/ffmpeg/FfmpegProcess.js
@@ -0,0 +1,95 @@
+const EventEmitter = require('events').EventEmitter;
+const ChildProcess = require('child_process');
+
+/**
+ * A spawned FFMPEG process
+ */
+class FfmpegProcess extends EventEmitter {
+ constructor(ffmpegTranscoder, options) {
+ super();
+ /**
+ * The ffmpeg process
+ * @type {ChildProcess}
+ */
+ this.process = ChildProcess.spawn(ffmpegTranscoder.command, options.ffmpegArguments);
+ /**
+ * The FFMPEG transcoder that created this process
+ * @type {FfmpegTranscoder}
+ */
+ this.transcoder = ffmpegTranscoder;
+ /**
+ * The input media
+ * @type {?ReadableStream|string}
+ */
+ this.inputMedia = options.media;
+
+ if (typeof this.inputMedia !== 'string') {
+ try {
+ this.connectStream(this.inputMedia);
+ } catch (e) {
+ this.emit('error', e, 'instantiation');
+ }
+ } else {
+ this.attachErrorHandlers();
+ }
+
+ this.on('error', this.kill.bind(this));
+ this.once('end', this.kill.bind(this));
+ }
+
+ /**
+ * The ffmpeg output stream
+ * @type {?ReadableStream}
+ */
+ get output() {
+ return this.process ? this.process.stdout : null;
+ }
+
+ attachErrorHandlers() {
+ this.process.stdin.on('error', e => {
+ // if not killed
+ if (this.process) {
+ this.emit('error', e, 'ffmpegProcess.stdin');
+ }
+ });
+ this.process.stdout.on('error', e => {
+ // if not killed
+ if (this.process) {
+ this.emit('error', e, 'ffmpegProcess.stdout');
+ }
+ });
+ this.process.on('error', e => this.emit('error', e, 'ffmpegProcess'));
+ this.process.stdout.on('end', () => this.emit('end'));
+ }
+
+ /**
+ * Connects an input stream to the ffmpeg process
+ * @param {ReadableStream} inputMedia the stream to pass to ffmpeg
+ * @returns {ReadableStream} the ffmpeg output stream
+ */
+ connectStream(inputMedia) {
+ if (!this.process) throw new Error('No FFMPEG process available');
+ this.inputMedia = inputMedia;
+ this.inputMedia.pipe(this.process.stdin, { end: false });
+
+ inputMedia.on('error', e => this.emit('error', e, 'inputstream', inputMedia));
+
+ this.attachErrorHandlers();
+
+ return this.process.stdout;
+ }
+
+ /**
+ * Kills the ffmpeg process
+ */
+ kill() {
+ if (!this.process) return;
+ if (this.inputMedia && this.inputMedia.unpipe) {
+ this.inputMedia.unpipe(this.process.stdin);
+ }
+ this.process.kill('SIGKILL');
+ this.process = null;
+ }
+}
+
+module.exports = FfmpegProcess;