ziplayer 0.2.7 → 0.3.1

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.
Files changed (63) hide show
  1. package/AI-Guide.md +624 -956
  2. package/README.md +277 -10
  3. package/dist/extensions/BaseExtension.d.ts +1 -0
  4. package/dist/extensions/BaseExtension.d.ts.map +1 -1
  5. package/dist/extensions/BaseExtension.js.map +1 -1
  6. package/dist/extensions/index.d.ts +38 -3
  7. package/dist/extensions/index.d.ts.map +1 -1
  8. package/dist/extensions/index.js +259 -41
  9. package/dist/extensions/index.js.map +1 -1
  10. package/dist/persistence/PersistenceManager.d.ts +95 -0
  11. package/dist/persistence/PersistenceManager.d.ts.map +1 -0
  12. package/dist/persistence/PersistenceManager.js +975 -0
  13. package/dist/persistence/PersistenceManager.js.map +1 -0
  14. package/dist/plugins/BasePlugin.js +1 -1
  15. package/dist/plugins/BasePlugin.js.map +1 -1
  16. package/dist/plugins/index.d.ts +74 -8
  17. package/dist/plugins/index.d.ts.map +1 -1
  18. package/dist/plugins/index.js +657 -116
  19. package/dist/plugins/index.js.map +1 -1
  20. package/dist/structures/FilterManager.js +3 -3
  21. package/dist/structures/FilterManager.js.map +1 -1
  22. package/dist/structures/PersistenceManager.d.ts +96 -0
  23. package/dist/structures/PersistenceManager.d.ts.map +1 -0
  24. package/dist/structures/PersistenceManager.js +1008 -0
  25. package/dist/structures/PersistenceManager.js.map +1 -0
  26. package/dist/structures/Player.d.ts +158 -14
  27. package/dist/structures/Player.d.ts.map +1 -1
  28. package/dist/structures/Player.js +1175 -188
  29. package/dist/structures/Player.js.map +1 -1
  30. package/dist/structures/PlayerManager.d.ts +106 -91
  31. package/dist/structures/PlayerManager.d.ts.map +1 -1
  32. package/dist/structures/PlayerManager.js +365 -124
  33. package/dist/structures/PlayerManager.js.map +1 -1
  34. package/dist/structures/Queue.d.ts +136 -31
  35. package/dist/structures/Queue.d.ts.map +1 -1
  36. package/dist/structures/Queue.js +265 -46
  37. package/dist/structures/Queue.js.map +1 -1
  38. package/dist/structures/StreamManager.d.ts +137 -0
  39. package/dist/structures/StreamManager.d.ts.map +1 -0
  40. package/dist/structures/StreamManager.js +420 -0
  41. package/dist/structures/StreamManager.js.map +1 -0
  42. package/dist/types/index.d.ts +181 -8
  43. package/dist/types/index.d.ts.map +1 -1
  44. package/dist/types/index.js.map +1 -1
  45. package/dist/types/persistence.d.ts +77 -0
  46. package/dist/types/persistence.d.ts.map +1 -0
  47. package/dist/types/persistence.js +3 -0
  48. package/dist/types/persistence.js.map +1 -0
  49. package/package.json +3 -2
  50. package/src/extensions/BaseExtension.ts +1 -0
  51. package/src/extensions/index.ts +320 -37
  52. package/src/plugins/BasePlugin.ts +1 -1
  53. package/src/plugins/index.ts +809 -139
  54. package/src/structures/FilterManager.ts +3 -3
  55. package/src/structures/Player.ts +2810 -1693
  56. package/src/structures/PlayerManager.ts +438 -129
  57. package/src/structures/Queue.ts +300 -55
  58. package/src/structures/StreamManager.ts +524 -0
  59. package/src/types/extension.ts +129 -129
  60. package/src/types/fillter.ts +264 -264
  61. package/src/types/index.ts +187 -12
  62. package/src/types/plugin.ts +59 -59
  63. package/tsconfig.json +0 -1
@@ -3,7 +3,7 @@ import { Player } from "../structures/Player";
3
3
  import type { PlayerManager } from "../structures/PlayerManager";
4
4
  import type { AudioFilter } from "./fillter";
5
5
  import type { SourcePluginLike } from "./plugin";
