UNPKG

@spikebot/discord-ytdl-core

Version:

Simple ytdl wrapper for discord bots with custom ffmpeg args support.

166 lines (165 loc) 5.02 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; const ytdl_core_1 = __importDefault(require("@spikebot/ytdl-core")); const prism_media_1 = require("prism-media"); // ytdl events const evn = [ 'info', 'progress', 'abort', 'request', 'response', 'error', 'redirect', 'retry', 'reconnect', ]; /** * Create an opus stream for your video with provided encoder args * @param url - YouTube URL of the video * @param options - YTDL options * @example */ const StreamDownloader = (url, options) => { if (!url) { throw new Error('No input url provided'); } if (typeof url !== 'string') { throw new SyntaxError(`input URL must be a string. Received ${typeof url}!`); } options !== null && options !== void 0 ? options : (options = {}); let FFmpegArgs = [ '-analyzeduration', '0', '-loglevel', '0', '-f', `${typeof options.fmt === 'string' ? options.fmt : 's16le'}`, '-ar', '48000', '-ac', '2', ]; if (!isNaN(options.seek)) { FFmpegArgs.unshift('-ss', options.seek.toString()); } if (Array.isArray(options.encoderArgs)) { FFmpegArgs = FFmpegArgs.concat(options.encoderArgs); } const transcoder = new prism_media_1.FFmpeg({ args: FFmpegArgs, }); const inputStream = (0, ytdl_core_1.default)(url, options); const output = inputStream.pipe(transcoder); if (options && !options.opusEncoded) { for (const event of evn) { inputStream.on(event, (...args) => output.emit(event, ...args)); } inputStream.on('error', () => transcoder.destroy()); output.on('close', () => transcoder.destroy()); return output; } const opus = new prism_media_1.opus.Encoder({ rate: 48000, channels: 2, frameSize: 960, }); const outputStream = output.pipe(opus); output.on('error', (e) => outputStream.emit('error', e)); for (const event of evn) { inputStream.on(event, (...args) => outputStream.emit(event, ...args)); } outputStream.on('close', () => { transcoder.destroy(); opus.destroy(); }); return outputStream; }; /** * Creates arbitraryStream * @param stream Any readable stream source * @param options Stream options * @example const streamSource = "https://listen.moe/kpop/opus"; * let stream = ytdl.arbitraryStream(streamSource, { * encoderArgs: ["-af", "asetrate=44100*1.25"], * fmt: "mp3" * }); * * stream.pipe(fs.createWriteStream("kpop.mp3")); */ const arbitraryStream = (stream, options) => { if (!stream) { throw new Error('No stream source provided'); } options !== null && options !== void 0 ? options : (options = {}); let FFmpegArgs; if (typeof stream === 'string') { FFmpegArgs = [ '-reconnect', '1', '-reconnect_streamed', '1', '-reconnect_delay_max', '5', '-i', stream, '-analyzeduration', '0', '-loglevel', '0', '-f', `${typeof options.fmt === 'string' ? options.fmt : 's16le'}`, '-ar', '48000', '-ac', '2', ]; } else { FFmpegArgs = [ '-analyzeduration', '0', '-loglevel', '0', '-f', `${typeof options.fmt === 'string' ? options.fmt : 's16le'}`, '-ar', '48000', '-ac', '2', ]; } if (!isNaN(options.seek)) { FFmpegArgs.unshift('-ss', options.seek.toString()); } if (Array.isArray(options.encoderArgs)) { FFmpegArgs = FFmpegArgs.concat(options.encoderArgs); } let transcoder = new prism_media_1.FFmpeg({ args: FFmpegArgs, }); if (typeof stream !== 'string') { transcoder = stream.pipe(transcoder); stream.on('error', () => transcoder.destroy()); } if (options && !options.opusEncoded) { transcoder.on('close', () => transcoder.destroy()); return transcoder; } const opus = new prism_media_1.opus.Encoder({ rate: 48000, channels: 2, frameSize: 960, }); const outputStream = transcoder.pipe(opus); outputStream.on('close', () => { transcoder.destroy(); opus.destroy(); }); return outputStream; }; StreamDownloader.arbitraryStream = arbitraryStream; StreamDownloader.version = require('./package.json').version; const DiscordYTDLCore = Object.assign(StreamDownloader, ytdl_core_1.default); module.exports = DiscordYTDLCore;