streamify-audio 2.2.12 → 2.2.14

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "streamify-audio",
3
- "version": "2.2.12",
3
+ "version": "2.2.14",
4
4
  "description": "Dual-mode audio library: HTTP streaming proxy + Discord player (Lavalink alternative). Supports YouTube, Spotify, SoundCloud with audio filters.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/src/config.js CHANGED
@@ -26,8 +26,8 @@ const defaults = {
26
26
  bitrate: '128k',
27
27
  format: 'opus',
28
28
  vbr: true,
29
- compressionLevel: 10,
30
- application: 'audio'
29
+ compressionLevel: 5,
30
+ application: 'lowdelay'
31
31
  },
32
32
  ytdlp: {
33
33
  format: 'bestaudio/bestaudio[ext=webm]/bestaudio[ext=mp4]/18/22/best',
@@ -50,20 +50,16 @@ function findExecutable(name) {
50
50
  }
51
51
  }
52
52
 
53
- const MIN_YTDLP_VERSION = '2026.01.19';
54
-
55
- function checkYtdlpVersion(ytdlpPath) {
53
+ function autoUpdateYtdlp(ytdlpPath) {
56
54
  try {
57
- const version = execSync(`"${ytdlpPath}" --version`, { encoding: 'utf-8' }).trim();
58
- const versionDate = version.split('.').slice(0, 3).join('.');
59
-
60
- if (versionDate < MIN_YTDLP_VERSION) {
61
- console.warn(`[CONFIG] ⚠️ yt-dlp version ${version} is outdated`);
62
- console.warn(`[CONFIG] ⚠️ Live YouTube streams require yt-dlp >= ${MIN_YTDLP_VERSION}`);
63
- console.warn(`[CONFIG] ⚠️ Update with: yt-dlp --update-to nightly`);
55
+ const result = execSync(`"${ytdlpPath}" -U`, { encoding: 'utf-8', timeout: 30000 }).trim();
56
+ const updated = result.includes('Updated') || result.includes('Updating');
57
+ if (updated) {
58
+ const match = result.match(/Updated.*to\s+([\w@.\-]+)/);
59
+ console.log(`[CONFIG] yt-dlp updated to ${match ? match[1] : 'latest'}`);
64
60
  }
65
61
  } catch (e) {
66
- console.warn('[CONFIG] Could not check yt-dlp version:', e.message);
62
+ console.warn('[CONFIG] yt-dlp auto-update failed:', e.message);
67
63
  }
68
64
  }
69
65
 
@@ -157,7 +153,7 @@ function load(options = {}) {
157
153
  throw new Error('ffmpeg not found. Install it: apt install ffmpeg');
158
154
  }
159
155
 
160
- checkYtdlpVersion(config.ytdlpPath);
156
+ autoUpdateYtdlp(config.ytdlpPath);
161
157
 
162
158
  return config;
163
159
  }
@@ -48,6 +48,7 @@ class Player extends EventEmitter {
48
48
  this._prefetching = false;
49
49
  this._changingStream = false;
50
50
  this._manualSkip = false;
51
+ this._pauseStreamTimeout = null;
51
52
 
52
53
  this.autoLeave = {
53
54
  enabled: options.autoLeave?.enabled ?? true,
@@ -492,7 +493,7 @@ class Player extends EventEmitter {
492
493
  }
493
494
  }
494
495
 
495
- pause(destroyStream = true) {
496
+ pause(destroyStream = false) {
496
497
  if (!this._playing || this._paused) return false;
497
498
 
498
499
  this._positionMs = this.position;
@@ -502,10 +503,23 @@ class Player extends EventEmitter {
502
503
  this._clearPrefetch();
503
504
  this.stream.destroy();
504
505
  this.stream = null;
506
+ this.audioPlayer.stop(true);
507
+ } else {
508
+ this.audioPlayer.pause();
509
+ }
510
+
511
+ if (!destroyStream && this.stream) {
512
+ this._pauseStreamTimeout = setTimeout(() => {
513
+ if (this._paused && this.stream) {
514
+ log.info('PLAYER', 'Destroying paused stream after 5m idle');
515
+ this._clearPrefetch();
516
+ this.stream.destroy();
517
+ this.stream = null;
518
+ }
519
+ }, 300000);
505
520
  }
506
521
 
507
- this.audioPlayer.stop(true);
508
- log.info('PLAYER', `Paused playback at ${Math.floor(this._positionMs / 1000)}s (Reason: User Request)`);
522
+ log.info('PLAYER', `Paused playback at ${Math.floor(this._positionMs / 1000)}s (stream kept: ${!destroyStream})`);
509
523
  this._clearVoiceChannelStatus();
510
524
 
511
525
  return true;
@@ -514,8 +528,13 @@ class Player extends EventEmitter {
514
528
  async resume() {
515
529
  if (!this._playing || !this._paused) return false;
516
530
 
531
+ if (this._pauseStreamTimeout) {
532
+ clearTimeout(this._pauseStreamTimeout);
533
+ this._pauseStreamTimeout = null;
534
+ }
535
+
517
536
  if (!this.stream && this.queue.current) {
518
- log.info('PLAYER', `Resuming playback from ${Math.floor(this._positionMs / 1000)}s`);
537
+ log.info('PLAYER', `Resuming playback from ${Math.floor(this._positionMs / 1000)}s (recreating stream)`);
519
538
 
520
539
  this._changingStream = true;
521
540
  const track = this.queue.current;
@@ -547,6 +566,7 @@ class Player extends EventEmitter {
547
566
  this.audioPlayer.unpause();
548
567
  this._paused = false;
549
568
  this._positionTimestamp = Date.now();
569
+ log.info('PLAYER', `Resumed playback instantly at ${Math.floor(this._positionMs / 1000)}s`);
550
570
  this._updateVoiceChannelStatus(this.queue.current, true);
551
571
  }
552
572
 
@@ -630,10 +650,20 @@ class Player extends EventEmitter {
630
650
  return true;
631
651
  }
632
652
 
633
- setVolume(volume) {
653
+ async setVolume(volume) {
634
654
  const oldVolume = this._volume;
635
655
  this._volume = Math.max(0, Math.min(200, volume));
636
656
  log.info('PLAYER', `Volume adjusted: ${oldVolume}% -> ${this._volume}%`);
657
+
658
+ if (this._playing && this.queue.current && !this._paused) {
659
+ this._changingStream = true;
660
+ try {
661
+ await this._playTrack(this.queue.current, this.position);
662
+ } finally {
663
+ this._changingStream = false;
664
+ }
665
+ }
666
+
637
667
  return this._volume;
638
668
  }
639
669
 
@@ -801,6 +831,10 @@ class Player extends EventEmitter {
801
831
  clearTimeout(this._inactivityTimeout);
802
832
  this._inactivityTimeout = null;
803
833
  }
834
+ if (this._pauseStreamTimeout) {
835
+ clearTimeout(this._pauseStreamTimeout);
836
+ this._pauseStreamTimeout = null;
837
+ }
804
838
 
805
839
  this._clearPrefetch();
806
840
 
@@ -125,7 +125,7 @@ class StreamController {
125
125
  '--no-warnings',
126
126
  '--no-cache-dir',
127
127
  '--no-mtime',
128
- '--buffer-size', '16K',
128
+ '--buffer-size', '256K',
129
129
  '--quiet',
130
130
  '--retries', '3',
131
131
  '--fragment-retries', '3',
@@ -244,8 +244,8 @@ class StreamController {
244
244
 
245
245
  this.resource = createAudioResource(this.ffmpeg.stdout, {
246
246
  inputType: StreamType.OggOpus,
247
- inlineVolume: true,
248
- silencePaddingFrames: 10
247
+ inlineVolume: false,
248
+ silencePaddingFrames: 5
249
249
  });
250
250
 
251
251
  const elapsed = Date.now() - startTimestamp;
@@ -69,7 +69,7 @@ function buildEqualizer(bands) {
69
69
  function buildFfmpegArgs(filters = {}, config = {}) {
70
70
  filters = filters || {};
71
71
  const args = [
72
- '-thread_queue_size', '512',
72
+ '-thread_queue_size', '4096',
73
73
  '-i', 'pipe:0',
74
74
  '-vn',
75
75
  '-sn'
@@ -260,8 +260,9 @@ function buildFfmpegArgs(filters = {}, config = {}) {
260
260
  '-acodec', 'libopus',
261
261
  '-b:a', bitrate,
262
262
  '-vbr', config.audio?.vbr !== false ? 'on' : 'off',
263
- '-compression_level', (config.audio?.compressionLevel ?? 10).toString(),
264
- '-application', config.audio?.application || 'audio',
263
+ '-compression_level', (config.audio?.compressionLevel ?? 5).toString(),
264
+ '-frame_duration', '20',
265
+ '-application', config.audio?.application || 'lowdelay',
265
266
  '-f', 'ogg'
266
267
  );
267
268
  } else if (format === 'mp3') {
@@ -0,0 +1,26 @@
1
+ # Netscape HTTP Cookie File
2
+ # This file is generated by yt-dlp. Do not edit.
3
+
4
+ .youtube.com TRUE / TRUE 1800398983 __Secure-YENID 12.YTE=UfQjguVvlx3WLiJJHSjg4nPS-N-5O3Xj8RZj-wlLmRdjAvaF3TRdMzSmyUmo82Z4P-tggpd89U5d3hMDN886ZuUZUzi5XdEFEmHjL0YrTPBwPhD6pZx5CJ-3bNb3Eb_7eZuq_YlqQb0OX6Hvu2yYtWfWZPq7dZUjnJarOqJB0UaWu4jlsn27LkAmA9ecZK7Tj0NXQsIiDMR_y8pHe-kOfQ9LhLBeMnUWvR7GXsSOo_NqyfHrNnu4W8YnBd45ZUQIhwQ91X7lhuTkbBj3hYNJsWv0G7yda1NfB8j-nh8ZkordnGPIyv5QlCTd745j2DiGeS1GSa2jP2bClx7SoQxTjQ
5
+ .youtube.com TRUE / FALSE 0 PREF f6=40000000&tz=UTC&hl=en
6
+ .youtube.com TRUE / TRUE 1782082203 NID 527=aqYd85605VNHKMN7IAs-QcA6YfpJm6LGDAjKm929dxg81_ly4EHuc_A0jCgct9sjP-yDkNobeQPSES7fdZYHdzmlnHO_gGQ-oVCIbS3GQvSB89DCDEPB-toK2K62rr6iUVoTg3lcUG5xBhVXwoPPOD6VWWqegOp-IOhJhTb7Ijp_899mbKpj-4Elx8vNwUL0X-lJAe5Th-4Mxv9lDynXDH8axGjFhMHboeuTOHiIXRg10-4BoqyhAGFDhKNohiMwDc66EraGHim03-ZM
7
+ .youtube.com TRUE / TRUE 1800826170 __Secure-1PSIDTS sidts-CjUB7I_69MoGgU9hYcmJtLk5dHx1d0LjE7gLaoN86V6V3M8eyIyUH6LOPPFj2llBVQAVsulbqRAA
8
+ .youtube.com TRUE / TRUE 1800826170 __Secure-3PSIDTS sidts-CjUB7I_69MoGgU9hYcmJtLk5dHx1d0LjE7gLaoN86V6V3M8eyIyUH6LOPPFj2llBVQAVsulbqRAA
9
+ .youtube.com TRUE / FALSE 1803850170 HSID Ab4swI6vjvKUnUkhu
10
+ .youtube.com TRUE / TRUE 1803850170 SSID AaxSz8h17yLe-BmmX
11
+ .youtube.com TRUE / FALSE 1803850170 APISID pQgk6uQUwAqRtThp/Ape45AAtgBDxnzVco
12
+ .youtube.com TRUE / TRUE 1803850170 SAPISID y_RgVkrBXATC2XrL/Avlu8CWS6dwZ7LTEg
13
+ .youtube.com TRUE / TRUE 1803850170 __Secure-1PAPISID y_RgVkrBXATC2XrL/Avlu8CWS6dwZ7LTEg
14
+ .youtube.com TRUE / TRUE 1803850170 __Secure-3PAPISID y_RgVkrBXATC2XrL/Avlu8CWS6dwZ7LTEg
15
+ .youtube.com TRUE / FALSE 1803850170 SID g.a0006AhyolP4RoeyrQXcHsFnRGkuVLVIZ9QQsgpwFaXGd822GTtb98Ev6KQIph7SQPbMD4aekgACgYKAaMSARMSFQHGX2MijLBjWKdOhQm5VmUkh9wlRhoVAUF8yKqE_WWJQO8PgiZpXVV1MiB30076
16
+ .youtube.com TRUE / TRUE 1803850170 __Secure-1PSID g.a0006AhyolP4RoeyrQXcHsFnRGkuVLVIZ9QQsgpwFaXGd822GTtb9khH10B1YSjuMht-R8LNjAACgYKAQ8SARMSFQHGX2MiWX5D8_L5MAZK1TLabPQMghoVAUF8yKoFUiQLoi8zHLuskryhcx1P0076
17
+ .youtube.com TRUE / TRUE 1803850170 __Secure-3PSID g.a0006AhyolP4RoeyrQXcHsFnRGkuVLVIZ9QQsgpwFaXGd822GTtbc5VtVrqvDy9fWzO4vguctgACgYKAUkSARMSFQHGX2MinKYgh3CtvTW5E5T8SwXiERoVAUF8yKqzIJTS4ajNX5uO8nh3r0j10076
18
+ .youtube.com TRUE / TRUE 1803850170 LOGIN_INFO AFmmF2swRQIgH6IrdLYFOhW8xu4opIUHTGxAf33LzI5EXw6pdoqsh_gCIQCxYHQL4VZEyb3nE-rhXM6VU2ua99G4AhzKl4JJlzZBEQ:QUQ3MjNmeFpJOS1rVDgtM2I4cm50Z3M4NUplLTlSbXV4OFl4MTM5eUtHX3FEcVNmT2ltVFlSWmpQdlR2QTVqR29mZlUtTVh4OEhkOGw4Rkd5d2tQZm52NXJmQzdrMFJPVk5uYTFLNFFMZWlGelJhRVk1TkVaMm9Uby0xWlcwR3ozYkwwY2lWT21pV2dpU0lsWW5saFhMektISWxwUkRUcXl3
19
+ .youtube.com TRUE / FALSE 1802574095 SIDCC AKEyXzXX7z54BpXowMgsJlE2WhHTn-XJfl-HESWVwvIuF-XZTI41oT6RE3J3Gml8YFOIT5nIFwk
20
+ .youtube.com TRUE / TRUE 1802574095 __Secure-1PSIDCC AKEyXzVeAdBZZPpvwaPZA3WV5R_wg__e9qY7kWwe2K-V2jS627fDM29WKIr_3CezOeUVY52Isg
21
+ .youtube.com TRUE / TRUE 1802574095 __Secure-3PSIDCC AKEyXzUMNwuEmFU-r8lgBnKD4qe6OP3Wi8eCSkJQrt-4WsUPToW1hs_sfuT-OqMNTQruKLpnfw
22
+ .youtube.com TRUE / TRUE 1786573286 __Secure-YNID 15.YT=e2qw4ji33I446Rqr9VcM1oUeAeMMQtzK_4XR9QTmeKD0Fh5ONXvMNU0xEWTjLwPvQDQ8ObjZM8h7HSHQsS4Rle2Na0cTLhm7IYs0ZDhJs-pG-jFE9NSjq9bqlS_NihoFh3SP144sgCZpL8K_ZoLPZq0E5LPCl0X6cJ7GdXw1e3oY3AKiB_LIoaIaUyBOTazRokN4s_PtsLQrErQtnG7_ImvPSY5HDWb6qZCQujMU9pV0xDtXiHlJU4hzRyyN1GzbBy3mMzqpnqX53SU0gbofaLW55ep-iGeSySMDGmYTiLxc4tSr2Wy6XJ1-6AKpowymKn_Oam7j7vxK_rREysa_7g
23
+ .youtube.com TRUE / TRUE 0 YSC -LHUdUOZvC4
24
+ .youtube.com TRUE / TRUE 1786590095 VISITOR_INFO1_LIVE AuEVGsoJz2Y
25
+ .youtube.com TRUE / TRUE 1786590095 VISITOR_PRIVACY_METADATA CgJVUxIEGgAgVQ%3D%3D
26
+ .youtube.com TRUE / TRUE 1786573286 __Secure-ROLLOUT_TOKEN CIbdoKq8kOipXhC__cjij6WSAxjF-py1wNeSAw%3D%3D