6
-
6
+ import type { AudioResource } from "@discordjs/voice";
7
7
  /**
8
8
  * Represents a music track with metadata and streaming information.
9
9
  *
@@ -60,6 +60,7 @@ export interface Track {
60
60
  requestedBy: string;
61
61
  source: string;
62
62
  metadata?: Record<string, any>;
63
+ isLive?: boolean;
63
64
  }
64
65
 
65
66
  /**
@@ -88,11 +89,20 @@ export interface SearchResult {
88
89
  tracks: Track[];
89
90
  playlist?: {
90
91
  name: string;
91
- url: string;
92
+ url?: string;
92
93
  thumbnail?: string;
93
- };
94
+ } | null;
95
+ query?: string;
96
+ score?: SearchScore;
97
+ source?: string;
94
98
  }
95
99
 
100
+ export interface SearchScore {
101
+ score: number; // 0-100
102
+ reason: string; // Lý do đạt điểm
103
+ matchedBy: "url" | "title" | "partial" | "none" | "playlist";
104
+ exactMatch: boolean;
105
+ }
96
106
  /**
97
107
  * Contains streaming information for audio playback.
98
108
  *
@@ -129,7 +139,7 @@ export interface StreamInfo {
129
139
  * createPlayer: true,
130
140
  * interrupt: true,
131
141
  * volume: 1.0,
132
- * Max_Time_TTS: 30000
142
+ * maxTimeTts: 30000
133
143
  * }
134
144
  * };
135
145
  */
@@ -160,7 +170,7 @@ export interface PlayerOptions {
160
170
  /** Default TTS volume multiplier 1 => 100% */
161
171
  volume?: number;
162
172
  /** Max time tts playback Duration */
163
- Max_Time_TTS?: number;
173
+ maxTimeTts?: number;
164
174
  };
165
175
  /**
166
176
  * Optional per-player extension selection. When provided, only these
@@ -177,16 +187,131 @@ export interface PlayerOptions {
177
187
  * - Multiple filters can be combined
178
188
  */
179
189
  filters?: (string | AudioFilter)[];
190
+ /**
191
+ * Enable low performance mode.
192
+ * When enabled, heavy features such as preload and crossfade can be auto-disabled.
193
+ */
194
+ lowPerformance?: boolean;
195
+ /**
196
+ * Preload behavior configuration.
197
+ */
198
+ preload?: {
199
+ /**
200
+ * Enable/disable preload explicitly.
201
+ * Default: true
202
+ */
203
+ enabled?: boolean;
204
+ /**
205
+ * Auto disable preload when lowPerformance is enabled.
206
+ * Default: true
207
+ */
208
+ autoDisableInLowPerformance?: boolean;
209
+ };
210
+ /**
211
+ * Crossfade behavior configuration.
212
+ */
213
+ crossfade?: {
214
+ /**
215
+ * Enable/disable crossfade explicitly.
216
+ * If omitted and autoEnable=true, ZiPlayer may enable it automatically.
217
+ */
218
+ enabled?: boolean;
219
+ /**
220
+ * Auto enable crossfade if runtime profile allows.
221
+ * Default: true
222
+ */
223
+ autoEnable?: boolean;
224
+ /**
225
+ * Auto disable crossfade when lowPerformance is enabled.
226
+ * Default: true
227
+ */
228
+ autoDisableInLowPerformance?: boolean;
229
+ /**
230
+ * Target crossfade duration in milliseconds.
231
+ * Default: 5000
232
+ */
233
+ durationMs?: number;
234
+ };
235
+ /**
236
+ * Smart transition engine settings.
237
+ */
238
+ smartTransition?: {
239
+ enabled?: boolean;
240
+ /**
241
+ * Prefer genre-aware fade duration when metadata.genre is available.
242
+ */
243
+ genreAware?: boolean;
244
+ /**
245
+ * Try to align transition with beat boundary using metadata.bpm.
246
+ */
247
+ beatAlign?: boolean;
248
+ /**
249
+ * Base duration in milliseconds when no specific profile matched.
250
+ */
251
+ baseDurationMs?: number;
252
+ minDurationMs?: number;
253
+ maxDurationMs?: number;
254
+ /**
255
+ * Genre profiles in milliseconds (e.g. chill, edm, pop, rock).
256
+ */
257
+ genreDurations?: Record<string, number>;
258
+ /**
259
+ * Max wait time while trying to align to beat boundary.
260
+ */
261
+ beatAlignMaxWaitMs?: number;
262
+ };
263
+ /**
264
+ * Recovery strategy for stream/player failures.
265
+ */
266
+ antiStuck?: {
267
+ enabled?: boolean;
268
+ maxRetries?: number;
269
+ retryDelayMs?: number;
270
+ /**
271
+ * Reuse preload/current cached stream before hard retries.
272
+ */
273
+ reusePreloadFirst?: boolean;
274
+ /**
275
+ * Temporarily force low quality during retry attempts.
276
+ */
277
+ reduceQualityOnRetry?: boolean;
278
+ /**
279
+ * If consecutive failures exceed this threshold, allow skipping track.
280
+ */
281
+ controlledSkipThreshold?: number;
282
+ };
283
+ /**
284
+ * Loudness normalization and limiter.
285
+ */
286
+ loudnessNormalization?: {
287
+ enabled?: boolean;
288
+ /**
289
+ * Target LUFS (integrated). Track metadata.lufs is used if available.
290
+ */
291
+ targetLUFS?: number;
292
+ /**
293
+ * Cap gain boost to avoid over-amplification.
294
+ */
295
+ maxBoostDb?: number;
296
+ /**
297
+ * Cap attenuation.
298
+ */
299
+ maxCutDb?: number;
300
+ /**
301
+ * Output ceiling multiplier (<= 1.0), acts as soft limiter ceiling.
302
+ */
303
+ limiterCeiling?: number;
304
+ };
180
305
  }
