1
0
mirror of https://github.com/musix-org/musix-oss synced 2025-06-16 18:56:00 +00:00
This commit is contained in:
MatteZ02
2019-05-30 12:06:47 +03:00
parent cbdffcf19c
commit 5eb0264906
2502 changed files with 360854 additions and 0 deletions

17
node_modules/prism-media/src/Prism.js generated vendored Normal file
View File

@ -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;

6
node_modules/prism-media/src/index.js generated vendored Normal file
View File

@ -0,0 +1,6 @@
const Prism = require('./Prism');
const MediaTranscoder = require('./transcoders/MediaTranscoder');
Prism.MediaTranscoder = MediaTranscoder;
module.exports = Prism;

90
node_modules/prism-media/src/opus/OggOpus.js generated vendored Normal file
View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,51 @@
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 {
return require('ffmpeg-binaries');
} catch (err) {
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;

View File

@ -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;

0
node_modules/prism-media/src/util/Constants.js generated vendored Normal file
View File