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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 LucasCzechia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,430 @@
1
+ # 🎵 Streamify
2
+
3
+ A dual-mode Node.js audio streaming engine that actually works with YouTube.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/streamify-audio.svg)](https://www.npmjs.com/package/streamify-audio)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
8
+
9
+ ---
10
+
11
+ ## ⚡ Why Streamify?
12
+
13
+ YouTube breaks music bots constantly. Lavalink times out. DisTube uses fragmented formats that fail. Most libraries don't work reliably anymore.
14
+
15
+ **Streamify works** because it:
16
+ - Uses **format 18** (progressive MP4, not fragmented DASH)
17
+ - Uses **web_creator** player client (bypasses restrictions)
18
+ - Pipes **directly** to Discord (no HTTP timeouts)
19
+ - Relies on **yt-dlp** (actively maintained, adapts fast)
20
+
21
+ ---
22
+
23
+ ## 🎯 Two Modes, One Library
24
+
25
+ Streamify offers two ways to stream audio:
26
+
27
+ | Mode | Use Case | How It Works |
28
+ |------|----------|--------------|
29
+ | 🎮 **Discord Player** | Discord music bots | Direct pipe to @discordjs/voice |
30
+ | 🌐 **HTTP Server** | Web apps, other platforms, debugging | REST API with stream URLs |
31
+
32
+ Both modes share the same providers, filters, and streaming engine.
33
+
34
+ ---
35
+
36
+ ## 🚀 Quick Start
37
+
38
+ ```bash
39
+ npm install streamify-audio
40
+ ```
41
+
42
+ ### 🎮 Discord Player Mode
43
+
44
+ For Discord bots — plays directly in voice channels.
45
+
46
+ ```bash
47
+ npm install @discordjs/voice @discordjs/opus
48
+ ```
49
+
50
+ ```javascript
51
+ const { Client, GatewayIntentBits } = require('discord.js');
52
+ const Streamify = require('streamify-audio');
53
+
54
+ const client = new Client({
55
+ intents: [
56
+ GatewayIntentBits.Guilds,
57
+ GatewayIntentBits.GuildVoiceStates,
58
+ GatewayIntentBits.GuildMessages,
59
+ GatewayIntentBits.MessageContent
60
+ ]
61
+ });
62
+
63
+ const manager = new Streamify.Manager(client, {
64
+ cookiesPath: './cookies.txt'
65
+ });
66
+
67
+ client.on('messageCreate', async (message) => {
68
+ if (message.content.startsWith('!play')) {
69
+ const query = message.content.slice(6);
70
+ const vc = message.member.voice.channel;
71
+
72
+ const result = await manager.search(query);
73
+ const player = await manager.create(message.guild.id, vc.id);
74
+
75
+ player.on('trackStart', (track) => {
76
+ message.channel.send(`🎵 Now playing: **${track.title}**`);
77
+ });
78
+
79
+ await player.play(result.tracks[0]);
80
+ }
81
+ });
82
+
83
+ client.login(process.env.TOKEN);
84
+ ```
85
+
86
+ ### 🌐 HTTP Server Mode
87
+
88
+ For web apps, external services, or any platform that can consume audio streams.
89
+
90
+ ```javascript
91
+ const Streamify = require('streamify-audio');
92
+
93
+ const streamify = new Streamify({
94
+ port: 8787,
95
+ host: '0.0.0.0'
96
+ });
97
+
98
+ await streamify.start();
99
+ console.log('Server running at http://localhost:8787');
100
+
101
+ // Search for tracks
102
+ const results = await streamify.youtube.search('never gonna give you up');
103
+ console.log(results.tracks[0].title);
104
+
105
+ // Get a stream URL (playable in any audio player)
106
+ const url = streamify.youtube.getStreamUrl(results.tracks[0].id);
107
+ // → http://localhost:8787/youtube/stream/dQw4w9WgXcQ
108
+
109
+ // With filters
110
+ const urlWithFilters = streamify.youtube.getStreamUrl('dQw4w9WgXcQ', {
111
+ bass: 10,
112
+ speed: 1.25,
113
+ nightcore: true
114
+ });
115
+ // → http://localhost:8787/youtube/stream/dQw4w9WgXcQ?bass=10&speed=1.25&nightcore=true
116
+ ```
117
+
118
+ ---
119
+
120
+ ## 🌐 HTTP Server API
121
+
122
+ When running in HTTP mode, Streamify exposes a REST API:
123
+
124
+ ### Endpoints
125
+
126
+ | Method | Endpoint | Description |
127
+ |--------|----------|-------------|
128
+ | `GET` | `/health` | Server status |
129
+ | `GET` | `/stats` | Memory, uptime, active streams |
130
+ | `GET` | `/streams` | List all active streams |
131
+ | `GET` | `/youtube/search?q=query` | Search YouTube |
132
+ | `GET` | `/youtube/info/:id` | Get track info |
133
+ | `GET` | `/youtube/stream/:id` | Stream audio (OGG/Opus) |
134
+ | `GET` | `/spotify/search?q=query` | Search Spotify |
135
+ | `GET` | `/spotify/stream/:id` | Stream Spotify track |
136
+ | `GET` | `/soundcloud/search?q=query` | Search SoundCloud |
137
+ | `GET` | `/soundcloud/stream/:id` | Stream SoundCloud track |
138
+
139
+ ### Stream Parameters
140
+
141
+ Add query parameters to `/stream` endpoints for real-time audio processing:
142
+
143
+ ```
144
+ /youtube/stream/dQw4w9WgXcQ?bass=10&speed=1.25&nightcore=true
145
+ ```
146
+
147
+ ### Example: Web Audio Player
148
+
149
+ ```html
150
+ <audio controls>
151
+ <source src="http://localhost:8787/youtube/stream/dQw4w9WgXcQ" type="audio/ogg">
152
+ </audio>
153
+ ```
154
+
155
+ ### Example: Fetch from Backend
156
+
157
+ ```javascript
158
+ // Search
159
+ const response = await fetch('http://localhost:8787/youtube/search?q=lofi+beats');
160
+ const { tracks } = await response.json();
161
+
162
+ // Play in browser
163
+ const audio = new Audio(`http://localhost:8787/youtube/stream/${tracks[0].id}`);
164
+ audio.play();
165
+ ```
166
+
167
+ ---
168
+
169
+ ## ✨ Features
170
+
171
+ | Feature | Discord | HTTP |
172
+ |---------|:-------:|:----:|
173
+ | 🎵 YouTube, Spotify, SoundCloud | ✅ | ✅ |
174
+ | 📋 Playlists & Albums | ✅ | ✅ |
175
+ | 🎚️ 25+ Audio Filters | ✅ | ✅ |
176
+ | 🎛️ 15-Band Equalizer | ✅ | ✅ |
177
+ | 🎨 15 EQ Presets | ✅ | ✅ |
178
+ | ⏭️ Instant Skip (prefetch) | ✅ | — |
179
+ | ⏸️ Auto-pause when alone | ✅ | — |
180
+ | ▶️ Auto-resume on rejoin | ✅ | — |
181
+ | 🚪 Auto-leave on inactivity | ✅ | — |
182
+ | 📻 Autoplay related tracks | ✅ | — |
183
+ | 🚫 Sponsorblock | ✅ | ✅ |
184
+ | 📊 Stream position tracking | ✅ | ✅ |
185
+ | 🔌 No Lavalink/Java needed | ✅ | ✅ |
186
+
187
+ ---
188
+
189
+ ## 🎮 Discord Player Features
190
+
191
+ ### Queue Management
192
+
193
+ ```javascript
194
+ const player = manager.get(guildId);
195
+
196
+ // Add tracks
197
+ player.queue.add(track);
198
+ player.queue.addMany(tracks);
199
+
200
+ // Controls
201
+ await player.skip();
202
+ await player.previous();
203
+ await player.seek(30000); // 30 seconds
204
+
205
+ // Queue operations
206
+ player.queue.shuffle();
207
+ player.queue.move(0, 5);
208
+ player.queue.remove(2);
209
+ player.queue.clear();
210
+
211
+ // Loop modes
212
+ player.setLoop('off'); // No loop
213
+ player.setLoop('track'); // Loop current track
214
+ player.setLoop('queue'); // Loop entire queue
215
+ ```
216
+
217
+ ### Events
218
+
219
+ ```javascript
220
+ player.on('trackStart', (track) => {
221
+ console.log(`Playing: ${track.title}`);
222
+ });
223
+
224
+ player.on('trackEnd', (track, reason) => {
225
+ console.log(`Ended: ${track.title} (${reason})`);
226
+ });
227
+
228
+ player.on('queueEnd', () => {
229
+ console.log('Queue finished');
230
+ });
231
+
232
+ player.on('trackError', (track, error) => {
233
+ console.error(`Error: ${error.message}`);
234
+ });
235
+
236
+ // Voice events
237
+ player.on('userJoin', (member, count) => { });
238
+ player.on('userLeave', (member, count) => { });
239
+ player.on('channelEmpty', () => { });
240
+ player.on('autoPause', (userCount) => { });
241
+ player.on('autoResume', (userCount) => { });
242
+ ```
243
+
244
+ ### Auto Features
245
+
246
+ ```javascript
247
+ const manager = new Streamify.Manager(client, {
248
+ autoLeave: {
249
+ enabled: true,
250
+ emptyDelay: 30000, // Leave after 30s if channel empty
251
+ inactivityTimeout: 300000 // Leave after 5min of no playback
252
+ },
253
+ autoPause: {
254
+ enabled: true,
255
+ minUsers: 1 // Pause when fewer than 1 user (excluding bot)
256
+ },
257
+ autoplay: {
258
+ enabled: true,
259
+ maxTracks: 5 // Add up to 5 related tracks when queue ends
260
+ }
261
+ });
262
+ ```
263
+
264
+ ---
265
+
266
+ ## 🎛️ Filters & Presets
267
+
268
+ Both modes support the same filters:
269
+
270
+ ```javascript
271
+ // Discord mode
272
+ await player.setFilter('bass', 10);
273
+ await player.setFilter('nightcore', true);
274
+ await player.setPreset('rock');
275
+
276
+ // HTTP mode (via URL params)
277
+ const url = streamify.getStreamUrl('youtube', 'dQw4w9WgXcQ', {
278
+ bass: 10,
279
+ nightcore: true,
280
+ preset: 'rock'
281
+ });
282
+ ```
283
+
284
+ ### EQ Presets
285
+
286
+ `flat` · `rock` · `pop` · `jazz` · `classical` · `electronic` · `hiphop` · `acoustic` · `rnb` · `latin` · `loudness` · `piano` · `vocal` · `bass_heavy` · `treble_heavy`
287
+
288
+ <details>
289
+ <summary><b>All available filters</b></summary>
290
+
291
+ | Filter | Type | Description |
292
+ |--------|------|-------------|
293
+ | `bass` | -20 to 20 | Bass boost/cut |
294
+ | `treble` | -20 to 20 | Treble boost/cut |
295
+ | `speed` | 0.5 to 2.0 | Playback speed |
296
+ | `pitch` | 0.5 to 2.0 | Pitch shift |
297
+ | `volume` | 0 to 200 | Volume % |
298
+ | `nightcore` | boolean | Speed + pitch up |
299
+ | `vaporwave` | boolean | Speed + pitch down |
300
+ | `8d` | boolean | Rotating audio |
301
+ | `karaoke` | boolean | Reduce vocals |
302
+ | `bassboost` | boolean | Heavy bass |
303
+ | `tremolo` | object | Volume wobble |
304
+ | `vibrato` | object | Pitch wobble |
305
+ | `rotation` | object | 8D with custom speed |
306
+ | `flanger` | boolean | Flanger effect |
307
+ | `phaser` | boolean | Phaser effect |
308
+ | `chorus` | boolean | Chorus effect |
309
+ | `compressor` | boolean | Dynamic compression |
310
+ | `normalizer` | boolean | Loudness normalization |
311
+ | `lowpass` | Hz | Cut highs |
312
+ | `highpass` | Hz | Cut lows |
313
+ | `bandpass` | object | Bandpass filter |
314
+ | `bandreject` | object | Notch filter |
315
+ | `lowshelf` | object | Low shelf EQ |
316
+ | `highshelf` | object | High shelf EQ |
317
+ | `peaking` | object | Parametric EQ |
318
+ | `mono` | boolean | Stereo to mono |
319
+ | `surround` | boolean | Surround effect |
320
+
321
+ </details>
322
+
323
+ ---
324
+
325
+ ## 🆚 Why Not Lavalink?
326
+
327
+ | | Streamify | Lavalink |
328
+ |--|:---------:|:--------:|
329
+ | Setup | `npm install` | Java + separate server |
330
+ | YouTube | ✅ Works | ⚠️ Timeout issues |
331
+ | Latency | ~3s start | Variable |
332
+ | Skip | Instant | 2-3s |
333
+ | Dependencies | Node.js only | Java 17+ |
334
+ | Filters | Built-in | Requires config |
335
+ | Auto-pause | ✅ Built-in | ❌ DIY |
336
+ | HTTP API | ✅ Built-in | ❌ WebSocket only |
337
+
338
+ ---
339
+
340
+ ## ⚙️ Configuration
341
+
342
+ ### Discord Mode
343
+
344
+ ```javascript
345
+ const manager = new Streamify.Manager(client, {
346
+ ytdlpPath: '/usr/local/bin/yt-dlp',
347
+ ffmpegPath: '/usr/bin/ffmpeg',
348
+ cookiesPath: './cookies.txt',
349
+ providers: {
350
+ youtube: { enabled: true },
351
+ spotify: { enabled: true },
352
+ soundcloud: { enabled: false } // Disable SoundCloud
353
+ },
354
+ spotify: {
355
+ clientId: 'your_client_id',
356
+ clientSecret: 'your_client_secret'
357
+ },
358
+ audio: {
359
+ bitrate: '128k',
360
+ format: 'opus'
361
+ },
362
+ defaultVolume: 80,
363
+ maxPreviousTracks: 25,
364
+ sponsorblock: {
365
+ enabled: true,
366
+ categories: ['sponsor', 'selfpromo', 'interaction', 'intro', 'outro', 'preview', 'music_offtopic']
367
+ }
368
+ });
369
+ ```
370
+
371
+ ### HTTP Mode
372
+
373
+ ```javascript
374
+ const streamify = new Streamify({
375
+ port: 8787,
376
+ host: '0.0.0.0',
377
+ ytdlpPath: '/usr/local/bin/yt-dlp',
378
+ ffmpegPath: '/usr/bin/ffmpeg',
379
+ cookiesPath: './cookies.txt',
380
+ providers: {
381
+ youtube: { enabled: true },
382
+ spotify: { enabled: true },
383
+ soundcloud: { enabled: true }
384
+ },
385
+ spotify: {
386
+ clientId: 'your_client_id',
387
+ clientSecret: 'your_client_secret'
388
+ },
389
+ audio: {
390
+ bitrate: '128k',
391
+ format: 'opus'
392
+ },
393
+ logLevel: 'info'
394
+ });
395
+ ```
396
+
397
+ ---
398
+
399
+ ## 📋 Requirements
400
+
401
+ - **Node.js** 18+
402
+ - **yt-dlp** — `pip install yt-dlp`
403
+ - **ffmpeg** — `apt install ffmpeg`
404
+ - **@discordjs/voice** + **@discordjs/opus** — Discord mode only
405
+
406
+ ---
407
+
408
+ ## 📖 Documentation
409
+
410
+ | Guide | Description |
411
+ |-------|-------------|
412
+ | [Quick Start](./docs/quick-start.md) | Get running in 5 minutes |
413
+ | [Configuration](./docs/configuration.md) | All options explained |
414
+ | [Filters](./docs/filters.md) | Audio filters, EQ, presets |
415
+ | [Events](./docs/discord/events.md) | Player events reference |
416
+ | [Examples](./docs/examples/basic-bot.md) | Full bot examples |
417
+
418
+ ---
419
+
420
+ ## 🔗 Links
421
+
422
+ - [GitHub](https://github.com/LucasCzechia/streamify)
423
+ - [npm](https://www.npmjs.com/package/streamify-audio)
424
+ - [Issues](https://github.com/LucasCzechia/streamify/issues)
425
+
426
+ ---
427
+
428
+ ## 📄 License
429
+
430
+ MIT © [LucasCzechia](https://github.com/LucasCzechia)
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+
3
+ const Streamify = require('../index');
4
+
5
+ const args = process.argv.slice(2);
6
+ const options = {};
7
+
8
+ for (let i = 0; i < args.length; i++) {
9
+ const arg = args[i];
10
+ if (arg === '--config' || arg === '-c') {
11
+ options.configPath = args[++i];
12
+ } else if (arg === '--port' || arg === '-p') {
13
+ options.port = parseInt(args[++i], 10);
14
+ } else if (arg === '--host' || arg === '-h') {
15
+ options.host = args[++i];
16
+ } else if (arg === '--cookies') {
17
+ options.cookiesPath = args[++i];
18
+ } else if (arg === '--help') {
19
+ console.log(`
20
+ Streamify - Audio Streaming Proxy for Discord Bots
21
+
22
+ Usage: streamify [options]
23
+
24
+ Options:
25
+ -c, --config <path> Path to config file (default: ./config.json)
26
+ -p, --port <port> Port to listen on (default: 8787)
27
+ -h, --host <host> Host to bind to (default: 0.0.0.0)
28
+ --cookies <path> Path to YouTube cookies file
29
+ --help Show this help message
30
+
31
+ Environment Variables:
32
+ PORT Server port
33
+ HOST Server host
34
+ SPOTIFY_CLIENT_ID Spotify API client ID
35
+ SPOTIFY_CLIENT_SECRET Spotify API client secret
36
+ COOKIES_PATH Path to cookies file
37
+ YTDLP_PATH Path to yt-dlp binary
38
+
39
+ Examples:
40
+ streamify
41
+ streamify --port 3000
42
+ streamify --config ./my-config.json
43
+ PORT=3000 SPOTIFY_CLIENT_ID=xxx streamify
44
+ `);
45
+ process.exit(0);
46
+ }
47
+ }
48
+
49
+ const log = require('../src/utils/logger');
50
+ log.init(options);
51
+ log.banner();
52
+
53
+ const server = new Streamify(options);
54
+
55
+ server.start().then(() => {
56
+ console.log(`
57
+ Ready! API Endpoints:
58
+ GET /health - Service health
59
+ GET /stats - Service statistics
60
+
61
+ GET /youtube/search - Search YouTube
62
+ GET /youtube/stream/:id - Stream from YouTube
63
+
64
+ GET /spotify/search - Search Spotify
65
+ GET /spotify/stream/:id - Stream from Spotify
66
+
67
+ GET /soundcloud/search - Search SoundCloud
68
+ GET /soundcloud/stream/:id - Stream from SoundCloud
69
+
70
+ Filter Parameters (add to stream URLs):
71
+ ?bass=5 Bass boost (-20 to 20)
72
+ ?treble=5 Treble boost (-20 to 20)
73
+ ?speed=1.25 Playback speed (0.5 to 2.0)
74
+ ?pitch=1.1 Pitch shift (0.5 to 2.0)
75
+ ?volume=150 Volume percentage (0 to 200)
76
+ ?nightcore=true Nightcore preset
77
+ ?vaporwave=true Vaporwave preset
78
+ ?bassboost=true Bass boost preset
79
+ ?8d=true 8D audio effect
80
+ `);
81
+ }).catch(err => {
82
+ console.error('Failed to start:', err.message);
83
+ process.exit(1);
84
+ });
package/docs/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Streamify Documentation
2
+
3
+ ## Getting Started
4
+
5
+ - [Quick Start](./quick-start.md) — Get up and running in 5 minutes
6
+ - [Configuration](./configuration.md) — All configuration options
7
+
8
+ ## Discord Player Mode
9
+
10
+ - [Manager](./discord/manager.md) — Create and manage players
11
+ - [Player](./discord/player.md) — Playback control and state
12
+ - [Queue](./discord/queue.md) — Queue management
13
+ - [Events](./discord/events.md) — All player events
14
+
15
+ ## HTTP Server Mode
16
+
17
+ - [Server Setup](./http/server.md) — Start the HTTP server
18
+ - [Endpoints](./http/endpoints.md) — API reference
19
+
20
+ ## Features
21
+
22
+ - [Filters](./filters.md) — Audio filters and presets
23
+ - [Sources](./sources.md) — YouTube, Spotify, SoundCloud
24
+ - [Automation](./automation.md) — Auto-pause, auto-leave, autoplay
25
+ - [Sponsorblock](./sponsorblock.md) — Skip YouTube sponsors
26
+
27
+ ## Examples
28
+
29
+ - [Basic Discord Bot](./examples/basic-bot.md)
30
+ - [Advanced Bot with Queue](./examples/advanced-bot.md)
31
+ - [HTTP Server with Lavalink](./examples/lavalink.md)