181
306
 
182
307
  export interface PlayerManagerOptions {
183
308
  plugins?: SourcePluginLike[];
184
309
  extensions?: any[];
185
- /**
186
- * Timeout in milliseconds for manager-level operations (e.g. search)
187
- * when running without a Player instance.
188
- */
189
310
  extractorTimeout?: number;
311
+ autoCleanup?: boolean; // Auto cleanup inactive players
312
+ cleanupInterval?: number; // Cleanup interval in ms
313
+ enableSearchCache?: boolean; // Enable search result caching
314
+ enableStatsCollection?: boolean; // Enable stats collection events
190
315
  }
191
316
 
192
317
  /**
@@ -200,9 +325,13 @@ export interface PlayerManagerOptions {
200
325
  * };
201
326
  */
202
327
  export interface ProgressBarOptions {
203
- size?: number;
204
- barChar?: string;
205
- progressChar?: string;
328
+ size?: number; // Bar length (default: 20)
329
+ barChar?: string; // Character for empty bar (default: "▬")
330
+ progressChar?: string; // Character for progress pointer (default: "🔘")
331
+ timeFormat?: "compact" | "full"; // Time format style (default: "compact")
332
+ showPercentage?: boolean; // Show percentage at end (default: false)
333
+ showTime?: boolean; // Show time labels (default: true)
334
+ hideProgressChar?: boolean; // Hide progress character (default: false)
206
335
  }
207
336
 
208
337
  /**
@@ -229,6 +358,46 @@ export interface SaveOptions {
229
358
  /** Seek position in milliseconds to start saving from */
230
359
  seek?: number;
231
360
  }
361
+ export interface PlayerSession {
362
+ guildId: string;
363
+ queue: Track[];
364
+ currentTrack: Track | null;
365
+ volume: number;
366
+ loopMode: LoopMode;
367
+ autoPlay: boolean;
368
+ position: number | null;
369
+ extensions: string[];
370
+ plugins: string[];
371
+ userdata?: Record<string, any>;
372
+ }
373
+
374
+ export interface PreloadState {
375
+ resource: AudioResource | null;
376
+ track: Track | null;
377
+ abortController: AbortController | null;
378
+ timeoutId: NodeJS.Timeout | null;
379
+ isValid: boolean;
380
+ streamId?: string;
381
+ isBeingUsed: boolean;
382
+ }
383
+
384
+ export interface PlayerStats {
385
+ totalPlayers: number;
386
+ activePlayers: number;
387
+ pausedPlayers: number;
388
+ connectedPlayers: number;
389
+ totalTracksInQueue: number;
390
+ }
391
+
392
+ export interface StreamSlot {
393
+ resource: AudioResource | null;
394
+ track: Track | null;
395
+ streamId: string | null;
396
+ abortController: AbortController | null;
397
+ isValid: boolean;
398
+ isLoading: boolean;
399
+ loadPromise: Promise<void> | null;
400
+ }
232
401
 
233
402
  export type LoopMode = "off" | "track" | "queue";
234
403
 
@@ -337,6 +506,8 @@ export interface ManagerEvents {
337
506
  lyricsCreate: [player: Player, track: Track, lyrics: any];
338
507
  lyricsChange: [player: Player, track: Track, lyrics: any];
339
508
  voiceCreate: [player: Player, evt: any];
509
+ stats: [stats: PlayerStats];
510
+ streamError: [error: Error, track: Track | null];
340
511
  }
