@ziplayer/plugin 0.1.33 → 0.1.40
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/README.md +180 -180
- package/YTSR_README.md +310 -310
- package/dist/TTSPlugin.js.map +1 -1
- package/dist/YTSRPlugin.d.ts.map +1 -1
- package/dist/YTSRPlugin.js +17 -1
- package/dist/YTSRPlugin.js.map +1 -1
- package/dist/YouTubePlugin.d.ts +15 -6
- package/dist/YouTubePlugin.d.ts.map +1 -1
- package/dist/YouTubePlugin.js +122 -47
- package/dist/YouTubePlugin.js.map +1 -1
- package/dist/utils/progress-bar.d.ts +8 -0
- package/dist/utils/progress-bar.d.ts.map +1 -0
- package/dist/utils/progress-bar.js +24 -0
- package/dist/utils/progress-bar.js.map +1 -0
- package/dist/utils/sabr-stream-factory.d.ts +25 -0
- package/dist/utils/sabr-stream-factory.d.ts.map +1 -0
- package/dist/utils/sabr-stream-factory.js +83 -0
- package/dist/utils/sabr-stream-factory.js.map +1 -0
- package/dist/utils/stream-converter.d.ts +10 -0
- package/dist/utils/stream-converter.d.ts.map +1 -0
- package/dist/utils/stream-converter.js +78 -0
- package/dist/utils/stream-converter.js.map +1 -0
- package/package.json +44 -42
- package/src/SoundCloudPlugin.ts +368 -368
- package/src/SpotifyPlugin.ts +312 -312
- package/src/TTSPlugin.ts +361 -361
- package/src/YTSRPlugin.ts +596 -583
- package/src/YouTubePlugin.ts +620 -528
- package/src/index.ts +103 -103
- package/src/types/googlevideo.d.ts +45 -0
- package/src/utils/sabr-stream-factory.ts +96 -0
- package/src/utils/stream-converter.ts +87 -0
- package/tsconfig.json +23 -23
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_SABR_OPTIONS = void 0;
|
|
4
|
+
exports.createSabrStream = createSabrStream;
|
|
5
|
+
exports.createOutputStream = createOutputStream;
|
|
6
|
+
exports.createStreamSink = createStreamSink;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const os_1 = require("os");
|
|
10
|
+
/**
|
|
11
|
+
* Creates a sabr stream for YouTube video download
|
|
12
|
+
*/
|
|
13
|
+
async function createSabrStream(videoId, options) {
|
|
14
|
+
try {
|
|
15
|
+
// Dynamic import to avoid build-time errors
|
|
16
|
+
const sabrModule = require("googlevideo/sabr-stream");
|
|
17
|
+
const createSabrStreamImpl = sabrModule.createSabrStream;
|
|
18
|
+
const streamResults = await createSabrStreamImpl(videoId, options);
|
|
19
|
+
return { streamResults };
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
// Fallback implementation if sabr download is not available
|
|
23
|
+
throw new Error(`Sabr download not available: ${error}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Creates an output stream for writing downloaded content
|
|
28
|
+
*/
|
|
29
|
+
function createOutputStream(videoTitle, mimeType) {
|
|
30
|
+
const sanitizedTitle = videoTitle.replace(/[<>:"/\\|?*]/g, "_").substring(0, 100);
|
|
31
|
+
const extension = getExtensionFromMimeType(mimeType);
|
|
32
|
+
const fileName = `${sanitizedTitle}.${extension}`;
|
|
33
|
+
const filePath = (0, path_1.join)((0, os_1.tmpdir)(), fileName);
|
|
34
|
+
const stream = (0, fs_1.createWriteStream)(filePath);
|
|
35
|
+
return {
|
|
36
|
+
stream,
|
|
37
|
+
filePath,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a stream sink for piping data with progress tracking
|
|
42
|
+
*/
|
|
43
|
+
function createStreamSink(format, outputStream, progressBar) {
|
|
44
|
+
return new WritableStream({
|
|
45
|
+
start() {
|
|
46
|
+
// Initialize progress tracking
|
|
47
|
+
},
|
|
48
|
+
write(chunk) {
|
|
49
|
+
outputStream.write(chunk);
|
|
50
|
+
if (progressBar) {
|
|
51
|
+
progressBar.increment(chunk.length);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
close() {
|
|
55
|
+
outputStream.end();
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Gets file extension from MIME type
|
|
61
|
+
*/
|
|
62
|
+
function getExtensionFromMimeType(mimeType) {
|
|
63
|
+
const mimeMap = {
|
|
64
|
+
"audio/mp4": "m4a",
|
|
65
|
+
"audio/webm": "webm",
|
|
66
|
+
"audio/ogg": "ogg",
|
|
67
|
+
"video/mp4": "mp4",
|
|
68
|
+
"video/webm": "webm",
|
|
69
|
+
"video/ogg": "ogv",
|
|
70
|
+
};
|
|
71
|
+
return mimeMap[mimeType] || "bin";
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Default sabr playback options
|
|
75
|
+
*/
|
|
76
|
+
exports.DEFAULT_SABR_OPTIONS = {
|
|
77
|
+
preferWebM: true,
|
|
78
|
+
preferOpus: true,
|
|
79
|
+
videoQuality: "720p",
|
|
80
|
+
audioQuality: "AUDIO_QUALITY_MEDIUM",
|
|
81
|
+
enabledTrackTypes: "VIDEO_AND_AUDIO",
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=sabr-stream-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sabr-stream-factory.js","sourceRoot":"","sources":["../../src/utils/sabr-stream-factory.ts"],"names":[],"mappings":";;;AAkBA,4CAaC;AAKD,gDAYC;AAKD,4CAeC;AApED,2BAAuC;AACvC,+BAA4B;AAC5B,2BAA4B;AAa5B;;GAEG;AACI,KAAK,UAAU,gBAAgB,CAAC,OAAe,EAAE,OAA4B;IACnF,IAAI,CAAC;QACJ,4CAA4C;QAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,yBAAyB,CAAQ,CAAC;QAC7D,MAAM,oBAAoB,GAAG,UAAU,CAAC,gBAAgB,CAAC;QAEzD,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEnE,OAAO,EAAE,aAAa,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,4DAA4D;QAC5D,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,EAAE,CAAC,CAAC;IAC1D,CAAC;AACF,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,UAAkB,EAAE,QAAgB;IACtE,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClF,MAAM,SAAS,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,GAAG,cAAc,IAAI,SAAS,EAAE,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,IAAA,WAAM,GAAE,EAAE,QAAQ,CAAC,CAAC;IAE1C,MAAM,MAAM,GAAG,IAAA,sBAAiB,EAAC,QAAQ,CAAC,CAAC;IAE3C,OAAO;QACN,MAAM;QACN,QAAQ;KACR,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,MAAW,EAAE,YAAmC,EAAE,WAAgB;IAClG,OAAO,IAAI,cAAc,CAAC;QACzB,KAAK;YACJ,+BAA+B;QAChC,CAAC;QACD,KAAK,CAAC,KAAK;YACV,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,WAAW,EAAE,CAAC;gBACjB,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;QACF,CAAC;QACD,KAAK;YACJ,YAAY,CAAC,GAAG,EAAE,CAAC;QACpB,CAAC;KACD,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAAC,QAAgB;IACjD,MAAM,OAAO,GAA8B;QAC1C,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,KAAK;KAClB,CAAC;IAEF,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC;AACnC,CAAC;AAED;;GAEG;AACU,QAAA,oBAAoB,GAAwB;IACxD,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,MAAM;IACpB,YAAY,EAAE,sBAAsB;IACpC,iBAAiB,EAAE,iBAAiB;CACpC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Readable } from "stream";
|
|
2
|
+
/**
|
|
3
|
+
* Converts a Web ReadableStream to a Node.js Readable stream
|
|
4
|
+
*/
|
|
5
|
+
export declare function webStreamToNodeStream(webStream: ReadableStream): Readable;
|
|
6
|
+
/**
|
|
7
|
+
* Converts a Web ReadableStream to a Node.js Readable stream with progress tracking
|
|
8
|
+
*/
|
|
9
|
+
export declare function webStreamToNodeStreamWithProgress(webStream: ReadableStream, progressCallback?: (bytesRead: number) => void): Readable;
|
|
10
|
+
//# sourceMappingURL=stream-converter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-converter.d.ts","sourceRoot":"","sources":["../../src/utils/stream-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,cAAc,GAAG,QAAQ,CAsCzE;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAChD,SAAS,EAAE,cAAc,EACzB,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GAC5C,QAAQ,CAmCV"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.webStreamToNodeStream = webStreamToNodeStream;
|
|
4
|
+
exports.webStreamToNodeStreamWithProgress = webStreamToNodeStreamWithProgress;
|
|
5
|
+
const stream_1 = require("stream");
|
|
6
|
+
/**
|
|
7
|
+
* Converts a Web ReadableStream to a Node.js Readable stream
|
|
8
|
+
*/
|
|
9
|
+
function webStreamToNodeStream(webStream) {
|
|
10
|
+
console.log("🔄 webStreamToNodeStream: Starting conversion");
|
|
11
|
+
const nodeStream = new stream_1.Readable({
|
|
12
|
+
read() {
|
|
13
|
+
// This will be handled by the Web Stream reader
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
// Create a reader from the Web Stream
|
|
17
|
+
const reader = webStream.getReader();
|
|
18
|
+
console.log("🔄 webStreamToNodeStream: Got reader");
|
|
19
|
+
// Read chunks and push to Node.js stream
|
|
20
|
+
const pump = async () => {
|
|
21
|
+
try {
|
|
22
|
+
console.log("🔄 webStreamToNodeStream: Starting pump");
|
|
23
|
+
while (true) {
|
|
24
|
+
const { done, value } = await reader.read();
|
|
25
|
+
if (done) {
|
|
26
|
+
console.log("🔄 webStreamToNodeStream: Stream ended");
|
|
27
|
+
nodeStream.push(null); // End the stream
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
console.log(`🔄 webStreamToNodeStream: Pushing chunk of ${value.length} bytes`);
|
|
31
|
+
nodeStream.push(Buffer.from(value));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error("🔄 webStreamToNodeStream: Error in pump:", error);
|
|
36
|
+
nodeStream.destroy(error);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
// Start pumping data
|
|
40
|
+
pump();
|
|
41
|
+
console.log("🔄 webStreamToNodeStream: Conversion complete, returning Node.js stream");
|
|
42
|
+
return nodeStream;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Converts a Web ReadableStream to a Node.js Readable stream with progress tracking
|
|
46
|
+
*/
|
|
47
|
+
function webStreamToNodeStreamWithProgress(webStream, progressCallback) {
|
|
48
|
+
const nodeStream = new stream_1.Readable({
|
|
49
|
+
read() {
|
|
50
|
+
// This will be handled by the Web Stream reader
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
let bytesRead = 0;
|
|
54
|
+
const reader = webStream.getReader();
|
|
55
|
+
const pump = async () => {
|
|
56
|
+
try {
|
|
57
|
+
while (true) {
|
|
58
|
+
const { done, value } = await reader.read();
|
|
59
|
+
if (done) {
|
|
60
|
+
nodeStream.push(null); // End the stream
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
const buffer = Buffer.from(value);
|
|
64
|
+
nodeStream.push(buffer);
|
|
65
|
+
bytesRead += buffer.length;
|
|
66
|
+
if (progressCallback) {
|
|
67
|
+
progressCallback(bytesRead);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
nodeStream.destroy(error);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
pump();
|
|
76
|
+
return nodeStream;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=stream-converter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-converter.js","sourceRoot":"","sources":["../../src/utils/stream-converter.ts"],"names":[],"mappings":";;AAKA,sDAsCC;AAKD,8EAsCC;AAtFD,mCAAkC;AAElC;;GAEG;AACH,SAAgB,qBAAqB,CAAC,SAAyB;IAC9D,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAE7D,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;IACrC,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;IAEpD,yCAAyC;IACzC,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACvB,IAAI,CAAC;YACJ,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;YACvD,OAAO,IAAI,EAAE,CAAC;gBACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI,EAAE,CAAC;oBACV,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;oBACtD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB;oBACxC,MAAM;gBACP,CAAC;gBACD,OAAO,CAAC,GAAG,CAAC,8CAA8C,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;gBAChF,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACrC,CAAC;QACF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;YACjE,UAAU,CAAC,OAAO,CAAC,KAAc,CAAC,CAAC;QACpC,CAAC;IACF,CAAC,CAAC;IAEF,qBAAqB;IACrB,IAAI,EAAE,CAAC;IAEP,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IACvF,OAAO,UAAU,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAgB,iCAAiC,CAChD,SAAyB,EACzB,gBAA8C;IAE9C,MAAM,UAAU,GAAG,IAAI,iBAAQ,CAAC;QAC/B,IAAI;YACH,gDAAgD;QACjD,CAAC;KACD,CAAC,CAAC;IAEH,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC;IAErC,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;gBAED,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAClC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAExB,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC;gBAC3B,IAAI,gBAAgB,EAAE,CAAC;oBACtB,gBAAgB,CAAC,SAAS,CAAC,CAAC;gBAC7B,CAAC;YACF,CAAC;QACF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,UAAU,CAAC,OAAO,CAAC,KAAc,CAAC,CAAC;QACpC,CAAC;IACF,CAAC,CAAC;IAEF,IAAI,EAAE,CAAC;IAEP,OAAO,UAAU,CAAC;AACnB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,42 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@ziplayer/plugin",
|
|
3
|
-
"version": "0.1.
|
|
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
|
-
"@zibot/scdl": "^0.0.5",
|
|
32
|
-
"@zibot/zitts": "^0.0.3",
|
|
33
|
-
"axios": "^1.12.2",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@ziplayer/plugin",
|
|
3
|
+
"version": "0.1.40",
|
|
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
|
+
"@zibot/scdl": "^0.0.5",
|
|
32
|
+
"@zibot/zitts": "^0.0.3",
|
|
33
|
+
"axios": "^1.12.2",
|
|
34
|
+
"cli-progress": "^3.12.0",
|
|
35
|
+
"googlevideo": "^1.0.0",
|
|
36
|
+
"youtube-sr": "^4.3.4",
|
|
37
|
+
"youtubei.js": "^16.0.1",
|
|
38
|
+
"ziplayer": "^0.1.2"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^20.0.0",
|
|
42
|
+
"typescript": "^5.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|