@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/src/index.ts CHANGED
@@ -1,103 +1,103 @@
1
- /**
2
- * @fileoverview Main export file for ZiPlayer plugins.
3
- *
4
- * This module exports all available plugins for the ZiPlayer music bot framework.
5
- * Each plugin provides support for different audio sources and services.
6
- *
7
- * @example
8
- * import { YouTubePlugin, SoundCloudPlugin, SpotifyPlugin, TTSPlugin } from "ziplayer/plugins";
9
- *
10
- * const manager = new PlayerManager({
11
- * plugins: [
12
- * new YouTubePlugin(),
13
- * new SoundCloudPlugin(),
14
- * new SpotifyPlugin(),
15
- * new TTSPlugin({ defaultLang: "en" })
16
- * ]
17
- * });
18
- *
19
- * @since 1.0.0
20
- */
21
-
22
- /**
23
- * YouTube plugin for handling YouTube videos, playlists, and search.
24
- *
25
- * Provides comprehensive support for YouTube content including:
26
- * - Video URLs (youtube.com, youtu.be, music.youtube.com)
27
- * - Playlist URLs and dynamic mixes
28
- * - Search functionality
29
- * - Audio stream extraction
30
- * - Related track recommendations
31
- *
32
- * @example
33
- * const youtubePlugin = new YouTubePlugin();
34
- * const result = await youtubePlugin.search("Never Gonna Give You Up", "user123");
35
- */
36
- export { YouTubePlugin } from "./YouTubePlugin";
37
-
38
- /**
39
- * SoundCloud plugin for handling SoundCloud tracks, playlists, and search.
40
- *
41
- * Provides comprehensive support for SoundCloud content including:
42
- * - Track URLs (soundcloud.com)
43
- * - Playlist URLs
44
- * - Search functionality
45
- * - Audio stream extraction
46
- * - Related track recommendations
47
- *
48
- * @example
49
- * const soundcloudPlugin = new SoundCloudPlugin();
50
- * const result = await soundcloudPlugin.search("chill music", "user123");
51
- */
52
- export { SoundCloudPlugin } from "./SoundCloudPlugin";
53
-
54
- /**
55
- * Spotify plugin for metadata extraction and display purposes.
56
- *
57
- * **Note:** This plugin only provides metadata extraction and does not support
58
- * audio streaming. It uses Spotify's public oEmbed endpoint for display purposes.
59
- *
60
- * Provides support for:
61
- * - Track URLs/URIs (spotify:track:...)
62
- * - Playlist URLs/URIs (spotify:playlist:...)
63
- * - Album URLs/URIs (spotify:album:...)
64
- * - Metadata extraction using oEmbed API
65
- *
66
- * @example
67
- * const spotifyPlugin = new SpotifyPlugin();
68
- * const result = await spotifyPlugin.search("spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "user123");
69
- */
70
- export { SpotifyPlugin } from "./SpotifyPlugin";
71
-
72
- /**
73
- * Text-to-Speech (TTS) plugin for converting text to audio.
74
- *
75
- * Provides comprehensive TTS functionality including:
76
- * - Google TTS integration
77
- * - Custom TTS provider support
78
- * - Multiple language support
79
- * - Configurable speech rate
80
- * - Flexible query parsing
81
- *
82
- * @example
83
- * const ttsPlugin = new TTSPlugin({ defaultLang: "en" });
84
- * const result = await ttsPlugin.search("tts:Hello world", "user123");
85
- */
86
- export { TTSPlugin } from "./TTSPlugin";
87
-
88
- /**
89
- * YTSR plugin for advanced YouTube search without streaming.
90
- *
91
- * Provides comprehensive YouTube search functionality including:
92
- * - Advanced video search with filters (duration, upload date, sort by)
93
- * - Playlist and channel search
94
- * - Multiple search types (video, playlist, channel, all)
95
- * - Metadata extraction without streaming
96
- * - Support for YouTube URLs
97
- *
98
- * @example
99
- * const ytsrPlugin = new YTSRPlugin();
100
- * const result = await ytsrPlugin.search("Never Gonna Give You Up", "user123");
101
- * const playlistResult = await ytsrPlugin.searchPlaylist("chill music", "user123");
102
- */
103
- export { YTSRPlugin } from "./YTSRPlugin";
1
+ /**
2
+ * @fileoverview Main export file for ZiPlayer plugins.
3
+ *
4
+ * This module exports all available plugins for the ZiPlayer music bot framework.
5
+ * Each plugin provides support for different audio sources and services.
6
+ *
7
+ * @example
8
+ * import { YouTubePlugin, SoundCloudPlugin, SpotifyPlugin, TTSPlugin } from "ziplayer/plugins";
9
+ *
10
+ * const manager = new PlayerManager({
11
+ * plugins: [
12
+ * new YouTubePlugin(),
13
+ * new SoundCloudPlugin(),
14
+ * new SpotifyPlugin(),
15
+ * new TTSPlugin({ defaultLang: "en" })
16
+ * ]
17
+ * });
18
+ *
19
+ * @since 1.0.0
20
+ */
21
+
22
+ /**
23
+ * YouTube plugin for handling YouTube videos, playlists, and search.
24
+ *
25
+ * Provides comprehensive support for YouTube content including:
26
+ * - Video URLs (youtube.com, youtu.be, music.youtube.com)
27
+ * - Playlist URLs and dynamic mixes
28
+ * - Search functionality
29
+ * - Audio stream extraction
30
+ * - Related track recommendations
31
+ *
32
+ * @example
33
+ * const youtubePlugin = new YouTubePlugin();
34
+ * const result = await youtubePlugin.search("Never Gonna Give You Up", "user123");
35
+ */
36
+ export { YouTubePlugin } from "./YouTubePlugin";
37
+
38
+ /**
39
+ * SoundCloud plugin for handling SoundCloud tracks, playlists, and search.
40
+ *
41
+ * Provides comprehensive support for SoundCloud content including:
42
+ * - Track URLs (soundcloud.com)
43
+ * - Playlist URLs
44
+ * - Search functionality
45
+ * - Audio stream extraction
46
+ * - Related track recommendations
47
+ *
48
+ * @example
49
+ * const soundcloudPlugin = new SoundCloudPlugin();
50
+ * const result = await soundcloudPlugin.search("chill music", "user123");
51
+ */
52
+ export { SoundCloudPlugin } from "./SoundCloudPlugin";
53
+
54
+ /**
55
+ * Spotify plugin for metadata extraction and display purposes.
56
+ *
57
+ * **Note:** This plugin only provides metadata extraction and does not support
58
+ * audio streaming. It uses Spotify's public oEmbed endpoint for display purposes.
59
+ *
60
+ * Provides support for:
61
+ * - Track URLs/URIs (spotify:track:...)
62
+ * - Playlist URLs/URIs (spotify:playlist:...)
63
+ * - Album URLs/URIs (spotify:album:...)
64
+ * - Metadata extraction using oEmbed API
65
+ *
66
+ * @example
67
+ * const spotifyPlugin = new SpotifyPlugin();
68
+ * const result = await spotifyPlugin.search("spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "user123");
69
+ */
70
+ export { SpotifyPlugin } from "./SpotifyPlugin";
71
+
72
+ /**
73
+ * Text-to-Speech (TTS) plugin for converting text to audio.
74
+ *
75
+ * Provides comprehensive TTS functionality including:
76
+ * - Google TTS integration
77
+ * - Custom TTS provider support
78
+ * - Multiple language support
79
+ * - Configurable speech rate
80
+ * - Flexible query parsing
81
+ *
82
+ * @example
83
+ * const ttsPlugin = new TTSPlugin({ defaultLang: "en" });
84
+ * const result = await ttsPlugin.search("tts:Hello world", "user123");
85
+ */
86
+ export { TTSPlugin } from "./TTSPlugin";
87
+
88
+ /**
89
+ * YTSR plugin for advanced YouTube search without streaming.
90
+ *
91
+ * Provides comprehensive YouTube search functionality including:
92
+ * - Advanced video search with filters (duration, upload date, sort by)
93
+ * - Playlist and channel search
94
+ * - Multiple search types (video, playlist, channel, all)
95
+ * - Metadata extraction without streaming
96
+ * - Support for YouTube URLs
97
+ *
98
+ * @example
99
+ * const ytsrPlugin = new YTSRPlugin();
100
+ * const result = await ytsrPlugin.search("Never Gonna Give You Up", "user123");
101
+ * const playlistResult = await ytsrPlugin.searchPlaylist("chill music", "user123");
102
+ */
103
+ export { YTSRPlugin } from "./YTSRPlugin";
@@ -0,0 +1,45 @@
1
+ export interface SabrPlaybackOptions {
2
+ preferWebM?: boolean;
3
+ preferOpus?: boolean;
4
+ videoQuality?: string;
5
+ audioQuality?: string;
6
+ enabledTrackTypes?: any;
7
+ }
8
+
9
+ export interface StreamResult {
10
+ videoStream: ReadableStream;
11
+ audioStream: ReadableStream;
12
+ selectedFormats: {
13
+ videoFormat: any;
14
+ audioFormat: any;
15
+ };
16
+ videoTitle: string;
17
+ }
18
+
19
+ declare module "googlevideo/sabr-stream" {
20
+ export interface SabrPlaybackOptions {
21
+ preferWebM?: boolean;
22
+ preferOpus?: boolean;
23
+ videoQuality?: string;
24
+ audioQuality?: string;
25
+ enabledTrackTypes?: any;
26
+ }
27
+
28
+ export interface StreamResult {
29
+ videoStream: ReadableStream;
30
+ audioStream: ReadableStream;
31
+ selectedFormats: {
32
+ videoFormat: any;
33
+ audioFormat: any;
34
+ };
35
+ videoTitle: string;
36
+ }
37
+
38
+ export function createSabrStream(videoId: string, options: SabrPlaybackOptions): Promise<{ streamResults: StreamResult }>;
39
+ }
40
+
41
+ declare module "googlevideo/utils" {
42
+ export enum EnabledTrackTypes {
43
+ VIDEO_AND_AUDIO = "VIDEO_AND_AUDIO",
44
+ }
45
+ }
@@ -0,0 +1,96 @@
1
+ import { createWriteStream } from "fs";
2
+ import { join } from "path";
3
+ import { tmpdir } from "os";
4
+
5
+ // Import type declarations
6
+ import type { SabrPlaybackOptions, StreamResult } from "../types/googlevideo";
7
+
8
+ // Re-export types for external use
9
+ export type { StreamResult, SabrPlaybackOptions };
10
+
11
+ export interface OutputStream {
12
+ stream: NodeJS.WritableStream;
13
+ filePath: string;
14
+ }
15
+
16
+ /**
17
+ * Creates a sabr stream for YouTube video download
18
+ */
19
+ export async function createSabrStream(videoId: string, options: SabrPlaybackOptions): Promise<{ streamResults: StreamResult }> {
20
+ try {
21
+ // Dynamic import to avoid build-time errors
22
+ const sabrModule = require("googlevideo/sabr-stream") as any;
23
+ const createSabrStreamImpl = sabrModule.createSabrStream;
24
+
25
+ const streamResults = await createSabrStreamImpl(videoId, options);
26
+
27
+ return { streamResults };
28
+ } catch (error) {
29
+ // Fallback implementation if sabr download is not available
30
+ throw new Error(`Sabr download not available: ${error}`);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Creates an output stream for writing downloaded content
36
+ */
37
+ export function createOutputStream(videoTitle: string, mimeType: string): OutputStream {
38
+ const sanitizedTitle = videoTitle.replace(/[<>:"/\\|?*]/g, "_").substring(0, 100);
39
+ const extension = getExtensionFromMimeType(mimeType);
40
+ const fileName = `${sanitizedTitle}.${extension}`;
41
+ const filePath = join(tmpdir(), fileName);
42
+
43
+ const stream = createWriteStream(filePath);
44
+
45
+ return {
46
+ stream,
47
+ filePath,
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Creates a stream sink for piping data with progress tracking
53
+ */
54
+ export function createStreamSink(format: any, outputStream: NodeJS.WritableStream, progressBar: any) {
55
+ return new WritableStream({
56
+ start() {
57
+ // Initialize progress tracking
58
+ },
59
+ write(chunk) {
60
+ outputStream.write(chunk);
61
+ if (progressBar) {
62
+ progressBar.increment(chunk.length);
63
+ }
64
+ },
65
+ close() {
66
+ outputStream.end();
67
+ },
68
+ });
69
+ }
70
+
71
+ /**
72
+ * Gets file extension from MIME type
73
+ */
74
+ function getExtensionFromMimeType(mimeType: string): string {
75
+ const mimeMap: { [key: string]: string } = {
76
+ "audio/mp4": "m4a",
77
+ "audio/webm": "webm",
78
+ "audio/ogg": "ogg",
79
+ "video/mp4": "mp4",
80
+ "video/webm": "webm",
81
+ "video/ogg": "ogv",
82
+ };
83
+
84
+ return mimeMap[mimeType] || "bin";
85
+ }
86
+
87
+ /**
88
+ * Default sabr playback options
89
+ */
90
+ export const DEFAULT_SABR_OPTIONS: SabrPlaybackOptions = {
91
+ preferWebM: true,
92
+ preferOpus: true,
93
+ videoQuality: "720p",
94
+ audioQuality: "AUDIO_QUALITY_MEDIUM",
95
+ enabledTrackTypes: "VIDEO_AND_AUDIO",
96
+ };
@@ -0,0 +1,87 @@
1
+ import { Readable } from "stream";
2
+
3
+ /**
4
+ * Converts a Web ReadableStream to a Node.js Readable stream
5
+ */
6
+ export function webStreamToNodeStream(webStream: ReadableStream): Readable {
7
+ console.log("🔄 webStreamToNodeStream: Starting conversion");
8
+
9
+ const nodeStream = new Readable({
10
+ read() {
11
+ // This will be handled by the Web Stream reader
12
+ },
13
+ });
14
+
15
+ // Create a reader from the Web Stream
16
+ const reader = webStream.getReader();
17
+ console.log("🔄 webStreamToNodeStream: Got reader");
18
+
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
+ } catch (error) {
34
+ console.error("🔄 webStreamToNodeStream: Error in pump:", error);
35
+ nodeStream.destroy(error as Error);
36
+ }
37
+ };
38
+
39
+ // Start pumping data
40
+ pump();
41
+
42
+ console.log("🔄 webStreamToNodeStream: Conversion complete, returning Node.js stream");
43
+ return nodeStream;
44
+ }
45
+
46
+ /**
47
+ * Converts a Web ReadableStream to a Node.js Readable stream with progress tracking
48
+ */
49
+ export function webStreamToNodeStreamWithProgress(
50
+ webStream: ReadableStream,
51
+ progressCallback?: (bytesRead: number) => void,
52
+ ): Readable {
53
+ const nodeStream = new Readable({
54
+ read() {
55
+ // This will be handled by the Web Stream reader
56
+ },
57
+ });
58
+
59
+ let bytesRead = 0;
60
+ const reader = webStream.getReader();
61
+
62
+ const pump = async () => {
63
+ try {
64
+ while (true) {
65
+ const { done, value } = await reader.read();
66
+ if (done) {
67
+ nodeStream.push(null); // End the stream
68
+ break;
69
+ }
70
+
71
+ const buffer = Buffer.from(value);
72
+ nodeStream.push(buffer);
73
+
74
+ bytesRead += buffer.length;
75
+ if (progressCallback) {
76
+ progressCallback(bytesRead);
77
+ }
78
+ }
79
+ } catch (error) {
80
+ nodeStream.destroy(error as Error);
81
+ }
82
+ };
83
+
84
+ pump();
85
+
86
+ return nodeStream;
87
+ }
package/tsconfig.json CHANGED
@@ -1,23 +1,23 @@
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/*"],
22
- "exclude": ["node_modules", "dist", "examples"]
23
- }
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
+ }