streamify-audio 2.3.0 → 2.3.2

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 (39) hide show
  1. package/index.d.ts +9 -0
  2. package/package.json +1 -1
  3. package/src/config.js +11 -0
  4. package/src/discord/Manager.js +1 -1
  5. package/src/discord/Stream.js +9 -12
  6. package/src/providers/spotify.js +2 -2
  7. package/docs/README.md +0 -31
  8. package/docs/automation.md +0 -186
  9. package/docs/configuration.md +0 -198
  10. package/docs/discord/events.md +0 -206
  11. package/docs/discord/manager.md +0 -195
  12. package/docs/discord/player.md +0 -263
  13. package/docs/discord/queue.md +0 -197
  14. package/docs/examples/advanced-bot.md +0 -391
  15. package/docs/examples/basic-bot.md +0 -182
  16. package/docs/examples/lavalink.md +0 -156
  17. package/docs/filters.md +0 -347
  18. package/docs/http/endpoints.md +0 -224
  19. package/docs/http/server.md +0 -174
  20. package/docs/plans/2026-02-22-stream-revamp-design.md +0 -88
  21. package/docs/plans/2026-02-22-stream-revamp-plan.md +0 -814
  22. package/docs/quick-start.md +0 -92
  23. package/docs/sources.md +0 -189
  24. package/docs/sponsorblock.md +0 -95
  25. package/tests/cache.test.js +0 -234
  26. package/tests/config.test.js +0 -44
  27. package/tests/error-handling.test.js +0 -318
  28. package/tests/ffmpeg.test.js +0 -66
  29. package/tests/filters-edge.test.js +0 -333
  30. package/tests/http.test.js +0 -24
  31. package/tests/integration.test.js +0 -325
  32. package/tests/local.test.js +0 -37
  33. package/tests/queue.test.js +0 -94
  34. package/tests/spotify.test.js +0 -238
  35. package/tests/stream.test.js +0 -217
  36. package/tests/twitch.test.js +0 -42
  37. package/tests/utils.test.js +0 -60
  38. package/tests/youtube.test.js +0 -219
  39. package/youtube-cookies.txt +0 -26
