streamify-audio 2.2.1 → 2.2.5
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/.github/workflows/npm-publish-github-packages.yml +36 -0
- package/README.md +81 -7
- package/docs/configuration.md +31 -2
- package/docs/discord/manager.md +14 -7
- package/docs/discord/player.md +84 -1
- package/docs/filters.md +39 -1
- package/docs/http/endpoints.md +25 -0
- package/docs/http/server.md +2 -0
- package/docs/sources.md +52 -4
- package/index.d.ts +31 -1
- package/index.js +67 -3
- package/package.json +8 -6
- package/src/config.js +17 -1
- package/src/discord/Manager.js +101 -7
- package/src/discord/Player.js +274 -86
- package/src/discord/Stream.js +171 -135
- package/src/filters/ffmpeg.js +119 -14
- package/src/providers/bandcamp.js +49 -0
- package/src/providers/http.js +25 -0
- package/src/providers/local.js +31 -0
- package/src/providers/mixcloud.js +49 -0
- package/src/providers/soundcloud.js +5 -1
- package/src/providers/twitch.js +49 -0
- package/src/providers/youtube.js +26 -5
- package/src/server.js +60 -5
- package/src/utils/logger.js +34 -12
- package/tests/config.test.js +44 -0
- package/tests/ffmpeg.test.js +66 -0
- package/tests/http.test.js +24 -0
- package/tests/local.test.js +37 -0
- package/tests/queue.test.js +94 -0
- package/tests/twitch.test.js +42 -0
- package/tests/utils.test.js +60 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
|
3
|
+
|
|
4
|
+
name: Node.js Package
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [created]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-node@v4
|
|
16
|
+
with:
|
|
17
|
+
node-version: 20
|
|
18
|
+
- run: npm ci
|
|
19
|
+
- run: npm test
|
|
20
|
+
|
|
21
|
+
publish-gpr:
|
|
22
|
+
needs: build
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
packages: write
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: actions/setup-node@v4
|
|
30
|
+
with:
|
|
31
|
+
node-version: 20
|
|
32
|
+
registry-url: https://npm.pkg.github.com/
|
|
33
|
+
- run: npm ci
|
|
34
|
+
- run: npm publish
|
|
35
|
+
env:
|
|
36
|
+
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
package/README.md
CHANGED
|
@@ -33,6 +33,21 @@ Both modes share the same providers, filters, and streaming engine.
|
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
36
|
+
## 🎵 Supported Sources
|
|
37
|
+
|
|
38
|
+
Streamify is built to be a universal audio engine. It supports:
|
|
39
|
+
|
|
40
|
+
- **YouTube**: Videos, Music, Shorts, Live, Playlists
|
|
41
|
+
- **Spotify**: Tracks, Albums, Playlists (resolved to YouTube)
|
|
42
|
+
- **SoundCloud**: Tracks
|
|
43
|
+
- **Twitch**: Live streams
|
|
44
|
+
- **Mixcloud**: Mixes and DJ sets
|
|
45
|
+
- **Bandcamp**: Tracks and Albums
|
|
46
|
+
- **Direct URLs**: Public raw audio links (MP3, OGG, WAV, etc.)
|
|
47
|
+
- **Local Files**: Absolute or relative paths on the host system
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
36
51
|
## 🚀 Quick Start
|
|
37
52
|
|
|
38
53
|
```bash
|
|
@@ -135,6 +150,13 @@ When running in HTTP mode, Streamify exposes a REST API:
|
|
|
135
150
|
| `GET` | `/spotify/stream/:id` | Stream Spotify track |
|
|
136
151
|
| `GET` | `/soundcloud/search?q=query` | Search SoundCloud |
|
|
137
152
|
| `GET` | `/soundcloud/stream/:id` | Stream SoundCloud track |
|
|
153
|
+
| `GET` | `/twitch/stream/:channel` | Stream Twitch live |
|
|
154
|
+
| `GET` | `/mixcloud/stream/:id` | Stream Mixcloud set |
|
|
155
|
+
| `GET` | `/bandcamp/stream/:id` | Stream Bandcamp track |
|
|
156
|
+
| `GET` | `/http/stream/:base64_url` | Stream from direct URL |
|
|
157
|
+
| `GET` | `/local/stream/:base64_path` | Stream local file |
|
|
158
|
+
| `GET` | `/search?q=query&source=...` | Generic search across providers |
|
|
159
|
+
| `GET` | `/stream/:source/:id` | Generic stream endpoint |
|
|
138
160
|
|
|
139
161
|
### Stream Parameters
|
|
140
162
|
|
|
@@ -171,23 +193,51 @@ audio.play();
|
|
|
171
193
|
| Feature | Discord | HTTP |
|
|
172
194
|
|---------|:-------:|:----:|
|
|
173
195
|
| 🎵 YouTube, Spotify, SoundCloud | ✅ | ✅ |
|
|
196
|
+
| 🎮 Twitch, Mixcloud, Bandcamp | ✅ | ✅ |
|
|
197
|
+
| 📁 Local Files & Direct URLs | ✅ | ✅ |
|
|
198
|
+
| 📺 **Voice Channel Status** | ✅ | — |
|
|
199
|
+
| 🔍 **Advanced Search Filters** | ✅ | ✅ |
|
|
174
200
|
| 📋 Playlists & Albums | ✅ | ✅ |
|
|
175
|
-
| 🎚️
|
|
201
|
+
| 🎚️ 30+ Stackable Filters | ✅ | ✅ |
|
|
176
202
|
| 🎛️ 15-Band Equalizer | ✅ | ✅ |
|
|
177
203
|
| 🎨 15 EQ Presets | ✅ | ✅ |
|
|
204
|
+
| 🔄 **Seamless Transitions** | ✅ | ✅ |
|
|
178
205
|
| ⏭️ Instant Skip (prefetch) | ✅ | — |
|
|
179
206
|
| ⏸️ Auto-pause when alone | ✅ | — |
|
|
180
207
|
| ▶️ Auto-resume on rejoin | ✅ | — |
|
|
181
208
|
| 🚪 Auto-leave on inactivity | ✅ | — |
|
|
182
|
-
| 📻 Autoplay related tracks | ✅ | — |
|
|
183
209
|
| 🚫 Sponsorblock | ✅ | ✅ |
|
|
184
|
-
| 📊
|
|
210
|
+
| 📊 Timing & Performance Logs | ✅ | ✅ |
|
|
185
211
|
| 🔌 No Lavalink/Java needed | ✅ | ✅ |
|
|
186
212
|
|
|
187
213
|
---
|
|
188
214
|
|
|
189
215
|
## 🎮 Discord Player Features
|
|
190
216
|
|
|
217
|
+
### Voice Channel Status
|
|
218
|
+
|
|
219
|
+
Show what's playing directly in the sidebar of the voice channel.
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
const manager = new Streamify.Manager(client, {
|
|
223
|
+
voiceChannelStatus: {
|
|
224
|
+
enabled: true,
|
|
225
|
+
template: '🎶 Playing: {title} | {requester}'
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Search with Filters
|
|
231
|
+
|
|
232
|
+
Filter for live streams or sort results by popularity/date.
|
|
233
|
+
|
|
234
|
+
```javascript
|
|
235
|
+
const results = await manager.search('lofi hip hop', {
|
|
236
|
+
type: 'live',
|
|
237
|
+
sort: 'popularity'
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
191
241
|
### Queue Management
|
|
192
242
|
|
|
193
243
|
```javascript
|
|
@@ -297,6 +347,10 @@ const url = streamify.getStreamUrl('youtube', 'dQw4w9WgXcQ', {
|
|
|
297
347
|
| `volume` | 0 to 200 | Volume % |
|
|
298
348
|
| `nightcore` | boolean | Speed + pitch up |
|
|
299
349
|
| `vaporwave` | boolean | Speed + pitch down |
|
|
350
|
+
| `subboost` | boolean | Extreme sub-bass boost |
|
|
351
|
+
| `reverb` | boolean | Room acoustics effect |
|
|
352
|
+
| `surround` | boolean | Surround sound mapping |
|
|
353
|
+
| `boost` | boolean | Clarity & volume boost |
|
|
300
354
|
| `8d` | boolean | Rotating audio |
|
|
301
355
|
| `karaoke` | boolean | Reduce vocals |
|
|
302
356
|
| `bassboost` | boolean | Heavy bass |
|
|
@@ -349,7 +403,10 @@ const manager = new Streamify.Manager(client, {
|
|
|
349
403
|
providers: {
|
|
350
404
|
youtube: { enabled: true },
|
|
351
405
|
spotify: { enabled: true },
|
|
352
|
-
soundcloud: { enabled:
|
|
406
|
+
soundcloud: { enabled: true },
|
|
407
|
+
twitch: { enabled: true },
|
|
408
|
+
mixcloud: { enabled: true },
|
|
409
|
+
bandcamp: { enabled: true }
|
|
353
410
|
},
|
|
354
411
|
spotify: {
|
|
355
412
|
clientId: 'your_client_id',
|
|
@@ -357,7 +414,14 @@ const manager = new Streamify.Manager(client, {
|
|
|
357
414
|
},
|
|
358
415
|
audio: {
|
|
359
416
|
bitrate: '128k',
|
|
360
|
-
format: 'opus'
|
|
417
|
+
format: 'opus',
|
|
418
|
+
vbr: true,
|
|
419
|
+
compressionLevel: 10,
|
|
420
|
+
application: 'audio'
|
|
421
|
+
},
|
|
422
|
+
ytdlp: {
|
|
423
|
+
format: 'bestaudio/best',
|
|
424
|
+
additionalArgs: []
|
|
361
425
|
},
|
|
362
426
|
defaultVolume: 80,
|
|
363
427
|
maxPreviousTracks: 25,
|
|
@@ -380,7 +444,10 @@ const streamify = new Streamify({
|
|
|
380
444
|
providers: {
|
|
381
445
|
youtube: { enabled: true },
|
|
382
446
|
spotify: { enabled: true },
|
|
383
|
-
soundcloud: { enabled: true }
|
|
447
|
+
soundcloud: { enabled: true },
|
|
448
|
+
twitch: { enabled: true },
|
|
449
|
+
mixcloud: { enabled: true },
|
|
450
|
+
bandcamp: { enabled: true }
|
|
384
451
|
},
|
|
385
452
|
spotify: {
|
|
386
453
|
clientId: 'your_client_id',
|
|
@@ -388,7 +455,14 @@ const streamify = new Streamify({
|
|
|
388
455
|
},
|
|
389
456
|
audio: {
|
|
390
457
|
bitrate: '128k',
|
|
391
|
-
format: 'opus'
|
|
458
|
+
format: 'opus',
|
|
459
|
+
vbr: true,
|
|
460
|
+
compressionLevel: 10,
|
|
461
|
+
application: 'audio'
|
|
462
|
+
},
|
|
463
|
+
ytdlp: {
|
|
464
|
+
format: 'bestaudio/best',
|
|
465
|
+
additionalArgs: []
|
|
392
466
|
},
|
|
393
467
|
logLevel: 'info'
|
|
394
468
|
});
|
package/docs/configuration.md
CHANGED
|
@@ -27,7 +27,16 @@ const manager = new Streamify.Manager(client, {
|
|
|
27
27
|
// Audio settings
|
|
28
28
|
audio: {
|
|
29
29
|
bitrate: '128k', // Audio bitrate
|
|
30
|
-
format: 'opus'
|
|
30
|
+
format: 'opus', // opus, mp3, aac
|
|
31
|
+
vbr: true, // Enable Variable Bitrate (Opus only)
|
|
32
|
+
compressionLevel: 10, // Opus compression level (0-10)
|
|
33
|
+
application: 'audio' // Opus application (audio, voip, lowdelay)
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
// yt-dlp settings
|
|
37
|
+
ytdlp: {
|
|
38
|
+
format: 'bestaudio/best', // Custom yt-dlp format string
|
|
39
|
+
additionalArgs: [] // Extra arguments for yt-dlp (e.g. proxy)
|
|
31
40
|
},
|
|
32
41
|
|
|
33
42
|
// Defaults
|
|
@@ -57,10 +66,21 @@ const manager = new Streamify.Manager(client, {
|
|
|
57
66
|
autoplay: {
|
|
58
67
|
enabled: false,
|
|
59
68
|
maxTracks: 5 // Related tracks to fetch
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
// Voice Channel Status
|
|
72
|
+
voiceChannelStatus: {
|
|
73
|
+
enabled: true, // Show "Now Playing" in VC description
|
|
74
|
+
template: '🎶 Now Playing: {title} - {artist}' // Custom template
|
|
60
75
|
}
|
|
61
76
|
});
|
|
62
77
|
```
|
|
63
78
|
|
|
79
|
+
**Voice Channel Status Template Variables:**
|
|
80
|
+
- `{title}` - Track title
|
|
81
|
+
- `{artist}` - Track artist/author
|
|
82
|
+
- `{requester}` - Username of the requester (if provided)
|
|
83
|
+
|
|
64
84
|
## HTTP Server Mode
|
|
65
85
|
|
|
66
86
|
```javascript
|
|
@@ -94,7 +114,16 @@ const streamify = new Streamify({
|
|
|
94
114
|
// Audio
|
|
95
115
|
audio: {
|
|
96
116
|
bitrate: '128k',
|
|
97
|
-
format: 'opus'
|
|
117
|
+
format: 'opus',
|
|
118
|
+
vbr: true,
|
|
119
|
+
compressionLevel: 10,
|
|
120
|
+
application: 'audio'
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
// yt-dlp
|
|
124
|
+
ytdlp: {
|
|
125
|
+
format: 'bestaudio/best',
|
|
126
|
+
additionalArgs: []
|
|
98
127
|
},
|
|
99
128
|
|
|
100
129
|
// Logging
|
package/docs/discord/manager.md
CHANGED
|
@@ -70,15 +70,22 @@ process.on('SIGINT', () => {
|
|
|
70
70
|
|
|
71
71
|
Searches for tracks.
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
+
|
|
80
|
+
**Example:**
|
|
76
81
|
|
|
77
|
-
|
|
78
|
-
const result = await manager.search('
|
|
79
|
-
source: '
|
|
80
|
-
|
|
82
|
+
```javascript
|
|
83
|
+
const result = await manager.search('lofi hip hop', {
|
|
84
|
+
source: 'youtube',
|
|
85
|
+
type: 'live',
|
|
86
|
+
sort: 'popularity'
|
|
81
87
|
});
|
|
88
|
+
```
|
|
82
89
|
|
|
83
90
|
// Result
|
|
84
91
|
{
|
package/docs/discord/player.md
CHANGED
|
@@ -14,7 +14,7 @@ const player = manager.get(guildId);
|
|
|
14
14
|
|
|
15
15
|
## Playback Methods
|
|
16
16
|
|
|
17
|
-
### play(track)
|
|
17
|
+
### play(track, options?)
|
|
18
18
|
|
|
19
19
|
Plays a track immediately. If something is playing, adds to queue and skips.
|
|
20
20
|
|
|
@@ -23,6 +23,34 @@ const result = await manager.search('never gonna give you up');
|
|
|
23
23
|
await player.play(result.tracks[0]);
|
|
24
24
|
```
|
|
25
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
|
+
|
|
26
54
|
### pause()
|
|
27
55
|
|
|
28
56
|
Pauses playback and destroys the stream to save resources.
|
|
@@ -97,6 +125,61 @@ console.log(player.filters); // { bass: 10, nightcore: true }
|
|
|
97
125
|
|
|
98
126
|
See [Filters](../filters.md) for all available filters.
|
|
99
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
|
+
|
|
100
183
|
## Loop Modes
|
|
101
184
|
|
|
102
185
|
```javascript
|
package/docs/filters.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Audio Filters
|
|
2
2
|
|
|
3
|
-
Filters are applied in real-time via ffmpeg. When you change a filter during playback, Streamify
|
|
3
|
+
Filters are applied in real-time via ffmpeg. When you change a filter during playback, Streamify uses **Seamless Transitions** to prepare the new stream in the background and swap it instantly once ready, ensuring no audio gaps.
|
|
4
4
|
|
|
5
5
|
## Available Filters
|
|
6
6
|
|
|
@@ -287,6 +287,44 @@ await player.setFilter('peaking', {
|
|
|
287
287
|
});
|
|
288
288
|
```
|
|
289
289
|
|
|
290
|
+
## Effect Presets (Stacked)
|
|
291
|
+
|
|
292
|
+
Streamify supports "Effect Presets" which can be stacked on top of each other. These are more powerful than standard filters because they can combine multiple FFmpeg settings.
|
|
293
|
+
|
|
294
|
+
### Available Effect Presets
|
|
295
|
+
|
|
296
|
+
| Preset | Description |
|
|
297
|
+
|--------|-------------|
|
|
298
|
+
| `bassboost` | Strong low-end boost |
|
|
299
|
+
| `subboost` | Extreme sub-woofer boost |
|
|
300
|
+
| `nightcore` | High speed and pitch |
|
|
301
|
+
| `vaporwave` | Low speed and pitch |
|
|
302
|
+
| `reverb` | Adds room acoustics / echo |
|
|
303
|
+
| `surround` | Virtual surround sound mapping |
|
|
304
|
+
| `boost` | General volume and clarity boost |
|
|
305
|
+
| `karaoke` | Vocal reduction |
|
|
306
|
+
| `8d` | Fast circular panning |
|
|
307
|
+
|
|
308
|
+
### Usage
|
|
309
|
+
|
|
310
|
+
```javascript
|
|
311
|
+
// Set a single effect with intensity (0.0 to 2.0)
|
|
312
|
+
await player.setEffectPresets({ name: 'reverb', intensity: 0.8 });
|
|
313
|
+
|
|
314
|
+
// Stack multiple effects
|
|
315
|
+
await player.setEffectPresets([
|
|
316
|
+
{ name: 'bassboost', intensity: 1.2 },
|
|
317
|
+
{ name: 'nightcore', intensity: 1.0 }
|
|
318
|
+
]);
|
|
319
|
+
|
|
320
|
+
// Clear all effects
|
|
321
|
+
await player.clearEffectPresets();
|
|
322
|
+
|
|
323
|
+
// Get active effects
|
|
324
|
+
const active = player.getActiveEffectPresets();
|
|
325
|
+
// [{ name: 'reverb', intensity: 0.8 }]
|
|
326
|
+
```
|
|
327
|
+
|
|
290
328
|
## Additional Effects
|
|
291
329
|
|
|
292
330
|
| Effect | Description |
|
package/docs/http/endpoints.md
CHANGED
|
@@ -100,6 +100,31 @@ GET /soundcloud/stream/:trackUrl
|
|
|
100
100
|
|
|
101
101
|
Note: `trackUrl` should be URL-encoded.
|
|
102
102
|
|
|
103
|
+
## Generic Routes
|
|
104
|
+
|
|
105
|
+
### Search
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
GET /search?q=query&source=youtube&limit=10
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Query Parameters:**
|
|
112
|
+
- `q` - Search query
|
|
113
|
+
- `source` - `youtube`, `spotify`, `soundcloud`, `twitch`, `mixcloud`, `bandcamp`, `local`, `http`
|
|
114
|
+
- `limit` - Number of results
|
|
115
|
+
|
|
116
|
+
### Stream
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
GET /stream/:source/:id
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Example:**
|
|
123
|
+
```
|
|
124
|
+
GET /stream/twitch/monstercat
|
|
125
|
+
GET /stream/local/L2hvbWUvdXNlci9tdXNpYy9zbmFyZS53YXY= (Base64 path)
|
|
126
|
+
```
|
|
127
|
+
|
|
103
128
|
## Stream Management
|
|
104
129
|
|
|
105
130
|
### List Active Streams
|
package/docs/http/server.md
CHANGED
|
@@ -95,6 +95,8 @@ const results = await streamify.search('youtube', 'query', 10);
|
|
|
95
95
|
const results = await streamify.youtube.search('query');
|
|
96
96
|
const results = await streamify.spotify.search('query');
|
|
97
97
|
const results = await streamify.soundcloud.search('query');
|
|
98
|
+
const info = await streamify.twitch.getInfo('channel');
|
|
99
|
+
const url = streamify.local.getStreamUrl('/path/to/file.mp3');
|
|
98
100
|
```
|
|
99
101
|
|
|
100
102
|
### Get Info
|
package/docs/sources.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Sources
|
|
2
2
|
|
|
3
|
-
Streamify supports YouTube, Spotify, and
|
|
3
|
+
Streamify supports YouTube, Spotify, SoundCloud, Twitch, Mixcloud, Bandcamp, Local Files, and Direct URLs.
|
|
4
4
|
|
|
5
5
|
## Supported Features
|
|
6
6
|
|
|
@@ -9,6 +9,11 @@ Streamify supports YouTube, Spotify, and SoundCloud.
|
|
|
9
9
|
| YouTube | ✅ | ✅ | ✅ | — |
|
|
10
10
|
| Spotify | ✅ | ✅ | ✅ | ✅ |
|
|
11
11
|
| SoundCloud | ✅ | ✅ | ❌ | — |
|
|
12
|
+
| Twitch | ✅ | ✅ | — | — |
|
|
13
|
+
| Mixcloud | ✅ | ✅ | — | — |
|
|
14
|
+
| Bandcamp | ✅ | ✅ | — | ✅ |
|
|
15
|
+
| Direct URL | ✅ | ✅ | — | — |
|
|
16
|
+
| Local File | ✅ | ✅ | — | — |
|
|
12
17
|
|
|
13
18
|
## YouTube
|
|
14
19
|
|
|
@@ -106,6 +111,50 @@ const result = await manager.resolve('https://soundcloud.com/rick-astley-officia
|
|
|
106
111
|
|
|
107
112
|
- `soundcloud.com/USER/TRACK`
|
|
108
113
|
|
|
114
|
+
## Twitch & Mixcloud
|
|
115
|
+
|
|
116
|
+
Streaming support for live content and DJ sets.
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
// Twitch Live
|
|
120
|
+
await manager.resolve('https://twitch.tv/monstercat');
|
|
121
|
+
|
|
122
|
+
// Mixcloud Sets
|
|
123
|
+
await manager.resolve('https://www.mixcloud.com/spinninrecords/spinnin-sessions-550/');
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Bandcamp
|
|
127
|
+
|
|
128
|
+
Support for high-quality independent music.
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
await manager.resolve('https://monstercatmedia.bandcamp.com/track/the-governor');
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Direct URLs (HTTP)
|
|
135
|
+
|
|
136
|
+
Play raw audio files from any public URL.
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
await manager.resolve('https://example.com/audio.mp3');
|
|
140
|
+
await manager.resolve('https://cdn.discordapp.com/attachments/.../music.ogg');
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Local Files
|
|
144
|
+
|
|
145
|
+
Play files directly from the host system.
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// Absolute path
|
|
149
|
+
await manager.resolve('/home/user/music/track.mp3');
|
|
150
|
+
|
|
151
|
+
// Relative path
|
|
152
|
+
await manager.resolve('./assets/sound-effect.wav');
|
|
153
|
+
|
|
154
|
+
// File URI
|
|
155
|
+
await manager.resolve('file:///var/lib/music/song.flac');
|
|
156
|
+
```
|
|
157
|
+
|
|
109
158
|
## Auto-Detection
|
|
110
159
|
|
|
111
160
|
The `resolve()` method auto-detects the source from URLs:
|
|
@@ -115,9 +164,8 @@ The `resolve()` method auto-detects the source from URLs:
|
|
|
115
164
|
await manager.resolve('https://youtube.com/watch?v=dQw4w9WgXcQ');
|
|
116
165
|
await manager.resolve('https://open.spotify.com/track/4PTG3Z6ehGkBFwjybzWkR8');
|
|
117
166
|
await manager.resolve('https://soundcloud.com/rick-astley-official/never-gonna-give-you-up');
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
await manager.resolve('never gonna give you up');
|
|
167
|
+
await manager.resolve('https://twitch.tv/some-channel');
|
|
168
|
+
await manager.resolve('/path/to/local/file.mp3');
|
|
121
169
|
```
|
|
122
170
|
|
|
123
171
|
## Track Object
|
package/index.d.ts
CHANGED
|
@@ -163,6 +163,8 @@ declare module 'streamify-audio' {
|
|
|
163
163
|
static Manager: typeof Manager;
|
|
164
164
|
static Player: typeof Player;
|
|
165
165
|
static Queue: typeof Queue;
|
|
166
|
+
static getEffectPresetsInfo(): EffectPresetInfo[];
|
|
167
|
+
static EFFECT_PRESETS: Record<string, { filters: Filters; description: string }>;
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
// ========================================================================
|
|
@@ -237,6 +239,29 @@ declare module 'streamify-audio' {
|
|
|
237
239
|
on(event: 'playerDestroy', listener: (player: Player) => void): this;
|
|
238
240
|
}
|
|
239
241
|
|
|
242
|
+
export interface PlayOptions {
|
|
243
|
+
startPosition?: number;
|
|
244
|
+
seek?: number;
|
|
245
|
+
volume?: number;
|
|
246
|
+
filters?: Filters;
|
|
247
|
+
replace?: boolean;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export interface EffectPreset {
|
|
251
|
+
name: string;
|
|
252
|
+
intensity?: number;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export interface EffectPresetInfo {
|
|
256
|
+
name: string;
|
|
257
|
+
description: string;
|
|
258
|
+
filters: string[];
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface SetEffectPresetsOptions {
|
|
262
|
+
replace?: boolean;
|
|
263
|
+
}
|
|
264
|
+
|
|
240
265
|
export class Player extends EventEmitter {
|
|
241
266
|
constructor(manager: Manager, options: any);
|
|
242
267
|
|
|
@@ -261,7 +286,7 @@ declare module 'streamify-audio' {
|
|
|
261
286
|
disconnect(): boolean;
|
|
262
287
|
destroy(): void;
|
|
263
288
|
|
|
264
|
-
play(track: Track): Promise<void>;
|
|
289
|
+
play(track: Track, options?: PlayOptions): Promise<void>;
|
|
265
290
|
pause(destroyStream?: boolean): boolean;
|
|
266
291
|
resume(): Promise<boolean>;
|
|
267
292
|
skip(): Promise<Track | null>;
|
|
@@ -281,6 +306,11 @@ declare module 'streamify-audio' {
|
|
|
281
306
|
clearEQ(): Promise<boolean>;
|
|
282
307
|
getPresets(): string[];
|
|
283
308
|
|
|
309
|
+
setEffectPresets(presets: (string | EffectPreset)[], options?: SetEffectPresetsOptions): Promise<boolean>;
|
|
310
|
+
getActiveEffectPresets(): EffectPreset[];
|
|
311
|
+
clearEffectPresets(): Promise<boolean>;
|
|
312
|
+
getEffectPresets(): string[];
|
|
313
|
+
|
|
284
314
|
toJSON(): any;
|
|
285
315
|
|
|
286
316
|
on(event: 'trackStart', listener: (track: Track) => void): this;
|