recker 1.0.20-next.de24f7d → 1.0.20

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.
@@ -7,7 +7,6 @@ import { DedupOptions } from '../plugins/dedup.js';
7
7
  import { ReckerWebSocket, type WebSocketOptions } from '../websocket/client.js';
8
8
  import { type WhoisOptions, type WhoisResult } from '../utils/whois.js';
9
9
  import { type ScrapePromise } from '../plugins/scrape.js';
10
- import { HlsPromise, type HlsOptions } from '../plugins/hls.js';
11
10
  interface ClientCacheConfig extends Omit<CacheOptions, 'storage'> {
12
11
  storage?: CacheStorage;
13
12
  driver?: 'memory' | 'file';
@@ -112,7 +111,6 @@ export declare class Client {
112
111
  ws(path: string, options?: WebSocketOptions): ReckerWebSocket;
113
112
  whois(query: string, options?: WhoisOptions): Promise<WhoisResult>;
114
113
  isDomainAvailable(domain: string, options?: WhoisOptions): Promise<boolean>;
115
- hls(manifestUrl: string, options?: HlsOptions): HlsPromise;
116
114
  }
117
115
  export declare function createClient(options?: ExtendedClientOptions): Client;
118
116
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
@@ -22,7 +22,6 @@ import { ReckerWebSocket } from '../websocket/client.js';
22
22
  import { whois as performWhois, isDomainAvailable } from '../utils/whois.js';
23
23
  import { MemoryCookieJar } from '../cookies/memory-cookie-jar.js';
24
24
  import { scrape as scrapeHelper } from '../plugins/scrape.js';
25
- import { HlsPromise } from '../plugins/hls.js';
26
25
  export class Client {
27
26
  baseUrl;
28
27
  middlewares;
@@ -658,9 +657,6 @@ export class Client {
658
657
  async isDomainAvailable(domain, options) {
659
658
  return isDomainAvailable(domain, options);
660
659
  }
661
- hls(manifestUrl, options = {}) {
662
- return new HlsPromise(this, manifestUrl, options);
663
- }
664
660
  }
665
661
  export function createClient(options = {}) {
666
662
  return new Client(options);
@@ -1,106 +1,33 @@
1
- import type { Client } from '../core/client.js';
2
- import { type WriteStream } from 'node:fs';
3
- import { Writable } from 'node:stream';
4
- export interface HlsVariant {
1
+ import { Client } from '../core/client.js';
2
+ export interface Variant {
5
3
  url: string;
6
4
  bandwidth?: number;
7
5
  resolution?: string;
8
- codecs?: string;
9
- name?: string;
10
6
  }
11
- export interface HlsSegment {
7
+ export interface Segment {
12
8
  url: string;
13
9
  duration: number;
14
10
  sequence: number;
15
- key?: HlsKeyInfo;
16
- discontinuity?: boolean;
17
- programDateTime?: Date;
11
+ key?: KeyInfo;
18
12
  }
19
- export interface HlsKeyInfo {
20
- method: 'NONE' | 'AES-128' | 'SAMPLE-AES';
13
+ export interface KeyInfo {
14
+ method: string;
21
15
  uri?: string;
22
16
  iv?: string;
23
17
  }
24
- export interface HlsPlaylist {
25
- segments: HlsSegment[];
26
- targetDuration: number;
27
- mediaSequence: number;
28
- endList: boolean;
29
- playlistType?: 'VOD' | 'EVENT';
30
- discontinuitySequence: number;
18
+ export interface HlsHooks {
19
+ onManifest?: (manifest: string, url: string) => string | void;
20
+ onVariantSelected?: (variants: Variant[], defaultSelected: Variant) => Variant | void;
21
+ onSegment?: (segment: Segment) => Segment | void | null;
22
+ onKey?: (key: KeyInfo) => KeyInfo | void;
31
23
  }
32
- export interface HlsMasterPlaylist {
33
- variants: HlsVariant[];
34
- isMaster: true;
35
- }
36
- export interface SegmentData {
37
- sequence: number;
38
- duration: number;
39
- data: Uint8Array;
40
- url: string;
41
- downloadedAt: Date;
42
- }
43
- export interface HlsProgress {
44
- downloadedSegments: number;
45
- totalSegments?: number;
46
- downloadedBytes: number;
47
- currentSegment: number;
48
- isLive: boolean;
49
- elapsed: number;
50
- }
51
- export interface HlsOptions {
52
- mode?: 'merge' | 'chunks';
53
- format?: 'ts' | 'mp4' | 'mkv';
54
- live?: boolean | {
55
- duration: number;
56
- };
57
- quality?: 'highest' | 'lowest' | {
58
- bandwidth?: number;
59
- resolution?: string;
60
- };
24
+ export interface HlsOptions extends HlsHooks {
61
25
  concurrency?: number;
62
- onSegment?: (segment: SegmentData) => void | Promise<void>;
63
- onProgress?: (progress: HlsProgress) => void;
26
+ merge?: boolean;
27
+ live?: boolean;
28
+ duration?: number;
29
+ onInfo?: (message: string) => void;
64
30
  onError?: (error: Error) => void;
65
- headers?: Record<string, string>;
66
- }
67
- type DownloadDest = string | ((segment: HlsSegment) => string);
68
- export declare class HlsPromise implements Promise<void> {
69
- private client;
70
- private manifestUrl;
71
- private options;
72
- private seenSequences;
73
- private downloadedBytes;
74
- private downloadedSegments;
75
- private startTime;
76
- private aborted;
77
- private abortController;
78
- constructor(client: Client, manifestUrl: string, options?: HlsOptions);
79
- get [Symbol.toStringTag](): string;
80
- then<TResult1 = void, TResult2 = never>(onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
81
- catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null): Promise<void | TResult>;
82
- finally(onfinally?: (() => void) | null): Promise<void>;
83
- cancel(): void;
84
- download(dest: DownloadDest): Promise<void>;
85
- stream(): AsyncGenerator<SegmentData>;
86
- pipe(writable: Writable | WriteStream): Promise<void>;
87
- info(): Promise<{
88
- master?: HlsMasterPlaylist;
89
- playlist?: HlsPlaylist;
90
- selectedVariant?: HlsVariant;
91
- isLive: boolean;
92
- totalDuration?: number;
93
- }>;
94
- private resolveMediaPlaylist;
95
- private fetchMediaPlaylist;
96
- private downloadSegment;
97
- private downloadMerged;
98
- private downloadChunks;
99
- private isLiveMode;
100
- private getMaxDuration;
101
- private emitProgress;
102
- private sleep;
103
31
  }
104
- export declare function hls(client: Client, manifestUrl: string, options?: HlsOptions): HlsPromise;
105
- export type { HlsVariant as Variant, HlsSegment as Segment, HlsKeyInfo as KeyInfo, };
32
+ export declare function downloadHls(client: Client, manifestUrl: string, outputPath: string, options?: HlsOptions): Promise<void>;
106
33
  //# sourceMappingURL=hls.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hls.d.ts","sourceRoot":"","sources":["../../src/plugins/hls.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hls.d.ts","sourceRoot":"","sources":["../../src/plugins/hls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAK3C,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,QAAQ;IAEvB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAE9D,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,CAAC;IAEtF,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC;IAExD,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAmHD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,UAAe,iBA+JzB"}
@@ -1,395 +1,225 @@
1
1
  import { createWriteStream } from 'node:fs';
2
- import { mkdir } from 'node:fs/promises';
3
2
  import { dirname, join } from 'node:path';
4
- function parseAttributes(line, prefix) {
5
- const attrs = {};
6
- const content = line.substring(prefix.length);
7
- const regex = /([A-Z0-9-]+)=(?:"([^"]*)"|([^,]*))/g;
8
- let match;
9
- while ((match = regex.exec(content)) !== null) {
10
- attrs[match[1]] = match[2] ?? match[3];
11
- }
12
- return attrs;
13
- }
14
- function resolveUrl(url, baseUrl) {
15
- if (url.startsWith('http://') || url.startsWith('https://')) {
16
- return url;
17
- }
18
- try {
19
- const base = new URL(baseUrl);
20
- const basePath = base.pathname.substring(0, base.pathname.lastIndexOf('/') + 1);
21
- return new URL(url, base.origin + basePath).toString();
22
- }
23
- catch {
24
- return url;
25
- }
26
- }
27
- function parseMasterPlaylist(content, baseUrl) {
28
- const lines = content.split('\n');
29
- const variants = [];
30
- let pendingVariant = {};
31
- for (const rawLine of lines) {
32
- const line = rawLine.trim();
33
- if (!line)
34
- continue;
35
- if (line.startsWith('#EXT-X-STREAM-INF:')) {
36
- const attrs = parseAttributes(line, '#EXT-X-STREAM-INF:');
37
- pendingVariant = {
38
- bandwidth: attrs.BANDWIDTH ? parseInt(attrs.BANDWIDTH, 10) : undefined,
39
- resolution: attrs.RESOLUTION,
40
- codecs: attrs.CODECS,
41
- name: attrs.NAME,
42
- };
43
- }
44
- else if (!line.startsWith('#') && pendingVariant.bandwidth !== undefined) {
45
- variants.push({
46
- ...pendingVariant,
47
- url: resolveUrl(line, baseUrl),
48
- });
49
- pendingVariant = {};
50
- }
51
- }
52
- return { variants, isMaster: true };
53
- }
54
- function parseMediaPlaylist(content, baseUrl) {
3
+ import { mkdir, readdir, readFile, rm } from 'node:fs/promises';
4
+ function parseM3u8(content, baseUrl) {
55
5
  const lines = content.split('\n');
56
6
  const segments = [];
57
- let targetDuration = 5;
7
+ let currentDuration = 0;
58
8
  let mediaSequence = 0;
59
- let discontinuitySequence = 0;
9
+ let targetDuration = 5;
60
10
  let endList = false;
61
- let playlistType;
62
- let currentDuration = 0;
63
11
  let currentKey;
64
- let currentDiscontinuity = false;
65
- let currentProgramDateTime;
66
- let segmentIndex = 0;
67
- for (const rawLine of lines) {
68
- const line = rawLine.trim();
12
+ for (let i = 0; i < lines.length; i++) {
13
+ const line = lines[i].trim();
69
14
  if (!line)
70
15
  continue;
71
16
  if (line.startsWith('#EXT-X-TARGETDURATION:')) {
72
- targetDuration = parseInt(line.split(':')[1], 10);
17
+ targetDuration = parseFloat(line.split(':')[1]);
73
18
  }
74
19
  else if (line.startsWith('#EXT-X-MEDIA-SEQUENCE:')) {
75
20
  mediaSequence = parseInt(line.split(':')[1], 10);
76
21
  }
77
- else if (line.startsWith('#EXT-X-DISCONTINUITY-SEQUENCE:')) {
78
- discontinuitySequence = parseInt(line.split(':')[1], 10);
79
- }
80
- else if (line.startsWith('#EXT-X-PLAYLIST-TYPE:')) {
81
- playlistType = line.split(':')[1];
82
- }
83
- else if (line === '#EXT-X-ENDLIST') {
22
+ else if (line.startsWith('#EXT-X-ENDLIST')) {
84
23
  endList = true;
85
24
  }
86
- else if (line === '#EXT-X-DISCONTINUITY') {
87
- currentDiscontinuity = true;
88
- }
89
- else if (line.startsWith('#EXT-X-PROGRAM-DATE-TIME:')) {
90
- currentProgramDateTime = new Date(line.split(':').slice(1).join(':'));
91
- }
92
25
  else if (line.startsWith('#EXT-X-KEY:')) {
93
- const attrs = parseAttributes(line, '#EXT-X-KEY:');
94
- if (attrs.METHOD === 'NONE') {
95
- currentKey = undefined;
96
- }
97
- else {
26
+ const attrs = line.substring(11);
27
+ const methodMatch = attrs.match(/METHOD=([^,]+)/);
28
+ const uriMatch = attrs.match(/URI="([^"]+)"/);
29
+ const ivMatch = attrs.match(/IV=([^,]+)/);
30
+ if (methodMatch) {
98
31
  currentKey = {
99
- method: attrs.METHOD,
100
- uri: attrs.URI ? resolveUrl(attrs.URI, baseUrl) : undefined,
101
- iv: attrs.IV,
32
+ method: methodMatch[1],
33
+ uri: uriMatch ? uriMatch[1] : undefined,
34
+ iv: ivMatch ? ivMatch[1] : undefined
102
35
  };
103
36
  }
104
37
  }
105
38
  else if (line.startsWith('#EXTINF:')) {
106
- const durationStr = line.substring(8).split(',')[0];
39
+ const durationStr = line.substring(8).split(',', 1)[0];
107
40
  currentDuration = parseFloat(durationStr);
108
41
  }
109
42
  else if (!line.startsWith('#')) {
43
+ let url = line;
44
+ if (!url.startsWith('http')) {
45
+ try {
46
+ const base = new URL(baseUrl);
47
+ const basePath = base.pathname.substring(0, base.pathname.lastIndexOf('/') + 1);
48
+ url = new URL(url, base.origin + basePath).toString();
49
+ }
50
+ catch {
51
+ }
52
+ }
110
53
  segments.push({
111
- url: resolveUrl(line, baseUrl),
54
+ url,
112
55
  duration: currentDuration,
113
- sequence: mediaSequence + segmentIndex,
114
- key: currentKey,
115
- discontinuity: currentDiscontinuity,
116
- programDateTime: currentProgramDateTime,
56
+ sequence: 0,
57
+ key: currentKey
117
58
  });
118
- segmentIndex++;
119
- currentDiscontinuity = false;
120
- currentProgramDateTime = undefined;
121
59
  }
122
60
  }
123
- return {
124
- segments,
125
- targetDuration,
126
- mediaSequence,
127
- endList,
128
- playlistType,
129
- discontinuitySequence,
130
- };
131
- }
132
- function isMasterPlaylist(content) {
133
- return content.includes('#EXT-X-STREAM-INF');
61
+ segments.forEach((seg, idx) => {
62
+ seg.sequence = mediaSequence + idx;
63
+ });
64
+ return { segments, targetDuration, endList, mediaSequence };
134
65
  }
135
- function selectVariant(variants, quality) {
136
- if (!variants.length) {
137
- throw new Error('No variants found in master playlist');
138
- }
139
- const sorted = [...variants].sort((a, b) => (a.bandwidth ?? 0) - (b.bandwidth ?? 0));
140
- if (quality === 'lowest') {
141
- return sorted[0];
142
- }
143
- if (quality === 'highest' || quality === undefined) {
144
- return sorted[sorted.length - 1];
145
- }
146
- if (quality.resolution) {
147
- const match = variants.find((v) => v.resolution === quality.resolution);
148
- if (match)
149
- return match;
150
- }
151
- if (quality.bandwidth) {
152
- const target = quality.bandwidth;
153
- return sorted.reduce((prev, curr) => {
154
- const prevDiff = Math.abs((prev.bandwidth ?? 0) - target);
155
- const currDiff = Math.abs((curr.bandwidth ?? 0) - target);
156
- return currDiff < prevDiff ? curr : prev;
157
- });
66
+ function parseVariants(content, baseUrl) {
67
+ const lines = content.split('\n');
68
+ const variants = [];
69
+ let currentBandwidth;
70
+ let currentResolution;
71
+ for (let i = 0; i < lines.length; i++) {
72
+ const line = lines[i].trim();
73
+ if (!line)
74
+ continue;
75
+ if (line.startsWith('#EXT-X-STREAM-INF:')) {
76
+ const bwMatch = line.match(/BANDWIDTH=(\d+)/);
77
+ const resMatch = line.match(/RESOLUTION=(\d+x\d+)/);
78
+ if (bwMatch)
79
+ currentBandwidth = parseInt(bwMatch[1], 10);
80
+ if (resMatch)
81
+ currentResolution = resMatch[1];
82
+ }
83
+ else if (!line.startsWith('#')) {
84
+ let url = line;
85
+ if (!url.startsWith('http')) {
86
+ try {
87
+ const base = new URL(baseUrl);
88
+ const basePath = base.pathname.substring(0, base.pathname.lastIndexOf('/') + 1);
89
+ url = new URL(url, base.origin + basePath).toString();
90
+ }
91
+ catch { }
92
+ }
93
+ variants.push({
94
+ url,
95
+ bandwidth: currentBandwidth,
96
+ resolution: currentResolution
97
+ });
98
+ }
158
99
  }
159
- return sorted[sorted.length - 1];
100
+ return variants;
160
101
  }
161
- export class HlsPromise {
162
- client;
163
- manifestUrl;
164
- options;
165
- seenSequences = new Set();
166
- downloadedBytes = 0;
167
- downloadedSegments = 0;
168
- startTime = 0;
169
- aborted = false;
170
- abortController = new AbortController();
171
- constructor(client, manifestUrl, options = {}) {
172
- this.client = client;
173
- this.manifestUrl = manifestUrl;
174
- this.options = {
175
- mode: 'merge',
176
- format: 'ts',
177
- concurrency: 5,
178
- ...options,
179
- };
180
- if (this.options.format !== 'ts') {
181
- throw new Error(`Format '${this.options.format}' requires ffmpeg. Use format: 'ts' or install ffmpeg.`);
102
+ export async function downloadHls(client, manifestUrl, outputPath, options = {}) {
103
+ const merge = options.merge !== false;
104
+ const concurrency = options.concurrency || 5;
105
+ const isLive = options.live === true;
106
+ const maxDuration = options.duration || (isLive ? Infinity : 0);
107
+ const info = options.onInfo || (() => { });
108
+ const error = options.onError || ((err) => { throw err; });
109
+ const seenSegments = new Set();
110
+ const outputDir = merge ? dirname(outputPath) : outputPath;
111
+ await mkdir(outputDir, { recursive: true });
112
+ const tempDir = join(outputDir, `.tmp_${Date.now()}_${Math.random().toString(36).slice(2)}`);
113
+ if (merge) {
114
+ await mkdir(tempDir, { recursive: true });
115
+ }
116
+ let currentManifestUrl = manifestUrl;
117
+ try {
118
+ let initialManifest = await client.get(currentManifestUrl).text();
119
+ if (options.onManifest) {
120
+ const modified = options.onManifest(initialManifest, currentManifestUrl);
121
+ if (typeof modified === 'string')
122
+ initialManifest = modified;
123
+ }
124
+ if (initialManifest.includes('#EXT-X-STREAM-INF')) {
125
+ const variants = parseVariants(initialManifest, currentManifestUrl);
126
+ if (variants.length > 0) {
127
+ let selected = variants[variants.length - 1];
128
+ if (options.onVariantSelected) {
129
+ const userSelected = options.onVariantSelected(variants, selected);
130
+ if (userSelected)
131
+ selected = userSelected;
132
+ }
133
+ currentManifestUrl = selected.url;
134
+ info(`Master playlist detected. Switching to variant: ${currentManifestUrl}`);
135
+ }
182
136
  }
183
137
  }
184
- get [Symbol.toStringTag]() {
185
- return 'HlsPromise';
138
+ catch (err) {
139
+ error(new Error(`Failed to fetch initial manifest: ${err}`));
140
+ return;
186
141
  }
187
- then(onfulfilled, onrejected) {
188
- return Promise.reject(new Error('HlsPromise requires .download(), .stream(), or .pipe() to execute')).then(onfulfilled, onrejected);
189
- }
190
- catch(onrejected) {
191
- return this.then(null, onrejected);
192
- }
193
- finally(onfinally) {
194
- return this.then(() => {
195
- onfinally?.();
196
- }, () => {
197
- onfinally?.();
198
- });
199
- }
200
- cancel() {
201
- this.aborted = true;
202
- this.abortController.abort();
203
- }
204
- async download(dest) {
205
- this.startTime = Date.now();
206
- const mediaPlaylistUrl = await this.resolveMediaPlaylist();
207
- if (this.options.mode === 'chunks') {
208
- await this.downloadChunks(mediaPlaylistUrl, dest);
209
- }
210
- else {
211
- if (typeof dest !== 'string') {
212
- throw new Error('Merge mode requires a string path, not a function');
142
+ const { RequestRunner } = await import('../runner/request-runner.js');
143
+ const runner = new RequestRunner({ concurrency });
144
+ const startTime = Date.now();
145
+ let recording = true;
146
+ while (recording) {
147
+ try {
148
+ let content = await client.get(currentManifestUrl).text();
149
+ if (options.onManifest) {
150
+ const modified = options.onManifest(content, currentManifestUrl);
151
+ if (typeof modified === 'string')
152
+ content = modified;
213
153
  }
214
- await this.downloadMerged(mediaPlaylistUrl, dest);
215
- }
216
- }
217
- async *stream() {
218
- this.startTime = Date.now();
219
- const mediaPlaylistUrl = await this.resolveMediaPlaylist();
220
- const isLive = this.isLiveMode();
221
- const maxDuration = this.getMaxDuration();
222
- while (!this.aborted) {
223
- const playlist = await this.fetchMediaPlaylist(mediaPlaylistUrl);
224
- const newSegments = playlist.segments.filter((s) => !this.seenSequences.has(s.sequence));
225
- for (const segment of newSegments) {
226
- if (this.aborted)
227
- break;
228
- if (maxDuration && Date.now() - this.startTime > maxDuration) {
229
- return;
230
- }
231
- this.seenSequences.add(segment.sequence);
232
- const data = await this.downloadSegment(segment);
233
- const segmentData = {
234
- sequence: segment.sequence,
235
- duration: segment.duration,
236
- data,
237
- url: segment.url,
238
- downloadedAt: new Date(),
239
- };
240
- this.downloadedSegments++;
241
- this.downloadedBytes += data.byteLength;
242
- this.emitProgress(playlist, isLive);
243
- if (this.options.onSegment) {
244
- await this.options.onSegment(segmentData);
154
+ const playlist = parseM3u8(content, currentManifestUrl);
155
+ let newSegments = playlist.segments.filter(s => !seenSegments.has(s.url));
156
+ if (options.onSegment) {
157
+ const filtered = [];
158
+ for (const seg of newSegments) {
159
+ if (seg.key && options.onKey) {
160
+ const modifiedKey = options.onKey(seg.key);
161
+ if (modifiedKey)
162
+ seg.key = modifiedKey;
163
+ }
164
+ const res = options.onSegment(seg);
165
+ if (res === null)
166
+ continue;
167
+ if (res)
168
+ filtered.push(res);
169
+ else
170
+ filtered.push(seg);
245
171
  }
246
- yield segmentData;
172
+ newSegments = filtered;
173
+ }
174
+ if (newSegments.length > 0) {
175
+ info(`Found ${newSegments.length} new segments.`);
176
+ await runner.run(newSegments, async (seg) => {
177
+ seenSegments.add(seg.url);
178
+ const fileDest = merge
179
+ ? join(tempDir, `${seg.sequence.toString().padStart(10, '0')}.ts`)
180
+ : join(outputDir, `segment_${seg.sequence}.ts`);
181
+ await client.get(seg.url).write(fileDest);
182
+ });
247
183
  }
248
184
  if (!isLive || playlist.endList) {
185
+ recording = false;
249
186
  break;
250
187
  }
251
- if (maxDuration && Date.now() - this.startTime > maxDuration) {
188
+ if (maxDuration > 0 && (Date.now() - startTime) > maxDuration) {
189
+ info('Max duration reached. Stopping.');
190
+ recording = false;
252
191
  break;
253
192
  }
254
- const pollInterval = Math.max(1000, (playlist.targetDuration * 1000) / 2);
255
- await this.sleep(pollInterval);
256
- }
257
- }
258
- async pipe(writable) {
259
- try {
260
- for await (const segment of this.stream()) {
261
- const canContinue = writable.write(segment.data);
262
- if (!canContinue) {
263
- await new Promise((resolve) => writable.once('drain', resolve));
264
- }
193
+ const waitTime = Math.max(1000, (playlist.targetDuration * 1000) / 2);
194
+ await new Promise(r => setTimeout(r, waitTime));
195
+ }
196
+ catch (err) {
197
+ if (isLive) {
198
+ info(`Error fetching live manifest, retrying: ${err.message}`);
199
+ const waitTime = 5000;
200
+ await new Promise(r => setTimeout(r, waitTime));
265
201
  }
266
- }
267
- finally {
268
- if ('end' in writable && typeof writable.end === 'function') {
269
- writable.end();
202
+ else {
203
+ error(new Error(`HLS download failed: ${err.message}`));
204
+ recording = false;
270
205
  }
271
206
  }
272
207
  }
273
- async info() {
274
- const content = await this.client.get(this.manifestUrl).text();
275
- if (isMasterPlaylist(content)) {
276
- const master = parseMasterPlaylist(content, this.manifestUrl);
277
- const selectedVariant = selectVariant(master.variants, this.options.quality);
278
- const playlistContent = await this.client.get(selectedVariant.url).text();
279
- const playlist = parseMediaPlaylist(playlistContent, selectedVariant.url);
280
- const totalDuration = playlist.endList
281
- ? playlist.segments.reduce((sum, s) => sum + s.duration, 0)
282
- : undefined;
283
- return {
284
- master,
285
- playlist,
286
- selectedVariant,
287
- isLive: !playlist.endList,
288
- totalDuration,
289
- };
290
- }
291
- const playlist = parseMediaPlaylist(content, this.manifestUrl);
292
- const totalDuration = playlist.endList
293
- ? playlist.segments.reduce((sum, s) => sum + s.duration, 0)
294
- : undefined;
295
- return {
296
- playlist,
297
- isLive: !playlist.endList,
298
- totalDuration,
299
- };
300
- }
301
- async resolveMediaPlaylist() {
302
- const content = await this.client.get(this.manifestUrl).text();
303
- if (!isMasterPlaylist(content)) {
304
- return this.manifestUrl;
305
- }
306
- const master = parseMasterPlaylist(content, this.manifestUrl);
307
- const variant = selectVariant(master.variants, this.options.quality);
308
- return variant.url;
309
- }
310
- async fetchMediaPlaylist(url) {
311
- const content = await this.client.get(url).text();
312
- return parseMediaPlaylist(content, url);
313
- }
314
- async downloadSegment(segment) {
315
- if (segment.key && segment.key.method !== 'NONE') {
316
- throw new Error(`Encrypted HLS (${segment.key.method}) requires ffmpeg. Use unencrypted streams or install ffmpeg.`);
317
- }
318
- const response = await this.client.get(segment.url, {
319
- headers: this.options.headers,
320
- signal: this.abortController.signal,
321
- });
322
- const blob = await response.blob();
323
- return new Uint8Array(await blob.arrayBuffer());
324
- }
325
- async downloadMerged(playlistUrl, outputPath) {
326
- await mkdir(dirname(outputPath), { recursive: true });
327
- const output = createWriteStream(outputPath);
328
- try {
329
- await this.pipe(output);
330
- }
331
- catch (error) {
332
- output.destroy();
333
- throw error;
334
- }
335
- }
336
- async downloadChunks(playlistUrl, dest) {
337
- const getPath = typeof dest === 'string'
338
- ? (seg) => join(dest, `segment-${seg.sequence}.ts`)
339
- : dest;
340
- const baseDir = typeof dest === 'string' ? dest : dirname(getPath({ sequence: 0, duration: 0, url: '' }));
341
- await mkdir(baseDir, { recursive: true });
342
- for await (const segment of this.stream()) {
343
- const filePath = getPath({
344
- sequence: segment.sequence,
345
- duration: segment.duration,
346
- url: segment.url,
347
- });
348
- await mkdir(dirname(filePath), { recursive: true });
349
- const output = createWriteStream(filePath);
350
- await new Promise((resolve, reject) => {
351
- output.write(segment.data, (err) => {
352
- if (err)
353
- reject(err);
354
- else {
355
- output.end();
356
- resolve();
357
- }
358
- });
359
- });
208
+ if (merge) {
209
+ info('Merging segments...');
210
+ const dest = createWriteStream(outputPath);
211
+ const files = (await readdir(tempDir)).sort();
212
+ for (const file of files) {
213
+ if (!file.endsWith('.ts'))
214
+ continue;
215
+ const chunk = await readFile(join(tempDir, file));
216
+ dest.write(chunk);
360
217
  }
218
+ dest.end();
219
+ await rm(tempDir, { recursive: true, force: true });
220
+ info(`Saved to ${outputPath}`);
361
221
  }
362
- isLiveMode() {
363
- return this.options.live === true || typeof this.options.live === 'object';
222
+ else {
223
+ info(`Download complete.`);
364
224
  }
365
- getMaxDuration() {
366
- if (typeof this.options.live === 'object' && this.options.live.duration) {
367
- return this.options.live.duration;
368
- }
369
- return undefined;
370
- }
371
- emitProgress(playlist, isLive) {
372
- if (!this.options.onProgress)
373
- return;
374
- this.options.onProgress({
375
- downloadedSegments: this.downloadedSegments,
376
- totalSegments: isLive ? undefined : playlist.segments.length,
377
- downloadedBytes: this.downloadedBytes,
378
- currentSegment: Math.max(...this.seenSequences),
379
- isLive,
380
- elapsed: Date.now() - this.startTime,
381
- });
382
- }
383
- sleep(ms) {
384
- return new Promise((resolve) => {
385
- const timeout = setTimeout(resolve, ms);
386
- this.abortController.signal.addEventListener('abort', () => {
387
- clearTimeout(timeout);
388
- resolve();
389
- }, { once: true });
390
- });
391
- }
392
- }
393
- export function hls(client, manifestUrl, options = {}) {
394
- return new HlsPromise(client, manifestUrl, options);
395
225
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recker",
3
- "version": "1.0.20-next.de24f7d",
3
+ "version": "1.0.20",
4
4
  "description": "AI & DevX focused HTTP client for Node.js 18+",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",