Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
v5.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
Snowflake107 committed May 5, 2021
1 parent b91f32d commit ee6926d
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 75 deletions.
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
test/
test/
index.ts
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"tabWidth": 4,
"useTabs": false,
"semi": true,
"printWidth": 80,
"singleQuote": true
}
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
Simple ytdl wrapper for discord bots with custom ffmpeg args support.

# Installing

| WARNING: To use `discord-ytdl-core`, you will need to install `ytdl-core` on your own (from v5.x). |
| --- |
> First of all, you need to install `ytdl-core` with `npm install --save ytdl-core`.
## Install ytdl core

Expand Down Expand Up @@ -246,6 +244,7 @@ Check out **[ytdl-core](https://npmjs.com/package/ytdl-core)** for other functio
[![](https://www.paypalobjects.com/webstatic/icon/pp258.png)](https://paypal.me/devsnowflake)

# Related
- **[youtube-sr](https://npmjs.com/package/youtube-sr)**
- **[ytdl-core-discord](https://npmjs.com/package/ytdl-core-discord)**
- **[discord-player](https://npmjs.com/discord-player)**

Expand Down
174 changes: 106 additions & 68 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,83 @@
import ytdl, { downloadOptions } from "ytdl-core";
import { opus as Opus, FFmpeg } from "prism-media";
import { Readable, Duplex } from "stream";
import ytdl, { downloadOptions } from 'ytdl-core';
import { opus as Opus, FFmpeg } from 'prism-media';
import { Readable, Duplex } from 'stream';

// ytdl events
const evn = ["info", "progress", "abort", "request", "response", "error", "redirect", "retry", "reconnect"];
const evn = [
'info',
'progress',
'abort',
'request',
'response',
'error',
'redirect',
'retry',
'reconnect',
];

interface YTDLStreamOptions extends downloadOptions {
seek?: number;
encoderArgs?: string[];
fmt?: string;
opusEncoded?: boolean;
};
}

interface StreamOptions {
seek?: number;
encoderArgs?: string[];
fmt?: string;
opusEncoded?: boolean;
};
}

/**
* Create an opus stream for your video with provided encoder args
* @param url - YouTube URL of the video
* @param options - YTDL options
* @example const ytdl = require("discord-ytdl-core");
* const stream = ytdl("VIDEO_URL", {
* seek: 3,
* encoderArgs: ["-af", "bass=g=10"],
* opusEncoded: true
* });
* VoiceConnection.play(stream, {
* type: "opus"
* });
*/
const StreamDownloader = (url: string, options: YTDLStreamOptions) => {
* Create an opus stream for your video with provided encoder args
* @param url - YouTube URL of the video
* @param options - YTDL options
* @example const ytdl = require("discord-ytdl-core");
* const stream = ytdl("VIDEO_URL", {
* seek: 3,
* encoderArgs: ["-af", "bass=g=10"],
* opusEncoded: true
* });
* VoiceConnection.play(stream, {
* type: "opus"
* });
*/
const StreamDownloader = (url: string, options?: YTDLStreamOptions) => {
if (!url) {
throw new Error("No input url provided");
throw new Error('No input url provided');
}
if (typeof url !== "string") {
throw new SyntaxError(`input URL must be a string. Received ${typeof url}!`);
if (typeof url !== 'string') {
throw new SyntaxError(
`input URL must be a string. Received ${typeof url}!`
);
}

options ??= {};

let FFmpegArgs: string[] = [
"-analyzeduration", "0",
"-loglevel", "0",
"-f", `${options && options.fmt && typeof (options.fmt) == "string" ? options.fmt : "s16le"}`,
"-ar", "48000",
"-ac", "2"
'-analyzeduration',
'0',
'-loglevel',
'0',
'-f',
`${typeof options.fmt === 'string' ? options.fmt : 's16le'}`,
'-ar',
'48000',
'-ac',
'2',
];

if (options && options.seek && !isNaN(options.seek)) {
FFmpegArgs.unshift("-ss", options.seek.toString());
if (!isNaN(options.seek)) {
FFmpegArgs.unshift('-ss', options.seek.toString());
}

if (options && options.encoderArgs && Array.isArray(options.encoderArgs)) {
if (Array.isArray(options.encoderArgs)) {
FFmpegArgs = FFmpegArgs.concat(options.encoderArgs);
}

const transcoder = new FFmpeg({
args: FFmpegArgs
args: FFmpegArgs,
});

const inputStream = ytdl(url, options);
Expand All @@ -67,26 +86,26 @@ const StreamDownloader = (url: string, options: YTDLStreamOptions) => {
for (const event of evn) {
inputStream.on(event, (...args) => output.emit(event, ...args));
}
inputStream.on("error", () => transcoder.destroy());
output.on("close", () => transcoder.destroy());
inputStream.on('error', () => transcoder.destroy());
output.on('close', () => transcoder.destroy());
return output;
};
}

const opus = new Opus.Encoder({
rate: 48000,
channels: 2,
frameSize: 960
frameSize: 960,
});

const outputStream = output.pipe(opus);

output.on('error', e => outputStream.emit('error', e));
output.on('error', (e) => outputStream.emit('error', e));

for (const event of evn) {
inputStream.on(event, (...args) => outputStream.emit(event, ...args));
}

outputStream.on("close", () => {
outputStream.on('close', () => {
transcoder.destroy();
opus.destroy();
});
Expand All @@ -102,73 +121,92 @@ const StreamDownloader = (url: string, options: YTDLStreamOptions) => {
* encoderArgs: ["-af", "asetrate=44100*1.25"],
* fmt: "mp3"
* });
*
*
* stream.pipe(fs.createWriteStream("kpop.mp3"));
*/
const arbitraryStream = (stream: string | Readable | Duplex, options: StreamOptions) => {
const arbitraryStream = (
stream: string | Readable | Duplex,
options?: StreamOptions
) => {
if (!stream) {
throw new Error("No stream source provided");
throw new Error('No stream source provided');
}

options ??= {};

let FFmpegArgs: string[];
if (typeof stream === "string") {
if (typeof stream === 'string') {
FFmpegArgs = [
'-reconnect', '1',
'-reconnect_streamed', '1',
'-reconnect_delay_max', '5',
"-i", stream,
"-analyzeduration", "0",
"-loglevel", "0",
"-f", `${options && options.fmt && typeof (options.fmt) == "string" ? options.fmt : "s16le"}`,
"-ar", "48000",
"-ac", "2"
'-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", `${options && options.fmt && typeof (options.fmt) == "string" ? options.fmt : "s16le"}`,
"-ar", "48000",
"-ac", "2"
'-analyzeduration',
'0',
'-loglevel',
'0',
'-f',
`${typeof options.fmt === 'string' ? options.fmt : 's16le'}`,
'-ar',
'48000',
'-ac',
'2',
];
}

if (options && options.seek && !isNaN(options.seek)) {
FFmpegArgs.unshift("-ss", options.seek.toString());
if (!isNaN(options.seek)) {
FFmpegArgs.unshift('-ss', options.seek.toString());
}

if (options && options.encoderArgs && Array.isArray(options.encoderArgs)) {
if (Array.isArray(options.encoderArgs)) {
FFmpegArgs = FFmpegArgs.concat(options.encoderArgs);
}

let transcoder = new FFmpeg({
args: FFmpegArgs
args: FFmpegArgs,
});
if (typeof stream !== "string") {
if (typeof stream !== 'string') {
transcoder = stream.pipe(transcoder);
stream.on("error", () => transcoder.destroy());
stream.on('error', () => transcoder.destroy());
}
if (options && !options.opusEncoded) {
transcoder.on("close", () => transcoder.destroy());
transcoder.on('close', () => transcoder.destroy());
return transcoder;
};
}
const opus = new Opus.Encoder({
rate: 48000,
channels: 2,
frameSize: 960
frameSize: 960,
});

const outputStream = transcoder.pipe(opus);
outputStream.on("close", () => {
outputStream.on('close', () => {
transcoder.destroy();
opus.destroy();
});
return outputStream;
};

StreamDownloader.arbitraryStream = arbitraryStream;
StreamDownloader.version = require("./package.json").version;
StreamDownloader.version = require('./package.json').version;

const DiscordYTDLCore = Object.assign(StreamDownloader, ytdl);

export = DiscordYTDLCore;
export = DiscordYTDLCore;
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "discord-ytdl-core",
"version": "5.0.2",
"version": "5.0.3",
"description": "Simple ytdl wrapper for discord bots with custom ffmpeg args support.",
"main": "index.js",
"types": "index.d.ts",
Expand Down Expand Up @@ -49,10 +49,11 @@
},
"homepage": "https://ytdl.snowflakedev.xyz",
"dependencies": {
"prism-media": "^1.2.7"
"prism-media": "^1.2.9"
},
"devDependencies": {
"@types/node": "^14.14.31",
"discord.js": "^12.5.3",
"ffmpeg-static": "^4.2.6",
"node-opus": "^0.3.2",
"ytdl-core": "^4.5.0"
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "ES2020",
"target": "ES6",
"declaration": false,
"strict": true,
"strictNullChecks": false,
Expand Down

0 comments on commit ee6926d

Please sign in to comment.