@@ -1,206 +0,0 @@
1
- # Events
2
-
3
- ## Manager Events
4
-
5
- ```javascript
6
- manager.on('playerCreate', (player) => {
7
- console.log(`Player created for guild ${player.guildId}`);
8
- });
9
-
10
- manager.on('playerDestroy', (player) => {
11
- console.log(`Player destroyed for guild ${player.guildId}`);
12
- });
13
- ```
14
-
15
- ## Player Events
16
-
17
- ### Track Events
18
-
19
- #### trackStart
20
-
21
- Fired when a track starts playing.
22
-
23
- ```javascript
24
- player.on('trackStart', (track) => {
25
- channel.send({
26
- embeds: [{
27
- title: 'Now Playing',
28
- description: `**${track.title}**\nby ${track.author}`,
29
- thumbnail: { url: track.thumbnail }
30
- }]
31
- });
32
- });
33
- ```
34
-
35
- #### trackEnd
36
-
37
- Fired when a track finishes.
38
-
39
- ```javascript
40
- player.on('trackEnd', (track, reason) => {
41
- // reason: 'finished' | 'skipped' | 'stopped'
42
- console.log(`Track ended: ${track.title} (${reason})`);
43
- });
44
- ```
45
-
46
- #### trackError
47
-
48
- Fired when a track fails to play.
49
-
50
- ```javascript
51
- player.on('trackError', (track, error) => {
52
- channel.send(`Failed to play **${track.title}**: ${error.message}`);
53
- });
54
- ```
55
-
56
- #### queueEnd
57
-
58
- Fired when the queue is empty and playback stops.
59
-
60
- ```javascript
61
- player.on('queueEnd', () => {
62
- channel.send('Queue finished. Add more songs or enable autoplay!');
63
- });
64
- ```
65
-
66
- ### Voice Events
67
-
68
- #### userJoin
69
-
70
- Fired when a user joins the voice channel.
71
-
72
- ```javascript
73
- player.on('userJoin', (member, count) => {
74
- console.log(`${member.user.tag} joined (${count} users now)`);
75
- });
76
- ```
77
-
78
- #### userLeave
79
-
80
- Fired when a user leaves the voice channel.
81
-
82
- ```javascript
83
- player.on('userLeave', (member, count) => {
84
- console.log(`${member.user.tag} left (${count} users remaining)`);
85
- });
86
- ```
87
-
88
- #### channelEmpty
89
-
90
- Fired when all users leave the voice channel.
91
-
92
- ```javascript
93
- player.on('channelEmpty', () => {
94
- channel.send('Everyone left. I\'ll leave in 30 seconds...');
95
- });
96
- ```
97
-
98
- #### channelMove
99
-
100
- Fired when the bot is moved to a different voice channel.
101
-
102
- ```javascript
103
- player.on('channelMove', (newChannelId) => {
104
- console.log(`Moved to channel ${newChannelId}`);
105
- });
106
- ```
107
-
108
- ### Automation Events
109
-
110
- #### autoPause
111
-
112
- Fired when playback is automatically paused.
113
-
114
- ```javascript
115
- player.on('autoPause', (userCount) => {
116
- channel.send(`Paused (${userCount} users in channel)`);
117
- });
118
- ```
119
-
120
- #### autoResume
121
-
122
- Fired when playback is automatically resumed.
123
-
124
- ```javascript
125
- player.on('autoResume', (userCount) => {
126
- channel.send(`Resumed (${userCount} users rejoined)`);
127
- });
128
- ```
129
-
130
- #### autoplayStart
131
-
132
- Fired when autoplay starts fetching related tracks.
133
-
134
- ```javascript
135
- player.on('autoplayStart', (lastTrack) => {
136
- console.log(`Finding tracks related to: ${lastTrack.title}`);
137
- });
138
- ```
139
-
140
- #### autoplayAdd
141
-
142
- Fired when autoplay adds tracks to the queue.
143
-
144
- ```javascript
145
- player.on('autoplayAdd', (tracks) => {
146
- channel.send(`Autoplay added ${tracks.length} tracks`);
147
- });
148
- ```
149
-
150
- ### Lifecycle Events
151
-
152
- #### destroy
153
-
154
- Fired when the player is destroyed.
155
-
156
- ```javascript
157
- player.on('destroy', () => {
158
- console.log('Player destroyed');
159
- });
160
- ```
161
-
162
- ## Example: Full Event Setup
163
-
164
- ```javascript
165
- function setupPlayerEvents(player, textChannel) {
166
- player.on('trackStart', (track) => {
167
- const embed = {
168
- color: 0x00ff00,
169
- title: track.isAutoplay ? 'Autoplay' : 'Now Playing',
170
- description: `**${track.title}**\nby ${track.author}`,
171
- thumbnail: { url: track.thumbnail }
172
- };
173
- textChannel.send({ embeds: [embed] });
174
- });
175
-
176
- player.on('trackError', (track, error) => {
177
- textChannel.send(`Failed to play **${track.title}**: ${error.message}`);
178
- });
179
-
180
- player.on('queueEnd', () => {
181
- if (!player.autoplay.enabled) {
182
- textChannel.send('Queue ended. Use `!autoplay` to keep the music going!');
183
- }
184
- });
185
-
186
- player.on('channelEmpty', () => {
187
- textChannel.send('Channel empty. Leaving in 30 seconds...');
188
- });
189
-
190
- player.on('autoPause', () => {
191
- textChannel.send('Paused - everyone left the channel.');
192
- });
193
-
194
- player.on('autoResume', () => {
195
- textChannel.send('Resumed - welcome back!');
196
- });
197
-
198
- player.on('destroy', () => {
199
- textChannel.send('Disconnected.');
200
- });
201
- }
202
-
203
- // Usage
204
- const player = await manager.create(guildId, vcId, tcId);
205
- setupPlayerEvents(player, textChannel);
206
- ```
@@ -1,195 +0,0 @@
1
- # Manager
2
-
3
- The Manager handles player creation, searching, and playlist loading.
4
-
5
- ## Creating a Manager
6
-
7
- ```javascript
8
- const Streamify = require('streamify-audio');
9
-
10
- const manager = new Streamify.Manager(client, {
11
- ytdlpPath: '/usr/local/bin/yt-dlp',
12
- ffmpegPath: '/usr/bin/ffmpeg',
13
- cookiesPath: './cookies.txt',
14
- spotify: {
15
- clientId: process.env.SPOTIFY_CLIENT_ID,
16
- clientSecret: process.env.SPOTIFY_CLIENT_SECRET
17
- }
18
- });
19
- ```
20
-
21
- See [Configuration](../configuration.md) for all options.
22
-
23
- ## Methods
24
-
25
- ### create(guildId, voiceChannelId, textChannelId)
26
-
27
- Creates or retrieves a player for a guild.
28
-
29
- ```javascript
30
- const player = await manager.create(
31
- message.guild.id,
32
- voiceChannel.id,
33
- message.channel.id
34
- );
35
- ```
36
-
37
- If a player already exists for the guild, returns the existing player. If the voice channel differs, disconnects and reconnects.
38
-
39
- ### get(guildId)
40
-
41
- Gets an existing player without creating one.
42
-
43
- ```javascript
44
- const player = manager.get(message.guild.id);
45
- if (!player) {
46
- return message.reply('No player in this server.');
47
- }
48
- ```
49
-
50
- ### destroy(guildId)
51
-
52
- Destroys a player and disconnects from voice.
53
-
54
- ```javascript
55
- manager.destroy(message.guild.id);
56
- ```
57
-
58
- ### destroyAll()
59
-
60
- Destroys all players. Useful for graceful shutdown.
61
-
62
- ```javascript
63
- process.on('SIGINT', () => {
64
- manager.destroyAll();
65
- process.exit();
66
- });
67
- ```
68
-
69
- ### search(query, options?)
70
-
71
- Searches for tracks.
72
-
73
- - `query` (string) - The search term or URL
74
- - `options` (object) - Search configuration
75
- - `source` (string) - `youtube`, `spotify`, `soundcloud`, `twitch`, `mixcloud`, `bandcamp`, `local`, `http`
76
- - `limit` (number) - Number of results (default: 10)
77
- - `type` (string) - `video`, `live`, or `all` (YouTube only)
78
- - `sort` (string) - `relevance`, `popularity`, `date`, or `rating` (YouTube only)
79
- - `artist` (string) - Filter results to only include tracks by this artist
80
-
81
- **Example:**
82
-
83
- ```javascript
84
- const result = await manager.search('lofi hip hop', {
85
- source: 'youtube',
86
- type: 'live',
87
- sort: 'popularity'
88
- });
89
-
90
- // Artist search - filters results to tracks BY the artist
91
- const artistTracks = await manager.search('Drake', {
92
- source: 'spotify',
93
- artist: 'Drake',
94
- limit: 5
95
- });
96
- ```
97
-
98
- // Result
99
- {
100
- loadType: 'search', // search, empty, error
101
- tracks: [{
102
- id: 'dQw4w9WgXcQ',
103
- title: 'Rick Astley - Never Gonna Give You Up',
104
- author: 'Rick Astley',
105
- duration: 213,
106
- thumbnail: 'https://...',
107
- uri: 'https://youtube.com/...',
108
- source: 'youtube'
109
- }]
110
- }
111
- ```
112
-
113
- ### resolve(query)
114
-
115
- Resolves a URL or falls back to search.
116
-
117
- ```javascript
118
- // URL - loads directly
119
- const result = await manager.resolve('https://youtube.com/watch?v=dQw4w9WgXcQ');
120
- // { loadType: 'track', tracks: [track] }
121
-
122
- // Search query - searches
123
- const result = await manager.resolve('never gonna give you up');
124
- // { loadType: 'search', tracks: [...] }
125
- ```
126
-
127
- ### loadPlaylist(url)
128
-
129
- Loads a playlist or album.
130
-
131
- ```javascript
132
- // YouTube playlist
133
- const result = await manager.loadPlaylist('https://youtube.com/playlist?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf');
134
-
135
- // Spotify playlist
136
- const result = await manager.loadPlaylist('https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M');
137
-
138
- // Spotify album
139
- const result = await manager.loadPlaylist('https://open.spotify.com/album/4LH4d3cOWNNsVw41Gqt2kv');
140
-
141
- // Result
142
- {
143
- loadType: 'playlist',
144
- playlist: {
145
- id: 'PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf',
146
- title: 'My Playlist',
147
- author: 'User',
148
- thumbnail: 'https://...',
149
- source: 'youtube'
150
- },
151
- tracks: [...]
152
- }
153
- ```
154
-
155
- ### getRelated(track, limit?)
156
-
157
- Gets related tracks for autoplay.
158
-
159
- ```javascript
160
- const result = await manager.getRelated(currentTrack, 5);
161
- // { tracks: [...] }
162
- ```
163
-
164
- ### getStats()
165
-
166
- Gets manager statistics.
167
-
168
- ```javascript
169
- const stats = manager.getStats();
170
- // {
171
- // players: 5,
172
- // playingPlayers: 3,
173
- // memory: { heapUsed: 52428800, ... }
174
- // }
175
- ```
176
-
177
- ## Events
178
-
179
- ```javascript
180
- manager.on('playerCreate', (player) => {
181
- console.log(`Player created: ${player.guildId}`);
182
- });
183
-
184
- manager.on('playerDestroy', (player) => {
185
- console.log(`Player destroyed: ${player.guildId}`);
186
- });
187
- ```
188
-
189
- ## Properties
190
-
191
- ```javascript
192
- manager.players // Map<guildId, Player>
193
- manager.client // Discord.js client
194
- manager.config // Resolved configuration
195
- ```
@@ -1,263 +0,0 @@
1
- # Player
2
-
3
- The Player handles playback, filters, and voice connection for a single guild.
4
-
5
- ## Getting a Player
6
-
7
- ```javascript
8
- // Create new or get existing
9
- const player = await manager.create(guildId, voiceChannelId, textChannelId);
10
-
11
- // Get existing only
12
- const player = manager.get(guildId);
13
- ```
14
-
15
- ## Playback Methods
16
-
17
- ### play(track, options?)
18
-
19
- Plays a track immediately. If something is playing, adds to queue and skips.
20
-
21
- ```javascript
22
- const result = await manager.search('never gonna give you up');
23
- await player.play(result.tracks[0]);
24
- ```
25
-
26
- **Options:**
27
- - `startPosition` - Start playback at a specific position in milliseconds
28
- - `volume` - Set volume before playing (0-200)
29
- - `filters` - Apply filters before playing
30
- - `replace` - Replace current track without adding to queue/history
31
-
32
- ```javascript
33
- // Start playing at 30 seconds
34
- await player.play(track, { startPosition: 30000 });
35
-
36
- // Start with specific volume
37
- await player.play(track, { volume: 50 });
38
-
39
- // Start with filters applied
40
- await player.play(track, { filters: { bass: 10, nightcore: true } });
41
-
42
- // Replace current track without queueing
43
- await player.play(track, { replace: true });
44
-
45
- // Combine options
46
- await player.play(track, {
47
- startPosition: savedPositionMs,
48
- volume: savedVolume,
49
- filters: savedFilters,
50
- replace: true
51
- });
52
- ```
53
-
54
- ### pause()
55
-
56
- Pauses playback and destroys the stream to save resources.
57
-
58
- ```javascript
59
- player.pause();
60
- ```
61
-
62
- ### resume()
63
-
64
- Resumes playback by recreating the stream and seeking to the saved position.
65
-
66
- ```javascript
67
- await player.resume();
68
- ```
69
-
70
- ### skip()
71
-
72
- Skips to the next track in queue.
73
-
74
- ```javascript
75
- await player.skip();
76
- ```
77
-
78
- ### previous()
79
-
80
- Goes back to the previous track.
81
-
82
- ```javascript
83
- await player.previous();
84
- ```
85
-
86
- ### stop()
87
-
88
- Stops playback and clears the queue.
89
-
90
- ```javascript
91
- player.stop();
92
- ```
93
-
94
- ### seek(positionMs)
95
-
96
- Seeks to a position in milliseconds.
97
-
98
- ```javascript
99
- await player.seek(30000); // Seek to 30 seconds
100
- ```
101
-
102
- ## Volume
103
-
104
- ```javascript
105
- // Set volume (0-200)
106
- player.setVolume(80);
107
-
108
- // Get current volume
109
- console.log(player.volume); // 80
110
- ```
111
-
112
- ## Filters
113
-
114
- ```javascript
115
- // Set a filter
116
- await player.setFilter('bass', 10);
117
- await player.setFilter('nightcore', true);
118
-
119
- // Clear all filters
120
- await player.clearFilters();
121
-
122
- // Get current filters
123
- console.log(player.filters); // { bass: 10, nightcore: true }
124
- ```
125
-
126
- See [Filters](../filters.md) for all available filters.
127
-
128
- ## Effect Presets
129
-
130
- Effect presets are pre-configured filter combinations that stack by default.
131
-
132
- ```javascript
133
- // Apply a single preset
134
- await player.setEffectPresets(['bassboost']);
135
-
136
- // Apply multiple presets (they stack)
137
- await player.setEffectPresets(['nightcore', 'bassboost']);
138
-
139
- // Apply with custom intensity (0.1 - 1.0)
140
- await player.setEffectPresets([
141
- { name: 'nightcore', intensity: 0.8 },
142
- { name: 'bassboost', intensity: 0.5 }
143
- ]);
144
-
145
- // Replace all presets instead of stacking
146
- await player.setEffectPresets(['8d'], { replace: true });
147
-
148
- // Get active presets
149
- const active = player.getActiveEffectPresets();
150
- // [{ name: 'nightcore', intensity: 0.8 }, { name: 'bassboost', intensity: 0.5 }]
151
-
152
- // Clear all effect presets
153
- await player.clearEffectPresets();
154
-
155
- // List available presets
156
- const presets = player.getEffectPresets();
157
- // ['bassboost', 'nightcore', 'vaporwave', '8d', 'karaoke', ...]
158
- ```
159
-
160
- **Available Presets:**
161
- - `bassboost` - Boost bass frequencies
162
- - `nightcore` - Speed up with higher pitch
163
- - `vaporwave` - Slow down with lower pitch
164
- - `8d` - 8D rotating audio effect
165
- - `karaoke` - Reduce vocals
166
- - `reverb` - Add room acoustics / echo
167
- - `surround` - Virtual surround sound mapping
168
- - `boost` - General volume and clarity boost
169
- - `subboost` - Extreme sub-woofer boost
170
- - `trebleboost` - Boost treble frequencies
171
- - `deep` - Deep bass with lower pitch
172
- - `lofi` - Lo-fi aesthetic
173
- - `radio` - Radio/telephone effect
174
- - `telephone` - Old telephone effect
175
- - `soft` - Softer, quieter sound
176
- - `loud` - Louder, compressed sound
177
- - `chipmunk` - High-pitched voice
178
- - `darth` - Deep Darth Vader voice
179
- - `echo` - Echo/reverb effect
180
- - `vibrato` - Vibrato effect
181
- - `tremolo` - Tremolo effect
182
-
183
- ## Loop Modes
184
-
185
- ```javascript
186
- player.setLoop('off'); // No looping
187
- player.setLoop('track'); // Loop current track
188
- player.setLoop('queue'); // Loop entire queue
189
- ```
190
-
191
- ## Toggles
192
-
193
- ```javascript
194
- // Autoplay (play related tracks when queue ends)
195
- player.setAutoplay(true);
196
- player.setAutoplay(false);
197
-
198
- // Auto-pause (pause when channel empty)
199
- player.setAutoPause(true);
200
- player.setAutoPause(false);
201
- ```
202
-
203
- ## Connection
204
-
205
- ```javascript
206
- // Connect to voice
207
- await player.connect();
208
-
209
- // Disconnect (keeps player)
210
- player.disconnect();
211
-
212
- // Destroy player completely
213
- player.destroy();
214
- ```
215
-
216
- ## State Properties
217
-
218
- ```javascript
219
- player.connected // true if connected to voice
220
- player.playing // true if playing (not paused)
221
- player.paused // true if paused
222
- player.position // Current position in ms
223
- player.volume // Current volume (0-200)
224
- player.filters // Current filters object
225
-
226
- player.guildId // Guild ID
227
- player.voiceChannelId // Voice channel ID
228
- player.textChannelId // Text channel ID
229
-
230
- player.autoplay // { enabled, maxTracks }
231
- player.autoPause // { enabled, minUsers }
232
- player.autoLeave // { enabled, emptyDelay, inactivityTimeout }
233
- ```
234
-
235
- ## Queue Access
236
-
237
- ```javascript
238
- player.queue.current // Currently playing track
239
- player.queue.tracks // Upcoming tracks
240
- player.queue.previous // Previously played tracks
241
- ```
242
-
243
- See [Queue](./queue.md) for queue methods.
244
-
245
- ## Serialization
246
-
247
- ```javascript
248
- const json = player.toJSON();
249
- // {
250
- // guildId: '...',
251
- // voiceChannelId: '...',
252
- // connected: true,
253
- // playing: true,
254
- // paused: false,
255
- // volume: 80,
256
- // position: 45000,
257
- // filters: { bass: 10 },
258
- // queue: { current: {...}, tracks: [...] },
259
- // autoplay: { enabled: false },
260
- // autoPause: { enabled: true },
261
- // autoLeave: { enabled: true }
262
- // }
263
- ```