341
512
  export interface PlayerEvents {
342
513
  debug: [message: string, ...args: any[]];
@@ -366,6 +537,10 @@ export interface PlayerEvents {
366
537
  filterRemoved: [filter: AudioFilter];
367
538
  /** Emitted when all filters are cleared */
368
539
  filtersCleared: [];
540
+ trackStuck: [track: Track | null];
541
+ streamError: [error: Error, track: Track | null];
542
+ /** Emitted when player stats are updated (if enabled) */
543
+ stats: [stats: PlayerStats];
369
544
  }
370
545
 
371
546
  export * from "./fillter";
@@ -1,59 +1,59 @@
1
- import type { SearchResult, StreamInfo, Track } from ".";
2
- /**
3
- * Plugin interface
4
- *
5
- * @example
6
- * const plugin: SourcePlugin = {
7
- * name: "YouTube",
8
- * version: "1.0.0"
9
- * priority: 0, // Optional, default is 0. Lower priority plugins are tried first in getStream fallback.
10
- * };
11
- */
12
- export interface SourcePlugin {
13
- name: string;
14
- version: string;
15
- priority?: number;
16
- canHandle(query: string): boolean;
17
- search(query: string, requestedBy: string): Promise<SearchResult>;
18
- getStream(track: Track): Promise<StreamInfo>;
19
- getRelatedTracks?(track: Track, opts?: { limit?: number; offset?: number }): Promise<Track[]>;
20
- validate?(url: string): boolean;
21
- extractPlaylist?(url: string, requestedBy: string): Promise<Track[]>;
22
- }
23
-
24
- /**
25
- * Constructor for a SourcePlugin
26
- *
27
- * @example
28
- * const plugin = new YouTubePlugin();
29
- * console.log(`Plugin: ${plugin.name}`);
30
- */
31
- export type SourcePluginCtor<T extends SourcePlugin = SourcePlugin> = new (...args: any[]) => T;
32
-
33
- /**
34
- * SourcePlugin or SourcePluginCtor
35
- *
36
- * @example
37
- * const plugin = new YouTubePlugin();
38
- * console.log(`Plugin: ${plugin.name}`);
39
- */
40
- export type SourcePluginLike = SourcePlugin | SourcePluginCtor;
41
-
42
- /**
43
- * Configuration options for creating a PlayerManager instance.
44
- *
45
- * @example
46
- * const managerOptions: PlayerManagerOptions = {
47
- * plugins: [
48
- * new YouTubePlugin(),
49
- * new SoundCloudPlugin(),
50
- * new SpotifyPlugin(),
51
- * new TTSPlugin({ defaultLang: "en" })
52
- * ],
53
- * extensions: [
54
- * new voiceExt(null, { lang: "en-US" }),
55
- * new lavalinkExt(null, { nodes: [...] })
56
- * ],
57
- * extractorTimeout: 10000
58
- * };
59
- */
1
+ import type { SearchResult, StreamInfo, Track } from ".";
2
+ /**
3
+ * Plugin interface
4
+ *
5
+ * @example
6
+ * const plugin: SourcePlugin = {
7
+ * name: "YouTube",
8
+ * version: "1.0.0"
9
+ * priority: 0, // Optional, default is 0. Lower priority plugins are tried first in getStream fallback.
10
+ * };
11
+ */
12
+ export interface SourcePlugin {
13
+ name: string;
14
+ version: string;
15
+ priority?: number; // Higher = run first, default is 0. Lower priority plugins are tried first in getStream fallback.
16
+ canHandle(query: string): boolean;
17
+ search(query: string, requestedBy: string): Promise<SearchResult>;
18
+ getStream(track: Track): Promise<StreamInfo>;
19
+ getRelatedTracks?(track: Track, opts?: { limit?: number; offset?: number }): Promise<Track[]>;
20
+ validate?(url: string): boolean;
21
+ extractPlaylist?(url: string, requestedBy: string): Promise<Track[]>;
22
+ }
23
+
24
+ /**
25
+ * Constructor for a SourcePlugin
26
+ *
27
+ * @example
28
+ * const plugin = new YouTubePlugin();
29
+ * console.log(`Plugin: ${plugin.name}`);
30
+ */
31
+ export type SourcePluginCtor<T extends SourcePlugin = SourcePlugin> = new (...args: any[]) => T;
32
+
33
+ /**
34
+ * SourcePlugin or SourcePluginCtor
35
+ *
36
+ * @example
37
+ * const plugin = new YouTubePlugin();
38
+ * console.log(`Plugin: ${plugin.name}`);
39
+ */
40
+ export type SourcePluginLike = SourcePlugin | SourcePluginCtor;
41
+
42
+ /**
43
+ * Configuration options for creating a PlayerManager instance.
44
+ *
45
+ * @example
46
+ * const managerOptions: PlayerManagerOptions = {
47
+ * plugins: [
48
+ * new YouTubePlugin(),
49
+ * new SoundCloudPlugin(),
50
+ * new SpotifyPlugin(),
51
+ * new TTSPlugin({ defaultLang: "en" })
52
+ * ],
53
+ * extensions: [
54
+ * new voiceExt(null, { lang: "en-US" }),
55
+ * new lavalinkExt(null, { nodes: [...] })
56
+ * ],
57
+ * extractorTimeout: 10000
58
+ * };
59
+ */
package/tsconfig.json CHANGED
@@ -12,7 +12,6 @@
12
12
  "declaration": true,
13
13
  "declarationMap": true,
14
14
  "sourceMap": true,
15
- "moduleResolution": "node",
16
15
  "allowSyntheticDefaultImports": true,
17
16
  "experimentalDecorators": true,
18
17
  "emitDecoratorMetadata": true,