streamify-audio 2.0.1 → 2.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "streamify-audio",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
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",
@@ -47,8 +47,17 @@ class StreamController {
47
47
  }
48
48
 
49
49
  const isYouTube = source === 'youtube' || source === 'spotify';
50
+ const isLive = this.track.isLive === true || this.track.duration === 0;
51
+
52
+ let formatString;
53
+ if (isLive) {
54
+ formatString = 'bestaudio[ext=webm]/bestaudio/best';
55
+ } else {
56
+ formatString = isYouTube ? '18/22/bestaudio[ext=webm]/bestaudio/best' : 'bestaudio/best';
57
+ }
58
+
50
59
  const ytdlpArgs = [
51
- '-f', isYouTube ? '18/22/bestaudio[ext=webm]/bestaudio/best' : 'bestaudio/best',
60
+ '-f', formatString,
52
61
  '--no-playlist',
53
62
  '--no-check-certificates',
54
63
  '--no-warnings',
@@ -58,6 +67,11 @@ class StreamController {
58
67
  url
59
68
  ];
60
69
 
70
+ if (isLive) {
71
+ ytdlpArgs.push('--live-from-start');
72
+ log.info('STREAM', `Live stream detected, using live-compatible format`);
73
+ }
74
+
61
75
  if (isYouTube) {
62
76
  ytdlpArgs.push('--extractor-args', 'youtube:player_client=web_creator');
63
77
  }
@@ -163,7 +177,7 @@ class StreamController {
163
177
  }
164
178
  });
165
179
 
166
- await this._waitForData();
180
+ await this._waitForData(isLive);
167
181
 
168
182
  this.resource = createAudioResource(this.ffmpeg.stdout, {
169
183
  inputType: StreamType.OggOpus,
@@ -177,12 +191,13 @@ class StreamController {
177
191
  return this.resource;
178
192
  }
179
193
 
180
- _waitForData() {
194
+ _waitForData(isLive = false) {
181
195
  return new Promise((resolve, reject) => {
196
+ const timeoutMs = isLive ? 30000 : 15000;
182
197
  const timeout = setTimeout(() => {
183
- log.warn('STREAM', `Timeout waiting for data, proceeding anyway (received: ${this.bytesReceived})`);
198
+ log.warn('STREAM', `Timeout waiting for data, proceeding anyway (received: ${this.bytesReceived}, isLive: ${isLive})`);
184
199
  resolve();
185
- }, 15000);
200
+ }, timeoutMs);
186
201
 
187
202
  let resolved = false;
188
203
 
@@ -39,12 +39,13 @@ async function search(query, limit, config) {
39
39
  const tracks = (data.entries || []).map(entry => ({
40
40
  id: entry.id,
41
41
  title: entry.title,
42
- duration: entry.duration,
42
+ duration: entry.duration || 0,
43
43
  author: entry.channel || entry.uploader,
44
44
  thumbnail: entry.thumbnails?.[0]?.url,
45
45
  uri: `https://www.youtube.com/watch?v=${entry.id}`,
46
46
  streamUrl: `/youtube/stream/${entry.id}`,
47
- source: 'youtube'
47
+ source: 'youtube',
48
+ isLive: entry.live_status === 'is_live' || entry.is_live === true || !entry.duration
48
49
  }));
49
50
  const elapsed = Date.now() - startTime;
50
51
  log.info('YOUTUBE', `Found ${tracks.length} results (${elapsed}ms)`);
@@ -87,15 +88,17 @@ async function getInfo(videoId, config) {
87
88
  }
88
89
  try {
89
90
  const data = JSON.parse(stdout);
91
+ const isLive = data.live_status === 'is_live' || data.is_live === true || !data.duration;
90
92
  resolve({
91
93
  id: data.id,
92
94
  title: data.title,
93
- duration: data.duration,
95
+ duration: data.duration || 0,
94
96
  author: data.channel || data.uploader,
95
97
  thumbnail: data.thumbnail,
96
98
  uri: data.webpage_url,
97
99
  streamUrl: `/youtube/stream/${data.id}`,
98
- source: 'youtube'
100
+ source: 'youtube',
101
+ isLive
99
102
  });
100
103
  } catch (e) {
101
104
  reject(new Error('Failed to parse yt-dlp output'));
@@ -238,12 +241,13 @@ async function getPlaylist(playlistId, config) {
238
241
  const tracks = (data.entries || []).map(entry => ({
239
242
  id: entry.id,
240
243
  title: entry.title,
241
- duration: entry.duration,
244
+ duration: entry.duration || 0,
242
245
  author: entry.channel || entry.uploader,
243
246
  thumbnail: entry.thumbnails?.[0]?.url,
244
247
  uri: `https://www.youtube.com/watch?v=${entry.id}`,
245
248
  streamUrl: `/youtube/stream/${entry.id}`,
246
- source: 'youtube'
249
+ source: 'youtube',
250
+ isLive: entry.live_status === 'is_live' || entry.is_live === true || !entry.duration
247
251
  }));
248
252
  log.info('YOUTUBE', `Playlist loaded: ${data.title || playlistId} (${tracks.length} tracks)`);
249
253
  resolve({