streamify-audio 2.0.0

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.
@@ -0,0 +1,186 @@
1
+ # Automation
2
+
3
+ Streamify includes built-in automation features for common scenarios.
4
+
5
+ ## Auto-Pause
6
+
7
+ Automatically pauses playback when users leave the voice channel and resumes when they return.
8
+
9
+ ### Configuration
10
+
11
+ ```javascript
12
+ const manager = new Streamify.Manager(client, {
13
+ autoPause: {
14
+ enabled: true,
15
+ minUsers: 1 // Pause when users drop below this
16
+ }
17
+ });
18
+ ```
19
+
20
+ ### Behavior
21
+
22
+ 1. User count drops below `minUsers`
23
+ 2. Playback pauses immediately
24
+ 3. Stream is destroyed (saves resources)
25
+ 4. Position is saved
26
+ 5. When users rejoin and count reaches `minUsers`:
27
+ 6. Stream recreates with seek
28
+ 7. Playback resumes
29
+
30
+ ### Events
31
+
32
+ ```javascript
33
+ player.on('autoPause', (userCount) => {
34
+ channel.send(`Paused (${userCount} users in channel)`);
35
+ });
36
+
37
+ player.on('autoResume', (userCount) => {
38
+ channel.send(`Resumed (${userCount} users now)`);
39
+ });
40
+ ```
41
+
42
+ ### Runtime Toggle
43
+
44
+ ```javascript
45
+ player.setAutoPause(false); // Disable
46
+ player.setAutoPause(true); // Enable
47
+ ```
48
+
49
+ ## Auto-Leave
50
+
51
+ Automatically leaves the voice channel after a period of inactivity.
52
+
53
+ ### Configuration
54
+
55
+ ```javascript
56
+ const manager = new Streamify.Manager(client, {
57
+ autoLeave: {
58
+ enabled: true,
59
+ emptyDelay: 30000, // Leave 30s after channel empty
60
+ inactivityTimeout: 300000 // Leave after 5min of not playing
61
+ }
62
+ });
63
+ ```
64
+
65
+ ### Behavior
66
+
67
+ **Empty Channel:**
68
+ 1. All users leave
69
+ 2. 30 second countdown starts
70
+ 3. If no one rejoins, player destroys
71
+
72
+ **Inactivity:**
73
+ 1. Queue ends, nothing playing
74
+ 2. 5 minute countdown starts
75
+ 3. If nothing plays, player destroys
76
+
77
+ ### Events
78
+
79
+ ```javascript
80
+ player.on('channelEmpty', () => {
81
+ channel.send('Everyone left. Leaving in 30 seconds...');
82
+ });
83
+
84
+ player.on('destroy', () => {
85
+ channel.send('Disconnected due to inactivity.');
86
+ });
87
+ ```
88
+
89
+ ## Autoplay
90
+
91
+ Automatically plays related tracks when the queue ends.
92
+
93
+ ### Configuration
94
+
95
+ ```javascript
96
+ const manager = new Streamify.Manager(client, {
97
+ autoplay: {
98
+ enabled: false, // Off by default
99
+ maxTracks: 5 // How many related tracks to fetch
100
+ }
101
+ });
102
+ ```
103
+
104
+ ### Behavior
105
+
106
+ 1. Queue ends (last track finishes)
107
+ 2. Fetch related tracks from YouTube Mix or Spotify Recommendations
108
+ 3. Add to queue and start playing
109
+ 4. Repeat when those tracks end
110
+
111
+ ### Events
112
+
113
+ ```javascript
114
+ player.on('autoplayStart', (lastTrack) => {
115
+ console.log(`Finding tracks like: ${lastTrack.title}`);
116
+ });
117
+
118
+ player.on('autoplayAdd', (tracks) => {
119
+ channel.send(`Autoplay added ${tracks.length} tracks`);
120
+ });
121
+ ```
122
+
123
+ ### Runtime Toggle
124
+
125
+ ```javascript
126
+ player.setAutoplay(true); // Enable
127
+ player.setAutoplay(false); // Disable
128
+ ```
129
+
130
+ ### Track Identification
131
+
132
+ Autoplay tracks are marked:
133
+
134
+ ```javascript
135
+ player.on('trackStart', (track) => {
136
+ if (track.isAutoplay) {
137
+ channel.send(`Autoplay: **${track.title}**`);
138
+ } else {
139
+ channel.send(`Now playing: **${track.title}**`);
140
+ }
141
+ });
142
+ ```
143
+
144
+ ## Combining Features
145
+
146
+ All automation features work together:
147
+
148
+ ```javascript
149
+ const manager = new Streamify.Manager(client, {
150
+ autoPause: {
151
+ enabled: true,
152
+ minUsers: 1
153
+ },
154
+ autoLeave: {
155
+ enabled: true,
156
+ emptyDelay: 30000,
157
+ inactivityTimeout: 300000
158
+ },
159
+ autoplay: {
160
+ enabled: true,
161
+ maxTracks: 5
162
+ }
163
+ });
164
+ ```
165
+
166
+ **Scenario: User leaves during playback**
167
+ 1. `autoPause` triggers → pauses playback
168
+ 2. `autoLeave` starts 30s countdown
169
+ 3. User rejoins within 30s
170
+ 4. `autoResume` triggers → playback continues
171
+ 5. Countdown cancelled
172
+
173
+ **Scenario: Queue ends**
174
+ 1. `autoplay` fetches related tracks
175
+ 2. Playback continues with recommendations
176
+ 3. If autoplay disabled, `autoLeave` inactivity timeout starts
177
+
178
+ ## Disabling All Automation
179
+
180
+ ```javascript
181
+ const manager = new Streamify.Manager(client, {
182
+ autoPause: { enabled: false },
183
+ autoLeave: { enabled: false },
184
+ autoplay: { enabled: false }
185
+ });
186
+ ```
@@ -0,0 +1,169 @@
1
+ # Configuration
2
+
3
+ ## Discord Player Mode
4
+
5
+ ```javascript
6
+ const manager = new Streamify.Manager(client, {
7
+ // Paths (required)
8
+ ytdlpPath: '/usr/local/bin/yt-dlp',
9
+ ffmpegPath: '/usr/bin/ffmpeg',
10
+
11
+ // YouTube cookies (optional)
12
+ cookiesPath: './cookies.txt',
13
+
14
+ // Providers (optional - all enabled by default)
15
+ providers: {
16
+ youtube: { enabled: true },
17
+ spotify: { enabled: true },
18
+ soundcloud: { enabled: true }
19
+ },
20
+
21
+ // Spotify credentials (optional)
22
+ spotify: {
23
+ clientId: process.env.SPOTIFY_CLIENT_ID,
24
+ clientSecret: process.env.SPOTIFY_CLIENT_SECRET
25
+ },
26
+
27
+ // Audio settings
28
+ audio: {
29
+ bitrate: '128k', // Audio bitrate
30
+ format: 'opus' // opus, mp3, aac
31
+ },
32
+
33
+ // Defaults
34
+ defaultVolume: 80, // 0-200
35
+ maxPreviousTracks: 25, // History size
36
+
37
+ // Sponsorblock
38
+ sponsorblock: {
39
+ enabled: true,
40
+ categories: ['sponsor', 'selfpromo', 'intro', 'outro']
41
+ },
42
+
43
+ // Auto-leave
44
+ autoLeave: {
45
+ enabled: true,
46
+ emptyDelay: 30000, // Leave 30s after channel empty
47
+ inactivityTimeout: 300000 // Leave after 5min idle
48
+ },
49
+
50
+ // Auto-pause
51
+ autoPause: {
52
+ enabled: true,
53
+ minUsers: 1 // Pause when users drop below this
54
+ },
55
+
56
+ // Autoplay
57
+ autoplay: {
58
+ enabled: false,
59
+ maxTracks: 5 // Related tracks to fetch
60
+ }
61
+ });
62
+ ```
63
+
64
+ ## HTTP Server Mode
65
+
66
+ ```javascript
67
+ const streamify = new Streamify({
68
+ // Server
69
+ port: 8787,
70
+ host: '0.0.0.0',
71
+
72
+ // Paths
73
+ ytdlpPath: '/usr/local/bin/yt-dlp',
74
+ ffmpegPath: '/usr/bin/ffmpeg',
75
+
76
+ // YouTube cookies
77
+ cookiesPath: './cookies.txt',
78
+ // Or direct string:
79
+ cookies: '# Netscape HTTP Cookie File\n...',
80
+
81
+ // Providers (optional - all enabled by default)
82
+ providers: {
83
+ youtube: { enabled: true },
84
+ spotify: { enabled: true },
85
+ soundcloud: { enabled: true }
86
+ },
87
+
88
+ // Spotify
89
+ spotify: {
90
+ clientId: 'xxx',
91
+ clientSecret: 'xxx'
92
+ },
93
+
94
+ // Audio
95
+ audio: {
96
+ bitrate: '128k',
97
+ format: 'opus'
98
+ },
99
+
100
+ // Logging
101
+ logLevel: 'info', // none, error, warn, info, debug
102
+ silent: false,
103
+ colors: true
104
+ });
105
+ ```
106
+
107
+ ## Environment Variables
108
+
109
+ | Variable | Description |
110
+ |----------|-------------|
111
+ | `SPOTIFY_CLIENT_ID` | Spotify API client ID |
112
+ | `SPOTIFY_CLIENT_SECRET` | Spotify API client secret |
113
+ | `YTDLP_PATH` | Path to yt-dlp binary |
114
+ | `FFMPEG_PATH` | Path to ffmpeg binary |
115
+ | `COOKIES_PATH` | Path to YouTube cookies file |
116
+ | `PORT` | HTTP server port |
117
+
118
+ ## YouTube Cookies
119
+
120
+ For age-restricted or region-locked videos:
121
+
122
+ 1. Install browser extension "Get cookies.txt"
123
+ 2. Visit youtube.com while logged in
124
+ 3. Export cookies in Netscape format
125
+ 4. Save as `cookies.txt`
126
+
127
+ ```javascript
128
+ // File path
129
+ cookiesPath: './cookies.txt'
130
+
131
+ // Or direct string
132
+ cookies: `# Netscape HTTP Cookie File
133
+ .youtube.com TRUE / TRUE 0 COOKIE_NAME COOKIE_VALUE`
134
+ ```
135
+
136
+ ## Spotify Setup
137
+
138
+ 1. Go to [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)
139
+ 2. Create an app
140
+ 3. Copy Client ID and Client Secret
141
+
142
+ ```javascript
143
+ spotify: {
144
+ clientId: process.env.SPOTIFY_CLIENT_ID,
145
+ clientSecret: process.env.SPOTIFY_CLIENT_SECRET
146
+ }
147
+ ```
148
+
149
+ Spotify tracks are resolved to YouTube for playback.
150
+
151
+ ## Providers
152
+
153
+ Enable or disable individual providers:
154
+
155
+ ```javascript
156
+ providers: {
157
+ youtube: { enabled: true },
158
+ spotify: { enabled: true },
159
+ soundcloud: { enabled: false } // Disabled
160
+ }
161
+ ```
162
+
163
+ All providers are enabled by default. When a disabled provider is accessed, an error is thrown:
164
+
165
+ ```
166
+ Error: SoundCloud provider is disabled
167
+ ```
168
+
169
+ This is useful if you only want to support specific platforms.
@@ -0,0 +1,206 @@
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
+ ```