@ziplayer/ytexecplug 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { Readable } from "stream";
4
4
  /**
5
5
  * Converts a Web ReadableStream to a Node.js Readable stream
6
6
  */
7
- export declare function webStreamToNodeStream(webStream: ReadableStream): Readable;
7
+ export declare function webStreamToNodeStream(webStream: ReadableStream, highWaterMark?: number, seekBytes?: number): Promise<Readable>;
8
8
  export declare class YTexec extends BasePlugin {
9
9
  name: string;
10
10
  version: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,cAAc,GAAG,QAAQ,CA8BzE;AA0CD,qBAAa,MAAO,SAAQ,UAAU;IACrC,IAAI,SAAY;IAChB,OAAO,SAAW;IAElB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAe3B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIjE,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;CAqBlD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC;;GAEG;AACH,wBAAsB,qBAAqB,CAC1C,SAAS,EAAE,cAAc,EACzB,aAAa,GAAE,MAAkB,EACjC,SAAS,GAAE,MAAU,GACnB,OAAO,CAAC,QAAQ,CAAC,CAoEnB;AA0CD,qBAAa,MAAO,SAAQ,UAAU;IACrC,IAAI,SAAY;IAChB,OAAO,SAAW;IAElB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAe3B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIjE,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;CAqBlD"}
package/dist/index.js CHANGED
@@ -11,32 +11,67 @@ const youtube_dl_exec_1 = __importDefault(require("youtube-dl-exec"));
11
11
  /**
12
12
  * Converts a Web ReadableStream to a Node.js Readable stream
13
13
  */
14
- function webStreamToNodeStream(webStream) {
15
- const nodeStream = new stream_1.Readable({
16
- read() {
17
- // This will be handled by the Web Stream reader
18
- },
19
- });
20
- // Create a reader from the Web Stream
14
+ async function webStreamToNodeStream(webStream, highWaterMark = 64 * 1024, seekBytes = 0) {
21
15
  const reader = webStream.getReader();
22
- // Read chunks and push to Node.js stream
23
- const pump = async () => {
24
- try {
25
- while (true) {
26
- const { done, value } = await reader.read();
27
- if (done) {
28
- nodeStream.push(null); // End the stream
29
- break;
16
+ let bytesSkipped = 0;
17
+ let streamEnded = false;
18
+ const nodeStream = new stream_1.Readable({
19
+ highWaterMark,
20
+ async read() {
21
+ if (streamEnded) {
22
+ this.push(null);
23
+ return;
24
+ }
25
+ try {
26
+ while (true) {
27
+ const { done, value } = await reader.read();
28
+ if (done) {
29
+ streamEnded = true;
30
+ this.push(null);
31
+ break;
32
+ }
33
+ if (!value)
34
+ continue;
35
+ // Handle seek
36
+ if (seekBytes > 0 && bytesSkipped < seekBytes) {
37
+ const remaining = seekBytes - bytesSkipped;
38
+ if (value.length <= remaining) {
39
+ bytesSkipped += value.length;
40
+ continue;
41
+ }
42
+ else {
43
+ const partial = value.subarray(remaining);
44
+ bytesSkipped = seekBytes;
45
+ const buffer = Buffer.from(partial);
46
+ if (!this.push(buffer)) {
47
+ // Backpressure
48
+ break;
49
+ }
50
+ return;
51
+ }
52
+ }
53
+ const buffer = Buffer.from(value);
54
+ if (!this.push(buffer)) {
55
+ // Backpressure
56
+ break;
57
+ }
58
+ return;
30
59
  }
31
- nodeStream.push(Buffer.from(value));
32
60
  }
33
- }
34
- catch (error) {
35
- nodeStream.destroy(error);
36
- }
37
- };
38
- // Start pumping data
39
- pump();
61
+ catch (err) {
62
+ console.error("Stream read error:", err);
63
+ streamEnded = true;
64
+ this.destroy(err);
65
+ }
66
+ },
67
+ });
68
+ // Cleanup handlers
69
+ nodeStream.on("close", () => {
70
+ reader.releaseLock();
71
+ });
72
+ nodeStream.on("error", () => {
73
+ reader.releaseLock();
74
+ });
40
75
  return nodeStream;
41
76
  }
42
77
  function extractVideoId(input) {
@@ -80,11 +115,8 @@ async function getYoutubeStream(url) {
80
115
  return videourl;
81
116
  }
82
117
  class YTexec extends ziplayer_1.BasePlugin {
83
- constructor() {
84
- super(...arguments);
85
- this.name = "YTexec";
86
- this.version = "1.0.0";
87
- }
118
+ name = "YTexec";
119
+ version = "1.0.0";
88
120
  canHandle(query) {
89
121
  const q = (query || "").trim().toLowerCase();
90
122
  const isUrl = q.startsWith("http://") || q.startsWith("https://");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAQA,sDA8BC;AAtCD,uCAAsC;AAEtC,mCAAkC;AAClC,sEAAwC;AAExC;;GAEG;AACH,SAAgB,qBAAqB,CAAC,SAAyB;IAC9D,MAAM,UAAU,GAAG,IAAI,iBAAQ,CAAC;QAC/B,IAAI;YACH,gDAAgD;QACjD,CAAC;KACD,CAAC,CAAC;IAEH,sCAAsC;IACtC,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC;IAErC,yCAAyC;IACzC,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACvB,IAAI,CAAC;YACJ,OAAO,IAAI,EAAE,CAAC;gBACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI,EAAE,CAAC;oBACV,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB;oBACxC,MAAM;gBACP,CAAC;gBACD,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACrC,CAAC;QACF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,UAAU,CAAC,OAAO,CAAC,KAAc,CAAC,CAAC;QACpC,CAAC;IACF,CAAC,CAAC;IAEF,qBAAqB;IACrB,IAAI,EAAE,CAAC;IAEP,OAAO,UAAU,CAAC;AACnB,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACpC,IAAI,CAAC;QACJ,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,iBAAiB,GAAG,CAAC,UAAU,CAAC,CAAC;QACvC,MAAM,gBAAgB,GAAG,CAAC,aAAa,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,eAAe,CAAC,CAAC;QAClG,IAAI,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QACzD,CAAC;QACD,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3C,4BAA4B;YAC5B,IAAI,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,OAAO,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5D,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC;YACxB,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;gBAAE,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACrE,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,GAAG,GAAG,mBAAmB,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,MAAM,IAAA,yBAAS,EAAC,GAAG,EAAE;QACjC,cAAc,EAAE,IAAI;QACpB,mBAAmB,EAAE,IAAI;QACzB,UAAU,EAAE,IAAI;QAChB,iBAAiB,EAAE,IAAI;QACvB,MAAM,EAAE,gBAAgB;QACxB,SAAS,EAAE,CAAC,qBAAqB,EAAE,sBAAsB,CAAC;KAC1D,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAY,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACtE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACb,CAAC;IAED,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAa,MAAO,SAAQ,qBAAU;IAAtC;;QACC,SAAI,GAAG,QAAQ,CAAC;QAChB,YAAO,GAAG,OAAO,CAAC;IA0CnB,CAAC;IAxCA,SAAS,CAAC,KAAa;QACtB,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAClE,IAAI,KAAK,EAAE,CAAC;YACX,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC9B,MAAM,YAAY,GAAG,CAAC,aAAa,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;gBACzG,OAAO,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7D,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACZ,OAAO,KAAK,CAAC;YACd,CAAC;QACF,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,WAAmB;QAC9C,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,KAAY;QAC3B,IAAI,CAAC;YACJ,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACrD,IAAI,CAAC,UAAU,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACrD,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACnD,CAAC;YACD,MAAM,MAAM,GAAG,qBAAqB,CAAC,QAAQ,CAAC,IAAsB,CAAwB,CAAC;YAE7F,OAAO;gBACN,MAAM;gBACN,IAAI,EAAE,WAAW;gBACjB,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACxB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAC;QAC3D,CAAC;IACF,CAAC;CACD;AA5CD,wBA4CC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,38 +1,38 @@
1
- {
2
- "name": "@ziplayer/ytexecplug",
3
- "version": "0.0.2",
4
- "description": "A modular Discord voice player with plugin system",
5
- "keywords": [
6
- "ZiPlayer",
7
- "@ziplayer/plugin",
8
- "discord",
9
- "music",
10
- "player",
11
- "voice"
12
- ],
13
- "homepage": "https://player.ziji.world",
14
- "bugs": {
15
- "url": "https://github.com/ZiProject/ZiPlayer/issues"
16
- },
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/ZiProject/ZiPlayer.git"
20
- },
21
- "license": "MIT",
22
- "author": "Ziji",
23
- "main": "dist/index.js",
24
- "types": "dist/index.d.ts",
25
- "scripts": {
26
- "build": "tsc",
27
- "dev": "tsc --watch",
28
- "prepare": "npm run build"
29
- },
30
- "dependencies": {
31
- "youtube-dl-exec": "^3.1.1",
32
- "ziplayer": "^0.2.1"
33
- },
34
- "devDependencies": {
35
- "@types/node": "^20.0.0",
36
- "typescript": "^5.0.0"
37
- }
38
- }
1
+ {
2
+ "name": "@ziplayer/ytexecplug",
3
+ "version": "0.0.3",
4
+ "description": "A modular Discord voice player with plugin system",
5
+ "keywords": [
6
+ "ZiPlayer",
7
+ "@ziplayer/plugin",
8
+ "discord",
9
+ "music",
10
+ "player",
11
+ "voice"
12
+ ],
13
+ "homepage": "https://player.ziji.best",
14
+ "bugs": {
15
+ "url": "https://github.com/ZiProject/ZiPlayer/issues"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/ZiProject/ZiPlayer.git"
20
+ },
21
+ "license": "MIT",
22
+ "author": "Ziji",
23
+ "main": "dist/index.js",
24
+ "types": "dist/index.d.ts",
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "dev": "tsc --watch",
28
+ "prepare": "npm run build"
29
+ },
30
+ "dependencies": {
31
+ "youtube-dl-exec": "^3.1.1",
32
+ "ziplayer": "^0.2.1"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^20.0.0",
36
+ "typescript": "^5.0.0"
37
+ }
38
+ }
package/src/index.ts CHANGED
@@ -6,34 +6,76 @@ import youtubedl from "youtube-dl-exec";
6
6
  /**
7
7
  * Converts a Web ReadableStream to a Node.js Readable stream
8
8
  */
9
- export function webStreamToNodeStream(webStream: ReadableStream): Readable {
9
+ export async function webStreamToNodeStream(
10
+ webStream: ReadableStream,
11
+ highWaterMark: number = 64 * 1024,
12
+ seekBytes: number = 0,
13
+ ): Promise<Readable> {
14
+ const reader = webStream.getReader();
15
+ let bytesSkipped = 0;
16
+ let streamEnded = false;
17
+
10
18
  const nodeStream = new Readable({
11
- read() {
12
- // This will be handled by the Web Stream reader
13
- },
14
- });
19
+ highWaterMark,
20
+ async read() {
21
+ if (streamEnded) {
22
+ this.push(null);
23
+ return;
24
+ }
15
25
 
16
- // Create a reader from the Web Stream
17
- const reader = webStream.getReader();
26
+ try {
27
+ while (true) {
28
+ const { done, value } = await reader.read();
18
29
 
19
- // Read chunks and push to Node.js stream
20
- const pump = async () => {
21
- try {
22
- while (true) {
23
- const { done, value } = await reader.read();
24
- if (done) {
25
- nodeStream.push(null); // End the stream
26
- break;
30
+ if (done) {
31
+ streamEnded = true;
32
+ this.push(null);
33
+ break;
34
+ }
35
+
36
+ if (!value) continue;
37
+
38
+ // Handle seek
39
+ if (seekBytes > 0 && bytesSkipped < seekBytes) {
40
+ const remaining = seekBytes - bytesSkipped;
41
+ if (value.length <= remaining) {
42
+ bytesSkipped += value.length;
43
+ continue;
44
+ } else {
45
+ const partial = value.subarray(remaining);
46
+ bytesSkipped = seekBytes;
47
+ const buffer = Buffer.from(partial);
48
+ if (!this.push(buffer)) {
49
+ // Backpressure
50
+ break;
51
+ }
52
+ return;
53
+ }
54
+ }
55
+
56
+ const buffer = Buffer.from(value);
57
+ if (!this.push(buffer)) {
58
+ // Backpressure
59
+ break;
60
+ }
61
+ return;
27
62
  }
28
- nodeStream.push(Buffer.from(value));
63
+ } catch (err) {
64
+ console.error("Stream read error:", err);
65
+ streamEnded = true;
66
+ this.destroy(err as Error);
29
67
  }
30
- } catch (error) {
31
- nodeStream.destroy(error as Error);
32
- }
33
- };
68
+ },
69
+ });
70
+
71
+ // Cleanup handlers
72
+ nodeStream.on("close", () => {
73
+ reader.releaseLock();
74
+ });
34
75
 
35
- // Start pumping data
36
- pump();
76
+ nodeStream.on("error", () => {
77
+ reader.releaseLock();
78
+ });
37
79
 
38
80
  return nodeStream;
39
81
  }
package/tsconfig.json CHANGED
@@ -1,23 +1,27 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "commonjs",
5
- "lib": ["ES2020"],
6
- "outDir": "./dist",
7
- "rootDir": "./src",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "forceConsistentCasingInFileNames": true,
12
- "declaration": true,
13
- "declarationMap": true,
14
- "sourceMap": true,
15
- "moduleResolution": "node",
16
- "allowSyntheticDefaultImports": true,
17
- "experimentalDecorators": true,
18
- "emitDecoratorMetadata": true,
19
- "resolveJsonModule": true
20
- },
21
- "include": ["src/*", "src/types/*"],
22
- "exclude": ["node_modules", "dist", "examples"]
23
- }
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022", "DOM"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "allowSyntheticDefaultImports": true,
17
+ "experimentalDecorators": true,
18
+ "emitDecoratorMetadata": true,
19
+ "resolveJsonModule": true,
20
+ "paths": {
21
+ "googlevideo/sabr-stream": ["./node_modules/googlevideo/dist/src/exports/sabr-stream"],
22
+ "googlevideo/utils": ["./node_modules/googlevideo/dist/src/exports/utils"]
23
+ }
24
+ },
25
+ "include": ["src/*"],
26
+ "exclude": ["node_modules", "dist", "examples"]
27
+ }
@@ -1 +0,0 @@
1
- //# sourceMappingURL=YouTubePlugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"YouTubePlugin.d.ts","sourceRoot":"","sources":["../src/YouTubePlugin.ts"],"names":[],"mappings":""}
@@ -1,343 +0,0 @@
1
- "use strict";
2
- // import { BasePlugin, Track, SearchResult, StreamInfo, Player } from "ziplayer";
3
- // export interface PluginOptions {
4
- // player: Player;
5
- // debug?: boolean;
6
- // }
7
- // /**
8
- // * A plugin for handling YouTube audio content including videos, playlists, and search functionality.
9
- // *
10
- // * This plugin provides comprehensive support for:
11
- // * - YouTube video URLs (youtube.com, youtu.be, music.youtube.com)
12
- // * - YouTube playlist URLs and dynamic mixes
13
- // * - YouTube search queries
14
- // * - Audio stream extraction from YouTube videos
15
- // * - Related track recommendations
16
- // *
17
- // * @example
18
- // * const youtubePlugin = new YouTubePlugin();
19
- // *
20
- // * // Add to PlayerManager
21
- // * const manager = new PlayerManager({
22
- // * plugins: [youtubePlugin]
23
- // * });
24
- // *
25
- // * // Search for videos
26
- // * const result = await youtubePlugin.search("Never Gonna Give You Up", "user123");
27
- // *
28
- // * // Get audio stream
29
- // * const stream = await youtubePlugin.getStream(result.tracks[0]);
30
- // *
31
- // * @since 1.0.0
32
- // */
33
- // export class YouTubePlugin extends BasePlugin {
34
- // name = "youtube";
35
- // version = "1.0.0";
36
- // private ready: Promise<void>;
37
- // private player: Player | undefined;
38
- // private options: PluginOptions;
39
- // /**
40
- // * Creates a new YouTubePlugin instance.
41
- // *
42
- // * The plugin will automatically initialize YouTube clients for both video playback
43
- // * and search functionality. Initialization is asynchronous and handled internally.
44
- // *
45
- // * @example
46
- // * const plugin = new YouTubePlugin();
47
- // * // Plugin is ready to use after initialization completes
48
- // */
49
- // constructor(options: PluginOptions) {
50
- // super();
51
- // this.player = options?.player ?? undefined;
52
- // this.options = options ?? {};
53
- // this.ready = this.init();
54
- // }
55
- // private async init(): Promise<void> {}
56
- // private debug(message?: any, ...optionalParams: any[]): void {
57
- // if (this.options?.debug && this?.player && this.player?.listenerCount("debug") > 0) {
58
- // this.player.emit("debug", `[YouTubePlugin] ${message}`, ...optionalParams);
59
- // }
60
- // }
61
- // // Build a Track from various YouTube object shapes (search item, playlist item, watch_next feed, basic_info, info)
62
- // private buildTrack(raw: any, requestedBy: string, extra?: { playlist?: string }): Track {
63
- // const pickFirst = (...vals: any[]) => vals.find((v) => v !== undefined && v !== null && v !== "");
64
- // // Try to resolve from multiple common shapes
65
- // const id = pickFirst(
66
- // raw?.id,
67
- // raw?.video_id,
68
- // raw?.videoId,
69
- // raw?.content_id,
70
- // raw?.identifier,
71
- // raw?.basic_info?.id,
72
- // raw?.basic_info?.video_id,
73
- // raw?.basic_info?.videoId,
74
- // raw?.basic_info?.content_id,
75
- // );
76
- // const title = pickFirst(
77
- // raw?.metadata?.title?.text,
78
- // raw?.title?.text,
79
- // raw?.title,
80
- // raw?.headline,
81
- // raw?.basic_info?.title,
82
- // "Unknown title",
83
- // );
84
- // const durationValue = pickFirst(
85
- // raw?.length_seconds,
86
- // raw?.duration?.seconds,
87
- // raw?.duration?.text,
88
- // raw?.duration,
89
- // raw?.length_text,
90
- // raw?.basic_info?.duration,
91
- // );
92
- // const duration = Number(toSeconds(durationValue)) || 0;
93
- // const thumb = pickFirst(
94
- // raw?.thumbnails?.[0]?.url,
95
- // raw?.thumbnail?.[0]?.url,
96
- // raw?.thumbnail?.url,
97
- // raw?.thumbnail?.thumbnails?.[0]?.url,
98
- // raw?.content_image?.image?.[0]?.url,
99
- // raw?.basic_info?.thumbnail?.[0]?.url,
100
- // raw?.basic_info?.thumbnail?.[raw?.basic_info?.thumbnail?.length - 1]?.url,
101
- // raw?.thumbnails?.[raw?.thumbnails?.length - 1]?.url,
102
- // );
103
- // const author = pickFirst(raw?.author?.name, raw?.author, raw?.channel?.name, raw?.owner?.name, raw?.basic_info?.author);
104
- // const views = pickFirst(
105
- // raw?.view_count,
106
- // raw?.views,
107
- // raw?.short_view_count,
108
- // raw?.stats?.view_count,
109
- // raw?.basic_info?.view_count,
110
- // );
111
- // const url = pickFirst(raw?.url, id ? `https://www.youtube.com/watch?v=${id}` : undefined);
112
- // this.debug("Track build:", {
113
- // id: String(id),
114
- // title: String(title),
115
- // url: String(url),
116
- // duration,
117
- // thumbnail: thumb,
118
- // requestedBy,
119
- // source: this.name,
120
- // });
121
- // return {
122
- // id: String(id),
123
- // title: String(title),
124
- // url: String(url),
125
- // duration,
126
- // thumbnail: thumb,
127
- // requestedBy,
128
- // source: this.name,
129
- // metadata: {
130
- // author,
131
- // views,
132
- // ...(extra?.playlist ? { playlist: extra.playlist } : {}),
133
- // },
134
- // } as Track;
135
- // }
136
- // /**
137
- // * Determines if this plugin can handle the given query.
138
- // *
139
- // * @param query - The search query or URL to check
140
- // * @returns `true` if the plugin can handle the query, `false` otherwise
141
- // *
142
- // * @example
143
- // * plugin.canHandle("https://www.youtube.com/watch?v=dQw4w9WgXcQ"); // true
144
- // * plugin.canHandle("Never Gonna Give You Up"); // true
145
- // * plugin.canHandle("spotify:track:123"); // false
146
- // */
147
- // canHandle(query: string): boolean {
148
- // const q = (query || "").trim().toLowerCase();
149
- // const isUrl = q.startsWith("http://") || q.startsWith("https://");
150
- // if (isUrl) {
151
- // try {
152
- // const parsed = new URL(query);
153
- // const allowedHosts = ["youtube.com", "www.youtube.com", "music.youtube.com", "youtu.be", "www.youtu.be"];
154
- // return allowedHosts.includes(parsed.hostname.toLowerCase());
155
- // } catch (e) {
156
- // return false;
157
- // }
158
- // }
159
- // // Avoid intercepting explicit patterns for other extractors
160
- // if (q.startsWith("tts:") || q.startsWith("say ")) return false;
161
- // if (q.startsWith("spotify:") || q.includes("open.spotify.com")) return false;
162
- // if (q.includes("soundcloud")) return false;
163
- // // Treat remaining non-URL free text as YouTube-searchable
164
- // return true;
165
- // }
166
- // /**
167
- // * Validates if a URL is a valid YouTube URL.
168
- // *
169
- // * @param url - The URL to validate
170
- // * @returns `true` if the URL is a valid YouTube URL, `false` otherwise
171
- // *
172
- // * @example
173
- // * plugin.validate("https://www.youtube.com/watch?v=dQw4w9WgXcQ"); // true
174
- // * plugin.validate("https://youtu.be/dQw4w9WgXcQ"); // true
175
- // * plugin.validate("https://spotify.com/track/123"); // false
176
- // */
177
- // validate(url: string): boolean {
178
- // try {
179
- // const parsed = new URL(url);
180
- // const allowedHosts = ["youtube.com", "www.youtube.com", "music.youtube.com", "youtu.be", "www.youtu.be", "m.youtube.com"];
181
- // return allowedHosts.includes(parsed.hostname.toLowerCase());
182
- // } catch (e) {
183
- // return false;
184
- // }
185
- // }
186
- // /**
187
- // * Retrieves the audio stream for a YouTube track using sabr download.
188
- // *
189
- // * This method extracts the audio stream from a YouTube video using the sabr download
190
- // * method which provides better quality and more reliable streaming.
191
- // *
192
- // * @param track - The Track object to get the stream for
193
- // * @returns A StreamInfo object containing the audio stream and metadata
194
- // * @throws {Error} If the track ID is invalid or stream extraction fails
195
- // *
196
- // * @example
197
- // * const track = { id: "dQw4w9WgXcQ", title: "Never Gonna Give You Up", ... };
198
- // * const streamInfo = await plugin.getStream(track);
199
- // * console.log(streamInfo.type); // "arbitrary"
200
- // * console.log(streamInfo.stream); // Readable stream
201
- // */
202
- // async getStream(track: Track): Promise<StreamInfo> {
203
- // await this.ready;
204
- // const id = this.extractVideoId(track.url) || track.id;
205
- // if (!id) throw new Error("Invalid track id");
206
- // try {
207
- // this.debug("🚀 Attempting sabr download for video ID:", id);
208
- // // Use sabr download for better quality and reliability
209
- // const { streamResults } = await createSabrStream(id, DEFAULT_SABR_OPTIONS);
210
- // const { audioStream, selectedFormats, videoTitle } = streamResults;
211
- // this.debug("✅ Sabr download successful, converting Web Stream to Node.js Stream");
212
- // // Convert Web Stream to Node.js Readable Stream
213
- // const nodeStream = webStreamToNodeStream(audioStream);
214
- // this.debug("✅ Stream conversion complete, returning Node.js stream");
215
- // // Return the converted Node.js stream
216
- // return {
217
- // stream: nodeStream,
218
- // type: "arbitrary",
219
- // metadata: {
220
- // ...track.metadata,
221
- // itag: selectedFormats.audioFormat.itag,
222
- // mime: selectedFormats.audioFormat.mimeType,
223
- // },
224
- // };
225
- // } catch (e: any) {
226
- // this.debug("⚠️ Sabr download failed, falling back to youtubei.js:", e.message);
227
- // // Fallback to original youtubei.js method if sabr download fails
228
- // try {
229
- // const stream: any = await (this.client as any).download(id, {
230
- // type: "audio",
231
- // quality: "best",
232
- // });
233
- // // Check if it's a Web Stream and convert it
234
- // this.debug("🔍 Checking stream type:", typeof stream, stream?.constructor?.name);
235
- // if (stream && typeof stream.getReader === "function") {
236
- // this.debug("🔄 Converting Web Stream to Node.js Stream");
237
- // const nodeStream = webStreamToNodeStream(stream);
238
- // this.debug("✅ Stream converted successfully");
239
- // return {
240
- // stream: nodeStream,
241
- // type: "arbitrary",
242
- // metadata: track.metadata,
243
- // };
244
- // } else {
245
- // this.debug("⚠️ Stream is not a Web Stream or is null");
246
- // }
247
- // return {
248
- // stream,
249
- // type: "arbitrary",
250
- // metadata: track.metadata,
251
- // };
252
- // } catch (fallbackError: any) {
253
- // try {
254
- // const info: any = await (this.client as any).getBasicInfo(id);
255
- // // Prefer m4a audio-only formats first
256
- // let format: any = info?.chooseFormat?.({
257
- // type: "audio",
258
- // quality: "best",
259
- // });
260
- // if (!format && info?.formats?.length) {
261
- // const audioOnly = info.formats.filter((f: any) => f.mime_type?.includes("audio"));
262
- // audioOnly.sort((a: any, b: any) => (b.bitrate || 0) - (a.bitrate || 0));
263
- // format = audioOnly[0];
264
- // }
265
- // if (!format) throw new Error("No audio format available");
266
- // let url: string | undefined = undefined;
267
- // if (typeof format.decipher === "function") {
268
- // url = format.decipher((this.client as any).session.player);
269
- // }
270
- // if (!url) url = format.url;
271
- // if (!url) throw new Error("No valid URL to decipher");
272
- // const res = await fetch(url);
273
- // if (!res.ok || !res.body) {
274
- // throw new Error(`HTTP ${res.status}`);
275
- // }
276
- // // Convert Web Stream to Node.js Stream
277
- // this.debug("🔄 Converting fetch response Web Stream to Node.js Stream");
278
- // const nodeStream = webStreamToNodeStream(res.body);
279
- // return {
280
- // stream: nodeStream,
281
- // type: "arbitrary",
282
- // metadata: {
283
- // ...track.metadata,
284
- // itag: format.itag,
285
- // mime: format.mime_type,
286
- // },
287
- // };
288
- // } catch (inner: any) {
289
- // throw new Error(`Failed to get YouTube stream: ${inner?.message || inner}`);
290
- // }
291
- // }
292
- // }
293
- // }
294
- // async getFallback(track: Track): Promise<StreamInfo> {
295
- // try {
296
- // const result = await this.search(track.title, track.requestedBy);
297
- // const first = result.tracks[0];
298
- // this.debug("Fallback track:", first);
299
- // if (!first) throw new Error("No fallback track found");
300
- // return await this.getStream(first);
301
- // } catch (e: any) {
302
- // throw new Error(`YouTube fallback search failed: ${e?.message || e}`);
303
- // }
304
- // }
305
- // private extractVideoId(input: string): string | null {
306
- // try {
307
- // const u = new URL(input);
308
- // const allowedShortHosts = ["youtu.be"];
309
- // const allowedLongHosts = ["youtube.com", "www.youtube.com", "music.youtube.com", "m.youtube.com"];
310
- // if (allowedShortHosts.includes(u.hostname)) {
311
- // return u.pathname.split("/").filter(Boolean)[0] || null;
312
- // }
313
- // if (allowedLongHosts.includes(u.hostname)) {
314
- // // watch?v=, shorts/, embed/
315
- // if (u.searchParams.get("v")) return u.searchParams.get("v");
316
- // const path = u.pathname;
317
- // if (path.startsWith("/shorts/")) return path.replace("/shorts/", "");
318
- // if (path.startsWith("/embed/")) return path.replace("/embed/", "");
319
- // }
320
- // return null;
321
- // } catch {
322
- // return null;
323
- // }
324
- // }
325
- // }
326
- // function toSeconds(d: any): number | undefined {
327
- // if (typeof d === "number") return d;
328
- // if (typeof d === "string") {
329
- // // mm:ss or hh:mm:ss
330
- // const parts = d.split(":").map(Number);
331
- // if (parts.some((n) => Number.isNaN(n))) return undefined;
332
- // if (parts.length === 3) return parts[0] * 3600 + parts[1] * 60 + parts[2];
333
- // if (parts.length === 2) return parts[0] * 60 + parts[1];
334
- // const asNum = Number(d);
335
- // return Number.isFinite(asNum) ? asNum : undefined;
336
- // }
337
- // if (d && typeof d === "object") {
338
- // if (typeof (d as any).seconds === "number") return (d as any).seconds;
339
- // if (typeof (d as any).milliseconds === "number") return Math.floor((d as any).milliseconds / 1000);
340
- // }
341
- // return undefined;
342
- // }
343
- //# sourceMappingURL=YouTubePlugin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"YouTubePlugin.js","sourceRoot":"","sources":["../src/YouTubePlugin.ts"],"names":[],"mappings":"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"}