summaryrefslogtreecommitdiff
path: root/node_modules/prism-media/src
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
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')
-rw-r--r--node_modules/prism-media/src/Prism.js17
-rw-r--r--node_modules/prism-media/src/index.js6
-rw-r--r--node_modules/prism-media/src/opus/OggOpus.js90
-rw-r--r--node_modules/prism-media/src/transcoders/MediaTranscoder.js31
-rw-r--r--node_modules/prism-media/src/transcoders/ffmpeg/Ffmpeg.js56
-rw-r--r--node_modules/prism-media/src/transcoders/ffmpeg/FfmpegProcess.js95
-rw-r--r--node_modules/prism-media/src/util/Constants.js0
7 files changed, 295 insertions, 0 deletions
diff --git a/node_modules/prism-media/src/Prism.js b/node_modules/prism-media/src/Prism.js
new file mode 100644
index 0000000..b2cee9e
--- /dev/null
+++ b/node_modules/prism-media/src/Prism.js
@@ -0,0 +1,17 @@
+const MediaTranscoder = require('./transcoders/MediaTranscoder');
+
+class Prism {
+ constructor() {
+ this.transcoder = new MediaTranscoder(this);
+ }
+
+ createTranscoder(...args) {
+ return this.transcode(...args);
+ }
+
+ transcode(...args) {
+ return this.transcoder.transcode(...args);
+ }
+}
+
+module.exports = Prism;
diff --git a/node_modules/prism-media/src/index.js b/node_modules/prism-media/src/index.js
new file mode 100644
index 0000000..9437f57
--- /dev/null
+++ b/node_modules/prism-media/src/index.js
@@ -0,0 +1,6 @@
+const Prism = require('./Prism');
+const MediaTranscoder = require('./transcoders/MediaTranscoder');
+
+Prism.MediaTranscoder = MediaTranscoder;
+
+module.exports = Prism;
diff --git a/node_modules/prism-media/src/opus/OggOpus.js b/node_modules/prism-media/src/opus/OggOpus.js
new file mode 100644
index 0000000..9a938cd
--- /dev/null
+++ b/node_modules/prism-media/src/opus/OggOpus.js
@@ -0,0 +1,90 @@
+const { Transform } = require('stream');
+
+const OGG_PAGE_HEADER_SIZE = 26;
+const STREAM_STRUCTURE_VERSION = 0;
+
+const OGGS_HEADER = Buffer.from('OggS'.split('').map(x => x.charCodeAt(0)));
+const OPUS_HEAD = Buffer.from('OpusHead'.split('').map(x => x.charCodeAt(0)));
+const OPUS_TAGS = Buffer.from('OpusTags'.split('').map(x => x.charCodeAt(0)));
+
+class OggOpusTransform extends Transform {
+ constructor() {
+ super();
+ this._remainder = null;
+ this._head = null;
+ }
+
+ _transform(chunk, encoding, done) {
+ if (this._remainder) {
+ chunk = Buffer.concat([this._remainder, chunk]);
+ this._remainder = null;
+ }
+
+ while (chunk) {
+ try {
+ const result = this.readPage(chunk);
+ if (result) chunk = result;
+ else break;
+ } catch (err) {
+ this.emit('error', err);
+ }
+ }
+ this._remainder = chunk;
+ done();
+ }
+
+ /**
+ * Reads a page from a buffer
+ * @param {Buffer} chunk The chunk containing the page
+ * @returns {boolean|Buffer}
+ */
+ readPage(chunk) {
+ if (chunk.length < OGG_PAGE_HEADER_SIZE) {
+ return false;
+ }
+ if (!chunk.slice(0, 4).equals(OGGS_HEADER)) {
+ throw Error(`capture_pattern is not ${OGGS_HEADER}`);
+ }
+ if (chunk.readUInt8(4) !== STREAM_STRUCTURE_VERSION) {
+ throw Error(`stream_structure_version is not ${STREAM_STRUCTURE_VERSION}`);
+ }
+
+ const pageSegments = chunk.readUInt8(26),
+ table = chunk.slice(27, 27 + pageSegments);
+
+ let sizes = [], totalSize = 0;
+
+ for (let i = 0; i < pageSegments;) {
+ let size = 0, x = 255;
+ while (x === 255) {
+ x = table.readUInt8(i);
+ i++;
+ size += x;
+ }
+ sizes.push(size);
+ totalSize += size;
+ }
+
+ if (chunk.length < 27 + pageSegments + totalSize) {
+ return false;
+ }
+
+ let start = 27 + pageSegments;
+ for (const size of sizes) {
+ const segment = chunk.slice(start, start + size);
+ const header = segment.slice(0, 8);
+ if (this._head) {
+ if (header.equals(OPUS_TAGS)) this.emit('opusTags', segment);
+ else this.push(segment);
+ } else if (header.equals(OPUS_HEAD)) {
+ this._head = segment;
+ } else {
+ throw Error(`Invalid segment ${segment}`);
+ }
+ start += size;
+ }
+ return chunk.slice(start);
+ }
+}
+
+module.exports = OggOpusTransform;
diff --git a/node_modules/prism-media/src/transcoders/MediaTranscoder.js b/node_modules/prism-media/src/transcoders/MediaTranscoder.js
new file mode 100644
index 0000000..217e34c
--- /dev/null
+++ b/node_modules/prism-media/src/transcoders/MediaTranscoder.js
@@ -0,0 +1,31 @@
+const Ffmpeg = require('./ffmpeg/Ffmpeg');
+
+const transcoders = [
+ 'ffmpeg',
+];
+
+class MediaTranscoder {
+ constructor(prism) {
+ this.prism = prism;
+ this.ffmpeg = new Ffmpeg(this);
+ }
+
+ static verifyOptions(options) {
+ if (!options) throw new Error('Options must be passed to MediaTranscoder.transcode()');
+ if (!options.type) throw new Error('Options.type must be passed to MediaTranscoder.transcode()');
+ if (!transcoders.includes(options.type)) throw new Error(`Options.type must be: ${transcoders.join(' ')}`);
+ return options;
+ }
+
+ /**
+ * Transcodes a media stream based on specified options
+ * @param {Object} options the options to use when transcoding
+ * @returns {ReadableStream} the transcodeed stream
+ */
+ transcode(options) {
+ options = MediaTranscoder.verifyOptions(options);
+ return this[options.type].transcode(options);
+ }
+}
+
+module.exports = MediaTranscoder;
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;
diff --git a/node_modules/prism-media/src/util/Constants.js b/node_modules/prism-media/src/util/Constants.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/node_modules/prism-media/src/util/Constants.js