@editframe/assets 0.47.1 → 0.48.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.
Files changed (64) hide show
  1. package/LICENSE-FULL.md +148 -0
  2. package/LICENSE.md +58 -0
  3. package/dist/Probe.cjs +63 -9
  4. package/dist/Probe.cjs.map +1 -1
  5. package/dist/Probe.d.cts +49 -0
  6. package/dist/Probe.d.ts +49 -0
  7. package/dist/Probe.js +59 -3
  8. package/dist/Probe.js.map +1 -1
  9. package/dist/VideoRenderOptions.cjs +2 -4
  10. package/dist/VideoRenderOptions.cjs.map +1 -1
  11. package/dist/VideoRenderOptions.js +1 -2
  12. package/dist/VideoRenderOptions.js.map +1 -1
  13. package/dist/_virtual/{rolldown_runtime.cjs → _rolldown/runtime.cjs} +2 -4
  14. package/dist/generateFragmentIndex.cjs +4 -12
  15. package/dist/generateFragmentIndex.cjs.map +1 -1
  16. package/dist/generateFragmentIndex.d.cts +1 -2
  17. package/dist/generateFragmentIndex.d.ts +1 -2
  18. package/dist/generateFragmentIndex.js +1 -2
  19. package/dist/generateFragmentIndex.js.map +1 -1
  20. package/dist/generateSingleTrack.cjs +7 -10
  21. package/dist/generateSingleTrack.cjs.map +1 -1
  22. package/dist/generateSingleTrack.js +2 -3
  23. package/dist/generateSingleTrack.js.map +1 -1
  24. package/dist/generateWebmSegmentIndex.cjs +346 -0
  25. package/dist/generateWebmSegmentIndex.cjs.map +1 -0
  26. package/dist/generateWebmSegmentIndex.js +343 -0
  27. package/dist/generateWebmSegmentIndex.js.map +1 -0
  28. package/dist/idempotentTask.cjs +5 -10
  29. package/dist/idempotentTask.cjs.map +1 -1
  30. package/dist/idempotentTask.d.cts +0 -1
  31. package/dist/idempotentTask.d.ts +0 -1
  32. package/dist/idempotentTask.js +1 -2
  33. package/dist/idempotentTask.js.map +1 -1
  34. package/dist/index.cjs +11 -11
  35. package/dist/index.js +1 -2
  36. package/dist/md5.cjs +3 -7
  37. package/dist/md5.cjs.map +1 -1
  38. package/dist/md5.js +1 -2
  39. package/dist/md5.js.map +1 -1
  40. package/dist/tasks/cacheImage.cjs +4 -6
  41. package/dist/tasks/cacheImage.cjs.map +1 -1
  42. package/dist/tasks/cacheImage.js +1 -2
  43. package/dist/tasks/cacheImage.js.map +1 -1
  44. package/dist/tasks/findOrCreateCaptions.cjs +5 -10
  45. package/dist/tasks/findOrCreateCaptions.cjs.map +1 -1
  46. package/dist/tasks/findOrCreateCaptions.js +1 -2
  47. package/dist/tasks/findOrCreateCaptions.js.map +1 -1
  48. package/dist/tasks/generateScrubTrack.cjs +6 -9
  49. package/dist/tasks/generateScrubTrack.cjs.map +1 -1
  50. package/dist/tasks/generateScrubTrack.js +1 -2
  51. package/dist/tasks/generateScrubTrack.js.map +1 -1
  52. package/dist/tasks/generateTrack.cjs +21 -9
  53. package/dist/tasks/generateTrack.cjs.map +1 -1
  54. package/dist/tasks/generateTrack.js +17 -4
  55. package/dist/tasks/generateTrack.js.map +1 -1
  56. package/dist/tasks/generateTrackFragmentIndex.cjs +26 -11
  57. package/dist/tasks/generateTrackFragmentIndex.cjs.map +1 -1
  58. package/dist/tasks/generateTrackFragmentIndex.js +21 -5
  59. package/dist/tasks/generateTrackFragmentIndex.js.map +1 -1
  60. package/dist/truncateDecimal.cjs +1 -2
  61. package/dist/truncateDecimal.cjs.map +1 -1
  62. package/dist/truncateDecimal.js +1 -1
  63. package/dist/truncateDecimal.js.map +1 -1
  64. package/package.json +1 -1
@@ -0,0 +1,343 @@
1
+ import { PacketProbe } from "./Probe.js";
2
+ import debug from "debug";
3
+ import { readFile } from "node:fs/promises";
4
+ //#region src/generateWebmSegmentIndex.ts
5
+ /**
6
+ * WebM / Matroska segment index generator.
7
+ *
8
+ * Instead of transcoding VP9-alpha WebM → fragmented MP4 (which strips the
9
+ * alpha BlockAdditions), this module parses the source WebM's EBML structure
10
+ * to produce byte-range segment maps directly into the original file.
11
+ *
12
+ * The pipeline:
13
+ * 1. EBML parse: locate init region (EBML + Segment header + Info + Tracks)
14
+ * and enumerate every Cluster with its timestamp.
15
+ * 2. Keyframe detection: cross-reference cluster byte ranges with ffprobe
16
+ * packet positions+flags to mark which clusters are keyframe-aligned.
17
+ * 3. Segment grouping: accumulate clusters into ≥2-second segments that
18
+ * start on keyframe clusters (mirrors generateFragmentIndex.ts logic).
19
+ * 4. Output: same TrackFragmentIndex shape used by the MP4 path so the
20
+ * rest of the pipeline (middleware, SegmentIndex.ts, EFVideo) is unchanged.
21
+ *
22
+ * Segment size patching
23
+ * ---------------------
24
+ * ffmpeg writes a known Segment-element size in the WebM header. When we
25
+ * serve a subset of clusters, the size field must be replaced with the EBML
26
+ * "unknown" value (0x01FFFFFFFFFFFFFF) so mediabunny does not expect more
27
+ * bytes than we provide. This patch is applied once to the cached copy of
28
+ * the source file (see generateTrack.ts).
29
+ */
30
+ const log = debug("ef:generateWebmSegmentIndex");
31
+ const MIN_SEGMENT_DURATION_MS = 2e3;
32
+ const ID_EBML = 440786851;
33
+ const ID_SEGMENT = 408125543;
34
+ const ID_INFO = 357149030;
35
+ const ID_CLUSTER = 524531317;
36
+ const ID_TIMESTAMP = 231;
37
+ const ID_SIMPLE_BLOCK = 163;
38
+ const ID_BLOCK_GROUP = 160;
39
+ const ID_REFERENCE_BLOCK = 251;
40
+ const ID_TIMESTAMP_SCALE = 2807729;
41
+ /**
42
+ * Decode an EBML variable-length integer used for **element sizes**.
43
+ * The leading 1-bit encodes the byte-width; that bit is then stripped from
44
+ * the value. Returns `null` for the "unknown / streaming" sentinel value
45
+ * (all data-bits = 1).
46
+ */
47
+ function readVintSize(buf, offset) {
48
+ const b = buf[offset];
49
+ let width = 1;
50
+ let mask = 128;
51
+ while (width <= 8 && !(b & mask)) {
52
+ mask >>= 1;
53
+ width++;
54
+ }
55
+ let value = b & mask - 1;
56
+ for (let i = 1; i < width; i++) value = value << 8 | (buf[offset + i] ?? 0);
57
+ const unknownSentinel = (1 << 7 * width) - 1;
58
+ return {
59
+ value: value === unknownSentinel ? null : value,
60
+ width
61
+ };
62
+ }
63
+ /**
64
+ * Decode an EBML **element ID**. Unlike sizes, the leading marker bit is
65
+ * *kept* in the returned value (IDs are opaque bit patterns).
66
+ */
67
+ function readElementId(buf, offset) {
68
+ const b = buf[offset];
69
+ let width = 1;
70
+ let mask = 128;
71
+ while (width <= 4 && !(b & mask)) {
72
+ mask >>= 1;
73
+ width++;
74
+ }
75
+ let id = b;
76
+ for (let i = 1; i < width; i++) id = id << 8 | (buf[offset + i] ?? 0);
77
+ return {
78
+ id,
79
+ width
80
+ };
81
+ }
82
+ /** Read a big-endian unsigned integer of `size` bytes. */
83
+ function readUintBE(buf, offset, size) {
84
+ let val = 0;
85
+ for (let i = 0; i < size; i++) val = val * 256 + (buf[offset + i] ?? 0) >>> 0;
86
+ return val;
87
+ }
88
+ /**
89
+ * Parse the top-level EBML and Segment structure of a WebM file.
90
+ * Only reads as deep as needed: EBML header → Segment → Info/Tracks/Clusters.
91
+ */
92
+ function parseWebmStructure(buf) {
93
+ let pos = 0;
94
+ const { id: ebmlId, width: ebmlIdWidth } = readElementId(buf, pos);
95
+ if (ebmlId !== ID_EBML) throw new Error(`Expected EBML element (0x1A45DFA3), got 0x${ebmlId.toString(16)}`);
96
+ const { value: ebmlSize, width: ebmlSizeWidth } = readVintSize(buf, pos + ebmlIdWidth);
97
+ if (ebmlSize === null) throw new Error("EBML element has unknown size");
98
+ pos += ebmlIdWidth + ebmlSizeWidth + ebmlSize;
99
+ const { id: segId, width: segIdWidth } = readElementId(buf, pos);
100
+ if (segId !== ID_SEGMENT) throw new Error(`Expected Segment element (0x18538067), got 0x${segId.toString(16)}`);
101
+ const segmentSizeVintOffset = pos + segIdWidth;
102
+ const { width: segSizeWidth } = readVintSize(buf, segmentSizeVintOffset);
103
+ let spos = segmentSizeVintOffset + segSizeWidth;
104
+ let initSize = 0;
105
+ let timestampScaleNs = 1e6;
106
+ const clusters = [];
107
+ while (spos < buf.length) {
108
+ if (buf.length - spos < 2) break;
109
+ const { id: childId, width: childIdWidth } = readElementId(buf, spos);
110
+ const { value: childSize, width: childSizeWidth } = readVintSize(buf, spos + childIdWidth);
111
+ const headerSize = childIdWidth + childSizeWidth;
112
+ if (childSize === null) {
113
+ log(`Unknown-size element 0x${childId.toString(16)} at ${spos}, stopping`);
114
+ break;
115
+ }
116
+ const elementEnd = spos + headerSize + childSize;
117
+ if (childId === ID_INFO) {
118
+ let ipos = spos + headerSize;
119
+ while (ipos < elementEnd && ipos < buf.length) {
120
+ const { id: infoChildId, width: infoIdW } = readElementId(buf, ipos);
121
+ const { value: infoChildSize, width: infoSizeW } = readVintSize(buf, ipos + infoIdW);
122
+ if (infoChildSize === null) break;
123
+ if (infoChildId === ID_TIMESTAMP_SCALE) timestampScaleNs = readUintBE(buf, ipos + infoIdW + infoSizeW, infoChildSize);
124
+ ipos += infoIdW + infoSizeW + infoChildSize;
125
+ }
126
+ } else if (childId === ID_CLUSTER) {
127
+ if (initSize === 0) initSize = spos;
128
+ let clusterTimestampUnits = 0;
129
+ let hasKeyframe = false;
130
+ let cpos = spos + headerSize;
131
+ while (cpos < elementEnd && cpos < buf.length) {
132
+ if (buf.length - cpos < 2) break;
133
+ const { id: cid, width: cidW } = readElementId(buf, cpos);
134
+ const { value: csize, width: csizeW } = readVintSize(buf, cpos + cidW);
135
+ if (csize === null) break;
136
+ const cHeaderSize = cidW + csizeW;
137
+ if (cid === ID_TIMESTAMP) clusterTimestampUnits = readUintBE(buf, cpos + cHeaderSize, csize);
138
+ else if (cid === ID_SIMPLE_BLOCK) {
139
+ const sbOffset = cpos + cHeaderSize;
140
+ const { width: trackNumWidth } = readVintSize(buf, sbOffset);
141
+ if ((buf[sbOffset + trackNumWidth + 2] ?? 0) & 128) hasKeyframe = true;
142
+ } else if (cid === ID_BLOCK_GROUP) {
143
+ let bgpos = cpos + cHeaderSize;
144
+ const bgEnd = cpos + cHeaderSize + csize;
145
+ let hasReferenceBlock = false;
146
+ while (bgpos < bgEnd && bgpos < buf.length) {
147
+ const { id: bgid, width: bgidW } = readElementId(buf, bgpos);
148
+ const { value: bgsize, width: bgsizeW } = readVintSize(buf, bgpos + bgidW);
149
+ if (bgsize === null) break;
150
+ if (bgid === ID_REFERENCE_BLOCK) {
151
+ hasReferenceBlock = true;
152
+ break;
153
+ }
154
+ bgpos += bgidW + bgsizeW + bgsize;
155
+ }
156
+ if (!hasReferenceBlock) hasKeyframe = true;
157
+ }
158
+ cpos += cHeaderSize + csize;
159
+ }
160
+ const timestampMs = Math.round(clusterTimestampUnits * timestampScaleNs / 1e6);
161
+ clusters.push({
162
+ offset: spos,
163
+ size: headerSize + childSize,
164
+ timestampMs,
165
+ hasKeyframe
166
+ });
167
+ }
168
+ spos = elementEnd;
169
+ }
170
+ if (initSize === 0) throw new Error("No Cluster elements found in WebM file");
171
+ return {
172
+ segmentSizeVintOffset,
173
+ segmentSizeVintWidth: segSizeWidth,
174
+ initSize,
175
+ clusters,
176
+ timestampScaleNs
177
+ };
178
+ }
179
+ /**
180
+ * Use ffprobe packet data to mark clusters that contain keyframe packets.
181
+ * More reliable than parsing SimpleBlock flags in-process for large files.
182
+ */
183
+ async function annotateKeyframes(clusters, absolutePath) {
184
+ const keyframePositions = (await PacketProbe.probePath(absolutePath)).packets.filter((p) => p.flags?.includes("K") && p.pos !== void 0).map((p) => p.pos);
185
+ for (const cluster of clusters) {
186
+ const clusterEnd = cluster.offset + cluster.size;
187
+ cluster.hasKeyframe = keyframePositions.some((pos) => pos >= cluster.offset && pos < clusterEnd);
188
+ }
189
+ }
190
+ function buildSegments(clusters, timescale, totalDurationMs) {
191
+ const segments = [];
192
+ let segmentClusters = [];
193
+ let segmentStartMs = 0;
194
+ const flushSegment = (nextStartMs) => {
195
+ if (segmentClusters.length === 0) return;
196
+ const first = segmentClusters[0];
197
+ const last = segmentClusters[segmentClusters.length - 1];
198
+ const offset = first.offset;
199
+ const size = last.offset + last.size - first.offset;
200
+ const cts = Math.round(segmentStartMs * timescale / 1e3);
201
+ const dts = cts;
202
+ const duration = Math.round((nextStartMs - segmentStartMs) * timescale / 1e3);
203
+ segments.push({
204
+ cts,
205
+ dts,
206
+ offset,
207
+ size,
208
+ duration
209
+ });
210
+ segmentClusters = [];
211
+ };
212
+ for (let i = 0; i < clusters.length; i++) {
213
+ const cluster = clusters[i];
214
+ const durationSoFarMs = segmentClusters.length > 0 ? cluster.timestampMs - segmentStartMs : 0;
215
+ if (segmentClusters.length > 0 && durationSoFarMs >= MIN_SEGMENT_DURATION_MS && cluster.hasKeyframe) {
216
+ flushSegment(cluster.timestampMs);
217
+ segmentStartMs = cluster.timestampMs;
218
+ }
219
+ if (segmentClusters.length === 0) {
220
+ if (!cluster.hasKeyframe) continue;
221
+ segmentStartMs = cluster.timestampMs;
222
+ }
223
+ segmentClusters.push(cluster);
224
+ }
225
+ flushSegment(totalDurationMs);
226
+ return segments;
227
+ }
228
+ /**
229
+ * Build a TrackFragmentIndex for a VP9-alpha WebM source without any
230
+ * transcoding. The returned index contains byte offsets that point directly
231
+ * into the cached copy of the source file (which has its Segment-size VINT
232
+ * patched to "unknown" by generateTrack.ts).
233
+ */
234
+ async function generateWebmSegmentIndex(absolutePath, startTimeOffsetMs) {
235
+ log(`Generating WebM segment index for ${absolutePath}`);
236
+ const { initSize, clusters, timestampScaleNs } = parseWebmStructure(await readFile(absolutePath));
237
+ const timescale = 1e3;
238
+ log(`Parsed ${clusters.length} clusters, init=${initSize} bytes, timestampScale=${timestampScaleNs}ns`);
239
+ await annotateKeyframes(clusters, absolutePath);
240
+ log(`Keyframe clusters: ${clusters.filter((c) => c.hasKeyframe).map((c) => `${c.timestampMs}ms@${c.offset}`).join(", ")}`);
241
+ const lastCluster = clusters[clusters.length - 1];
242
+ let finalDurationMs = lastCluster.timestampMs + lastCluster.size / 4096;
243
+ try {
244
+ const videoStream = (await PacketProbe.probePath(absolutePath)).data?.streams?.find((s) => s.codec_type === "video");
245
+ if (videoStream?.duration) finalDurationMs = Math.round(parseFloat(videoStream.duration) * 1e3);
246
+ } catch {}
247
+ log(`Total duration: ${finalDurationMs}ms`);
248
+ const segments = buildSegments(clusters, timescale, finalDurationMs);
249
+ log(`Built ${segments.length} segments: ${segments.map((s) => `[${s.cts / timescale * 1e3 | 0}ms offset=${s.offset} size=${s.size}]`).join(", ")}`);
250
+ const probe2 = await PacketProbe.probePath(absolutePath);
251
+ const videoStream = probe2.data?.streams?.find((s) => s.codec_type === "video");
252
+ const width = videoStream?.width ?? 1920;
253
+ const height = videoStream?.height ?? 1080;
254
+ const codec = videoStream?.codec_tag_string ?? videoStream?.codec_name ?? "vp09";
255
+ const sampleCount = probe2.packets?.filter((p) => p.codec_type !== "audio").length ?? 0;
256
+ let trackStartTimeOffsetMs;
257
+ if (startTimeOffsetMs !== void 0) trackStartTimeOffsetMs = startTimeOffsetMs;
258
+ else if (clusters[0] && clusters[0].timestampMs > 1) trackStartTimeOffsetMs = clusters[0].timestampMs;
259
+ const trackIndex = {
260
+ track: 1,
261
+ type: "video",
262
+ width,
263
+ height,
264
+ timescale,
265
+ codec,
266
+ duration: Math.round(finalDurationMs * timescale / 1e3),
267
+ sample_count: sampleCount,
268
+ startTimeOffsetMs: trackStartTimeOffsetMs,
269
+ initSegment: {
270
+ offset: 0,
271
+ size: initSize
272
+ },
273
+ segments
274
+ };
275
+ return { 1: trackIndex };
276
+ }
277
+ const ID_SEEKHEAD = 290298740;
278
+ const EBML_VOID_ID = 236;
279
+ /**
280
+ * Patch a WebM buffer in-place to make it safe for partial (segment-sliced) serving:
281
+ *
282
+ * 1. Segment-element size VINT → EBML unknown-size (0x01FFFFFFFFFFFFFF).
283
+ * Without this, mediabunny expects the full 44 MB when receiving a 5 MB chunk.
284
+ *
285
+ * 2. SeekHead element → EBML Void of the same byte length.
286
+ * The SeekHead contains Cues/cluster offsets relative to the original file.
287
+ * When mediabunny uses those offsets on a sliced buffer it reads garbage or
288
+ * falls off the end of the buffer, causing seek errors and de-sync. Replacing
289
+ * it with a Void element forces linear parsing: EBML → Info → Tracks → Clusters.
290
+ *
291
+ * Both patches are applied to a Buffer copy; the source file on disk is not modified.
292
+ */
293
+ function patchWebmForSegmentedServing(buf) {
294
+ try {
295
+ const { id: ebmlId, width: ebmlIdWidth } = readElementId(buf, 0);
296
+ if (ebmlId !== ID_EBML) return;
297
+ const { value: ebmlSize, width: ebmlSizeWidth } = readVintSize(buf, ebmlIdWidth);
298
+ if (ebmlSize === null) return;
299
+ const segPos = ebmlIdWidth + ebmlSizeWidth + ebmlSize;
300
+ const { id: segId, width: segIdWidth } = readElementId(buf, segPos);
301
+ if (segId !== ID_SEGMENT) return;
302
+ const segSizeOffset = segPos + segIdWidth;
303
+ const { width: segSizeWidth } = readVintSize(buf, segSizeOffset);
304
+ if (segSizeWidth === 8) Buffer.from([
305
+ 1,
306
+ 255,
307
+ 255,
308
+ 255,
309
+ 255,
310
+ 255,
311
+ 255,
312
+ 255
313
+ ]).copy(buf, segSizeOffset);
314
+ let pos = segPos + segIdWidth + segSizeWidth;
315
+ const scanLimit = Math.min(pos + 4096, buf.length);
316
+ while (pos < scanLimit) {
317
+ const { id: childId, width: childIdWidth } = readElementId(buf, pos);
318
+ const { value: childSize, width: childSizeWidth } = readVintSize(buf, pos + childIdWidth);
319
+ if (childSize === null) break;
320
+ const totalElementSize = childIdWidth + childSizeWidth + childSize;
321
+ if (childId === ID_SEEKHEAD) {
322
+ const voidContentSize = totalElementSize - 1;
323
+ let vintBytes;
324
+ if (voidContentSize <= 126) vintBytes = [128 | voidContentSize];
325
+ else if (voidContentSize <= 16382) vintBytes = [64 | voidContentSize >> 8, voidContentSize & 255];
326
+ else vintBytes = [
327
+ 32 | voidContentSize >> 16,
328
+ voidContentSize >> 8 & 255,
329
+ voidContentSize & 255
330
+ ];
331
+ buf[pos] = EBML_VOID_ID;
332
+ for (let i = 0; i < vintBytes.length; i++) buf[pos + 1 + i] = vintBytes[i];
333
+ buf.fill(0, pos + 1 + vintBytes.length, pos + totalElementSize);
334
+ break;
335
+ }
336
+ pos += totalElementSize;
337
+ }
338
+ } catch {}
339
+ }
340
+ //#endregion
341
+ export { generateWebmSegmentIndex, patchWebmForSegmentedServing };
342
+
343
+ //# sourceMappingURL=generateWebmSegmentIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateWebmSegmentIndex.js","names":[],"sources":["../src/generateWebmSegmentIndex.ts"],"mappings":"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"}
@@ -1,18 +1,13 @@
1
- const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
- const require_md5 = require('./md5.cjs');
1
+ const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
2
+ const require_md5 = require("./md5.cjs");
3
3
  let node_fs = require("node:fs");
4
- node_fs = require_rolldown_runtime.__toESM(node_fs);
5
4
  let debug = require("debug");
6
- debug = require_rolldown_runtime.__toESM(debug);
5
+ debug = require_runtime.__toESM(debug);
7
6
  let node_stream = require("node:stream");
8
- node_stream = require_rolldown_runtime.__toESM(node_stream);
9
7
  let node_fs_promises = require("node:fs/promises");
10
- node_fs_promises = require_rolldown_runtime.__toESM(node_fs_promises);
11
8
  let node_path = require("node:path");
12
- node_path = require_rolldown_runtime.__toESM(node_path);
9
+ node_path = require_runtime.__toESM(node_path);
13
10
  let node_url = require("node:url");
14
- node_url = require_rolldown_runtime.__toESM(node_url);
15
-
16
11
  //#region src/idempotentTask.ts
17
12
  const _pkgDir = node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
18
13
  const CACHE_VERSION = JSON.parse((0, node_fs.readFileSync)(node_path.default.join(_pkgDir, "../package.json"), "utf-8")).version;
@@ -195,7 +190,7 @@ const idempotentTask = ({ label, filename, runner }) => {
195
190
  return await fullTask;
196
191
  };
197
192
  };
198
-
199
193
  //#endregion
200
194
  exports.idempotentTask = idempotentTask;
195
+
201
196
  //# sourceMappingURL=idempotentTask.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"idempotentTask.cjs","names":["path","CACHE_VERSION: string","storedVersion: string | null","runnerQueue: Array<() => void>","tasks: Record<string, Promise<TaskResult>>","downloadTasks: Record<string, Promise<string>>","Readable","cachePath: string | null","md5: string | null","md5FilePath","result: string | Readable"],"sources":["../src/idempotentTask.ts"],"sourcesContent":["import { createWriteStream, existsSync, readFileSync } from \"node:fs\";\nimport path, { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { md5FilePath } from \"./md5.js\";\nimport debug from \"debug\";\nimport { mkdir, writeFile, stat, rename, readdir, readFile, rm } from \"node:fs/promises\";\nimport { Readable } from \"node:stream\";\n\n// @ts-ignore - import.meta.url is available at runtime; tsconfig uses CommonJS module for type-checking only\nconst _pkgDir = path.dirname(fileURLToPath(import.meta.url));\nconst CACHE_VERSION: string = (\n JSON.parse(readFileSync(path.join(_pkgDir, \"../package.json\"), \"utf-8\")) as {\n version: string;\n }\n).version;\n\n// Per-root validation promises — serializes the version check within a process\n// and memoizes it so subsequent calls in the same process are free.\nconst rootValidationPromises = new Map<string, Promise<void>>();\n\nasync function ensureCacheVersion(cacheDirRoot: string): Promise<void> {\n const existing = rootValidationPromises.get(cacheDirRoot);\n if (existing) return existing;\n\n const promise = (async () => {\n const versionFile = join(cacheDirRoot, \".version\");\n let storedVersion: string | null = null;\n try {\n storedVersion = (await readFile(versionFile, \"utf-8\")).trim();\n } catch {}\n\n if (storedVersion === CACHE_VERSION) return;\n\n const log = debug(\"ef:idempotentTask\");\n log(\n `Cache version mismatch (stored: ${storedVersion ?? \"none\"}, current: ${CACHE_VERSION}) — busting computed caches in ${cacheDirRoot}`,\n );\n\n // Delete computed output directories; preserve downloaded .file entries\n const entries = await readdir(cacheDirRoot, { withFileTypes: true }).catch(() => []);\n await Promise.all(\n entries\n .filter((e) => e.isDirectory())\n .map((e) =>\n rm(join(cacheDirRoot, e.name), {\n recursive: true,\n force: true,\n }).catch(() => {}),\n ),\n );\n\n await mkdir(cacheDirRoot, { recursive: true });\n await writeFile(versionFile, CACHE_VERSION);\n })();\n\n rootValidationPromises.set(cacheDirRoot, promise);\n return promise;\n}\n\nconst MAX_CONCURRENT_RUNNERS = 4;\nlet activeRunners = 0;\nconst runnerQueue: Array<() => void> = [];\n\nfunction acquireRunnerSlot(): Promise<void> {\n if (activeRunners < MAX_CONCURRENT_RUNNERS) {\n activeRunners++;\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n runnerQueue.push(() => {\n activeRunners++;\n resolve();\n });\n });\n}\n\nfunction releaseRunnerSlot(): void {\n activeRunners--;\n const next = runnerQueue.shift();\n if (next) next();\n}\n\ninterface TaskOptions<T extends unknown[]> {\n label: string;\n filename: (absolutePath: string, ...args: T) => string;\n runner: (absolutePath: string, ...args: T) => Promise<string | Readable>;\n}\n\nexport interface TaskResult {\n md5Sum: string;\n cachePath: string;\n}\n\nexport const idempotentTask = <T extends unknown[]>({\n label,\n filename,\n runner,\n}: TaskOptions<T>) => {\n const tasks: Record<string, Promise<TaskResult>> = {};\n const downloadTasks: Record<string, Promise<string>> = {};\n\n // Helper function to validate cache file completeness\n const isValidCacheFile = async (filePath: string, allowEmpty = false): Promise<boolean> => {\n try {\n const stats = await stat(filePath);\n // File must exist and either have content or be explicitly allowed to be empty\n return allowEmpty || stats.size > 0;\n } catch {\n return false;\n }\n };\n\n return async (rootDir: string, absolutePath: string, ...args: T): Promise<TaskResult> => {\n const log = debug(`ef:${label}`);\n const cacheDirRoot = path.join(rootDir, \".cache\");\n await mkdir(cacheDirRoot, { recursive: true });\n await ensureCacheVersion(cacheDirRoot);\n\n log(`Running ef:${label} task for ${absolutePath} in ${rootDir}`);\n\n // Handle HTTP downloads with proper race condition protection\n if (absolutePath.startsWith(\"http://\") || absolutePath.startsWith(\"https://\")) {\n const safePath = absolutePath.replace(/[^a-zA-Z0-9]/g, \"_\");\n const downloadCachePath = path.join(rootDir, \".cache\", `${safePath}.file`);\n\n // Check if already downloaded and valid (allow empty downloads)\n if (existsSync(downloadCachePath) && (await isValidCacheFile(downloadCachePath, true))) {\n log(`Already cached ${absolutePath}`);\n absolutePath = downloadCachePath;\n } else {\n // Use download task deduplication to prevent concurrent downloads\n const downloadKey = absolutePath;\n if (!downloadTasks[downloadKey]) {\n log(`Starting download for ${absolutePath}`);\n downloadTasks[downloadKey] = (async () => {\n try {\n const response = await fetch(absolutePath);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch file from URL ${absolutePath}: ${response.status} ${response.statusText}`,\n );\n }\n\n const stream = response.body;\n if (!stream) {\n throw new Error(`No response body for URL ${absolutePath}`);\n }\n\n // Use temporary file to prevent reading incomplete downloads\n const tempPath = `${downloadCachePath}.tmp`;\n const writeStream = createWriteStream(tempPath);\n\n // @ts-ignore node web stream support in typescript is incorrect about this.\n const readable = Readable.fromWeb(stream);\n readable.pipe(writeStream);\n\n await new Promise<void>((resolve, reject) => {\n readable.on(\"error\", reject);\n writeStream.on(\"error\", reject);\n writeStream.on(\"finish\", () => resolve());\n });\n\n // Atomically move completed file to final location\n await rename(tempPath, downloadCachePath);\n\n log(`Download completed for ${absolutePath}`);\n return downloadCachePath;\n } catch (error) {\n log(`Download failed for ${absolutePath}: ${error}`);\n // Clean up task reference on failure\n delete downloadTasks[downloadKey];\n throw error;\n }\n })();\n }\n\n absolutePath = await downloadTasks[downloadKey];\n // Clean up completed task\n delete downloadTasks[downloadKey];\n }\n }\n\n // Deduplicate concurrent callers by input parameters before any async work.\n // Using a synchronous key prevents the TOCTOU race where two concurrent\n // callers both pass the tasks[] check before either registers a task.\n const inputKey = JSON.stringify([absolutePath, ...args]);\n if (tasks[inputKey]) {\n log(`Returning existing ef:${label} task for ${absolutePath}`);\n return await tasks[inputKey];\n }\n\n const fullTask = (async (): Promise<TaskResult> => {\n try {\n // Try to find existing cache by scanning cache directories.\n // This avoids expensive MD5 computation when cache already exists.\n const expectedFilename = filename(absolutePath, ...args);\n let cachePath: string | null = null;\n let md5: string | null = null;\n\n const scanStartTime = Date.now();\n try {\n const cacheDirs = await readdir(cacheDirRoot, {\n withFileTypes: true,\n });\n log(`Scanning ${cacheDirs.length} cache directories for ${expectedFilename}`);\n for (const dir of cacheDirs) {\n if (dir.isDirectory()) {\n const candidatePath = path.join(cacheDirRoot, dir.name, expectedFilename);\n if (existsSync(candidatePath) && (await isValidCacheFile(candidatePath))) {\n cachePath = candidatePath;\n md5 = dir.name; // Directory name is the MD5\n const scanElapsed = Date.now() - scanStartTime;\n log(`Found existing cache in ${scanElapsed}ms: ${candidatePath} (skipped MD5)`);\n break;\n }\n }\n }\n if (!cachePath) {\n const scanElapsed = Date.now() - scanStartTime;\n log(`Cache scan completed in ${scanElapsed}ms, no cache found - will compute MD5`);\n }\n } catch (error) {\n const scanElapsed = Date.now() - scanStartTime;\n log(`Cache scan failed after ${scanElapsed}ms, will compute MD5: ${error}`);\n }\n\n const resolvedMd5 =\n md5 ??\n (await (async () => {\n const md5StartTime = Date.now();\n log(`Computing MD5 for ${absolutePath}...`);\n const computed = await md5FilePath(absolutePath);\n const md5Elapsed = Date.now() - md5StartTime;\n log(`MD5 computed in ${md5Elapsed}ms: ${computed}`);\n return computed;\n })());\n\n const cacheDir = path.join(cacheDirRoot, resolvedMd5);\n log(`Cache dir: ${cacheDir}`);\n await mkdir(cacheDir, { recursive: true });\n\n const resolvedCachePath = cachePath ?? path.join(cacheDir, expectedFilename);\n\n // Check if cache exists and is valid (not zero-byte)\n if (existsSync(resolvedCachePath) && (await isValidCacheFile(resolvedCachePath))) {\n log(`Returning cached ef:${label} task for ${resolvedCachePath}`);\n return { cachePath: resolvedCachePath, md5Sum: resolvedMd5 };\n }\n\n log(`Running ef:${label} runner for ${resolvedCachePath}`);\n await acquireRunnerSlot();\n let result: string | Readable;\n try {\n result = await runner(absolutePath, ...args);\n } finally {\n releaseRunnerSlot();\n }\n\n if (result instanceof Readable) {\n log(`Piping task for ${resolvedCachePath} to cache`);\n const tempPath = `${resolvedCachePath}.tmp`;\n const writeStream = createWriteStream(tempPath);\n result.pipe(writeStream);\n\n await new Promise<void>((resolve, reject) => {\n result.on(\"error\", reject);\n writeStream.on(\"error\", reject);\n writeStream.on(\"finish\", () => resolve());\n });\n\n await rename(tempPath, resolvedCachePath);\n } else {\n log(`Writing to ${resolvedCachePath}`);\n await writeFile(resolvedCachePath, result);\n }\n\n return {\n md5Sum: resolvedMd5,\n cachePath: resolvedCachePath,\n };\n } finally {\n delete tasks[inputKey];\n }\n })();\n\n tasks[inputKey] = fullTask;\n return await fullTask;\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"idempotentTask.cjs","names":["path","Readable","md5FilePath"],"sources":["../src/idempotentTask.ts"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  import { Readable } from "node:stream";
2
2
 
3
3
  //#region src/idempotentTask.d.ts
4
-
5
4
  interface TaskResult {
6
5
  md5Sum: string;
7
6
  cachePath: string;
@@ -1,7 +1,6 @@
1
1
  import { Readable } from "node:stream";
2
2
 
3
3
  //#region src/idempotentTask.d.ts
4
-
5
4
  interface TaskResult {
6
5
  md5Sum: string;
7
6
  cachePath: string;
@@ -5,7 +5,6 @@ import { Readable } from "node:stream";
5
5
  import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
6
6
  import path, { join } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
-
9
8
  //#region src/idempotentTask.ts
10
9
  const _pkgDir = path.dirname(fileURLToPath(import.meta.url));
11
10
  const CACHE_VERSION = JSON.parse(readFileSync(path.join(_pkgDir, "../package.json"), "utf-8")).version;
@@ -188,7 +187,7 @@ const idempotentTask = ({ label, filename, runner }) => {
188
187
  return await fullTask;
189
188
  };
190
189
  };
191
-
192
190
  //#endregion
193
191
  export { idempotentTask };
192
+
194
193
  //# sourceMappingURL=idempotentTask.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"idempotentTask.js","names":["CACHE_VERSION: string","storedVersion: string | null","runnerQueue: Array<() => void>","tasks: Record<string, Promise<TaskResult>>","downloadTasks: Record<string, Promise<string>>","cachePath: string | null","md5: string | null","result: string | Readable"],"sources":["../src/idempotentTask.ts"],"sourcesContent":["import { createWriteStream, existsSync, readFileSync } from \"node:fs\";\nimport path, { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { md5FilePath } from \"./md5.js\";\nimport debug from \"debug\";\nimport { mkdir, writeFile, stat, rename, readdir, readFile, rm } from \"node:fs/promises\";\nimport { Readable } from \"node:stream\";\n\n// @ts-ignore - import.meta.url is available at runtime; tsconfig uses CommonJS module for type-checking only\nconst _pkgDir = path.dirname(fileURLToPath(import.meta.url));\nconst CACHE_VERSION: string = (\n JSON.parse(readFileSync(path.join(_pkgDir, \"../package.json\"), \"utf-8\")) as {\n version: string;\n }\n).version;\n\n// Per-root validation promises — serializes the version check within a process\n// and memoizes it so subsequent calls in the same process are free.\nconst rootValidationPromises = new Map<string, Promise<void>>();\n\nasync function ensureCacheVersion(cacheDirRoot: string): Promise<void> {\n const existing = rootValidationPromises.get(cacheDirRoot);\n if (existing) return existing;\n\n const promise = (async () => {\n const versionFile = join(cacheDirRoot, \".version\");\n let storedVersion: string | null = null;\n try {\n storedVersion = (await readFile(versionFile, \"utf-8\")).trim();\n } catch {}\n\n if (storedVersion === CACHE_VERSION) return;\n\n const log = debug(\"ef:idempotentTask\");\n log(\n `Cache version mismatch (stored: ${storedVersion ?? \"none\"}, current: ${CACHE_VERSION}) — busting computed caches in ${cacheDirRoot}`,\n );\n\n // Delete computed output directories; preserve downloaded .file entries\n const entries = await readdir(cacheDirRoot, { withFileTypes: true }).catch(() => []);\n await Promise.all(\n entries\n .filter((e) => e.isDirectory())\n .map((e) =>\n rm(join(cacheDirRoot, e.name), {\n recursive: true,\n force: true,\n }).catch(() => {}),\n ),\n );\n\n await mkdir(cacheDirRoot, { recursive: true });\n await writeFile(versionFile, CACHE_VERSION);\n })();\n\n rootValidationPromises.set(cacheDirRoot, promise);\n return promise;\n}\n\nconst MAX_CONCURRENT_RUNNERS = 4;\nlet activeRunners = 0;\nconst runnerQueue: Array<() => void> = [];\n\nfunction acquireRunnerSlot(): Promise<void> {\n if (activeRunners < MAX_CONCURRENT_RUNNERS) {\n activeRunners++;\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n runnerQueue.push(() => {\n activeRunners++;\n resolve();\n });\n });\n}\n\nfunction releaseRunnerSlot(): void {\n activeRunners--;\n const next = runnerQueue.shift();\n if (next) next();\n}\n\ninterface TaskOptions<T extends unknown[]> {\n label: string;\n filename: (absolutePath: string, ...args: T) => string;\n runner: (absolutePath: string, ...args: T) => Promise<string | Readable>;\n}\n\nexport interface TaskResult {\n md5Sum: string;\n cachePath: string;\n}\n\nexport const idempotentTask = <T extends unknown[]>({\n label,\n filename,\n runner,\n}: TaskOptions<T>) => {\n const tasks: Record<string, Promise<TaskResult>> = {};\n const downloadTasks: Record<string, Promise<string>> = {};\n\n // Helper function to validate cache file completeness\n const isValidCacheFile = async (filePath: string, allowEmpty = false): Promise<boolean> => {\n try {\n const stats = await stat(filePath);\n // File must exist and either have content or be explicitly allowed to be empty\n return allowEmpty || stats.size > 0;\n } catch {\n return false;\n }\n };\n\n return async (rootDir: string, absolutePath: string, ...args: T): Promise<TaskResult> => {\n const log = debug(`ef:${label}`);\n const cacheDirRoot = path.join(rootDir, \".cache\");\n await mkdir(cacheDirRoot, { recursive: true });\n await ensureCacheVersion(cacheDirRoot);\n\n log(`Running ef:${label} task for ${absolutePath} in ${rootDir}`);\n\n // Handle HTTP downloads with proper race condition protection\n if (absolutePath.startsWith(\"http://\") || absolutePath.startsWith(\"https://\")) {\n const safePath = absolutePath.replace(/[^a-zA-Z0-9]/g, \"_\");\n const downloadCachePath = path.join(rootDir, \".cache\", `${safePath}.file`);\n\n // Check if already downloaded and valid (allow empty downloads)\n if (existsSync(downloadCachePath) && (await isValidCacheFile(downloadCachePath, true))) {\n log(`Already cached ${absolutePath}`);\n absolutePath = downloadCachePath;\n } else {\n // Use download task deduplication to prevent concurrent downloads\n const downloadKey = absolutePath;\n if (!downloadTasks[downloadKey]) {\n log(`Starting download for ${absolutePath}`);\n downloadTasks[downloadKey] = (async () => {\n try {\n const response = await fetch(absolutePath);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch file from URL ${absolutePath}: ${response.status} ${response.statusText}`,\n );\n }\n\n const stream = response.body;\n if (!stream) {\n throw new Error(`No response body for URL ${absolutePath}`);\n }\n\n // Use temporary file to prevent reading incomplete downloads\n const tempPath = `${downloadCachePath}.tmp`;\n const writeStream = createWriteStream(tempPath);\n\n // @ts-ignore node web stream support in typescript is incorrect about this.\n const readable = Readable.fromWeb(stream);\n readable.pipe(writeStream);\n\n await new Promise<void>((resolve, reject) => {\n readable.on(\"error\", reject);\n writeStream.on(\"error\", reject);\n writeStream.on(\"finish\", () => resolve());\n });\n\n // Atomically move completed file to final location\n await rename(tempPath, downloadCachePath);\n\n log(`Download completed for ${absolutePath}`);\n return downloadCachePath;\n } catch (error) {\n log(`Download failed for ${absolutePath}: ${error}`);\n // Clean up task reference on failure\n delete downloadTasks[downloadKey];\n throw error;\n }\n })();\n }\n\n absolutePath = await downloadTasks[downloadKey];\n // Clean up completed task\n delete downloadTasks[downloadKey];\n }\n }\n\n // Deduplicate concurrent callers by input parameters before any async work.\n // Using a synchronous key prevents the TOCTOU race where two concurrent\n // callers both pass the tasks[] check before either registers a task.\n const inputKey = JSON.stringify([absolutePath, ...args]);\n if (tasks[inputKey]) {\n log(`Returning existing ef:${label} task for ${absolutePath}`);\n return await tasks[inputKey];\n }\n\n const fullTask = (async (): Promise<TaskResult> => {\n try {\n // Try to find existing cache by scanning cache directories.\n // This avoids expensive MD5 computation when cache already exists.\n const expectedFilename = filename(absolutePath, ...args);\n let cachePath: string | null = null;\n let md5: string | null = null;\n\n const scanStartTime = Date.now();\n try {\n const cacheDirs = await readdir(cacheDirRoot, {\n withFileTypes: true,\n });\n log(`Scanning ${cacheDirs.length} cache directories for ${expectedFilename}`);\n for (const dir of cacheDirs) {\n if (dir.isDirectory()) {\n const candidatePath = path.join(cacheDirRoot, dir.name, expectedFilename);\n if (existsSync(candidatePath) && (await isValidCacheFile(candidatePath))) {\n cachePath = candidatePath;\n md5 = dir.name; // Directory name is the MD5\n const scanElapsed = Date.now() - scanStartTime;\n log(`Found existing cache in ${scanElapsed}ms: ${candidatePath} (skipped MD5)`);\n break;\n }\n }\n }\n if (!cachePath) {\n const scanElapsed = Date.now() - scanStartTime;\n log(`Cache scan completed in ${scanElapsed}ms, no cache found - will compute MD5`);\n }\n } catch (error) {\n const scanElapsed = Date.now() - scanStartTime;\n log(`Cache scan failed after ${scanElapsed}ms, will compute MD5: ${error}`);\n }\n\n const resolvedMd5 =\n md5 ??\n (await (async () => {\n const md5StartTime = Date.now();\n log(`Computing MD5 for ${absolutePath}...`);\n const computed = await md5FilePath(absolutePath);\n const md5Elapsed = Date.now() - md5StartTime;\n log(`MD5 computed in ${md5Elapsed}ms: ${computed}`);\n return computed;\n })());\n\n const cacheDir = path.join(cacheDirRoot, resolvedMd5);\n log(`Cache dir: ${cacheDir}`);\n await mkdir(cacheDir, { recursive: true });\n\n const resolvedCachePath = cachePath ?? path.join(cacheDir, expectedFilename);\n\n // Check if cache exists and is valid (not zero-byte)\n if (existsSync(resolvedCachePath) && (await isValidCacheFile(resolvedCachePath))) {\n log(`Returning cached ef:${label} task for ${resolvedCachePath}`);\n return { cachePath: resolvedCachePath, md5Sum: resolvedMd5 };\n }\n\n log(`Running ef:${label} runner for ${resolvedCachePath}`);\n await acquireRunnerSlot();\n let result: string | Readable;\n try {\n result = await runner(absolutePath, ...args);\n } finally {\n releaseRunnerSlot();\n }\n\n if (result instanceof Readable) {\n log(`Piping task for ${resolvedCachePath} to cache`);\n const tempPath = `${resolvedCachePath}.tmp`;\n const writeStream = createWriteStream(tempPath);\n result.pipe(writeStream);\n\n await new Promise<void>((resolve, reject) => {\n result.on(\"error\", reject);\n writeStream.on(\"error\", reject);\n writeStream.on(\"finish\", () => resolve());\n });\n\n await rename(tempPath, resolvedCachePath);\n } else {\n log(`Writing to ${resolvedCachePath}`);\n await writeFile(resolvedCachePath, result);\n }\n\n return {\n md5Sum: resolvedMd5,\n cachePath: resolvedCachePath,\n };\n } finally {\n delete tasks[inputKey];\n }\n })();\n\n tasks[inputKey] = fullTask;\n return await fullTask;\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"idempotentTask.js","names":[],"sources":["../src/idempotentTask.ts"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,13 +1,13 @@
1
- const require_Probe = require('./Probe.cjs');
2
- const require_generateFragmentIndex = require('./generateFragmentIndex.cjs');
3
- const require_md5 = require('./md5.cjs');
4
- const require_generateTrackFragmentIndex = require('./tasks/generateTrackFragmentIndex.cjs');
5
- const require_generateTrack = require('./tasks/generateTrack.cjs');
6
- const require_generateScrubTrack = require('./tasks/generateScrubTrack.cjs');
7
- const require_findOrCreateCaptions = require('./tasks/findOrCreateCaptions.cjs');
8
- const require_cacheImage = require('./tasks/cacheImage.cjs');
9
- const require_VideoRenderOptions = require('./VideoRenderOptions.cjs');
10
-
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_Probe = require("./Probe.cjs");
3
+ const require_generateFragmentIndex = require("./generateFragmentIndex.cjs");
4
+ const require_md5 = require("./md5.cjs");
5
+ const require_generateTrackFragmentIndex = require("./tasks/generateTrackFragmentIndex.cjs");
6
+ const require_generateTrack = require("./tasks/generateTrack.cjs");
7
+ const require_generateScrubTrack = require("./tasks/generateScrubTrack.cjs");
8
+ const require_findOrCreateCaptions = require("./tasks/findOrCreateCaptions.cjs");
9
+ const require_cacheImage = require("./tasks/cacheImage.cjs");
10
+ const require_VideoRenderOptions = require("./VideoRenderOptions.cjs");
11
11
  exports.PacketProbe = require_Probe.PacketProbe;
12
12
  exports.Probe = require_Probe.Probe;
13
13
  exports.VideoRenderOptions = require_VideoRenderOptions.VideoRenderOptions;
@@ -24,4 +24,4 @@ exports.generateTrackFromPath = require_generateTrack.generateTrackFromPath;
24
24
  exports.md5Buffer = require_md5.md5Buffer;
25
25
  exports.md5Directory = require_md5.md5Directory;
26
26
  exports.md5FilePath = require_md5.md5FilePath;
27
- exports.md5ReadStream = require_md5.md5ReadStream;
27
+ exports.md5ReadStream = require_md5.md5ReadStream;
package/dist/index.js CHANGED
@@ -7,5 +7,4 @@ import { generateScrubTrack, generateScrubTrackFromPath } from "./tasks/generate
7
7
  import { findOrCreateCaptions, generateCaptionDataFromPath } from "./tasks/findOrCreateCaptions.js";
8
8
  import { cacheImage } from "./tasks/cacheImage.js";
9
9
  import { VideoRenderOptions } from "./VideoRenderOptions.js";
10
-
11
- export { PacketProbe, Probe, VideoRenderOptions, cacheImage, findOrCreateCaptions, generateCaptionDataFromPath, generateFragmentIndex, generateScrubTrack, generateScrubTrackFromPath, generateTrack, generateTrackFragmentIndex, generateTrackFragmentIndexFromPath, generateTrackFromPath, md5Buffer, md5Directory, md5FilePath, md5ReadStream };
10
+ export { PacketProbe, Probe, VideoRenderOptions, cacheImage, findOrCreateCaptions, generateCaptionDataFromPath, generateFragmentIndex, generateScrubTrack, generateScrubTrackFromPath, generateTrack, generateTrackFragmentIndex, generateTrackFragmentIndexFromPath, generateTrackFromPath, md5Buffer, md5Directory, md5FilePath, md5ReadStream };
package/dist/md5.cjs CHANGED
@@ -1,13 +1,9 @@
1
- const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
1
+ const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
2
2
  let node_fs = require("node:fs");
3
- node_fs = require_rolldown_runtime.__toESM(node_fs);
4
3
  let node_fs_promises = require("node:fs/promises");
5
- node_fs_promises = require_rolldown_runtime.__toESM(node_fs_promises);
6
4
  let node_path = require("node:path");
7
- node_path = require_rolldown_runtime.__toESM(node_path);
8
5
  let node_crypto = require("node:crypto");
9
- node_crypto = require_rolldown_runtime.__toESM(node_crypto);
10
-
6
+ node_crypto = require_runtime.__toESM(node_crypto);
11
7
  //#region src/md5.ts
12
8
  async function md5Directory(directory, spinner) {
13
9
  const shouldEndSpinner = !spinner;
@@ -55,10 +51,10 @@ function addDashesToUUID(uuidWithoutDashes) {
55
51
  if (uuidWithoutDashes.length !== 32) throw new Error("Invalid UUID without dashes. Expected 32 characters.");
56
52
  return uuidWithoutDashes.slice(0, 8) + "-" + uuidWithoutDashes.slice(8, 12) + "-" + uuidWithoutDashes.slice(12, 16) + "-" + uuidWithoutDashes.slice(16, 20) + "-" + uuidWithoutDashes.slice(20, 32);
57
53
  }
58
-
59
54
  //#endregion
60
55
  exports.md5Buffer = md5Buffer;
61
56
  exports.md5Directory = md5Directory;
62
57
  exports.md5FilePath = md5FilePath;
63
58
  exports.md5ReadStream = md5ReadStream;
59
+
64
60
  //# sourceMappingURL=md5.cjs.map
package/dist/md5.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"md5.cjs","names":["crypto"],"sources":["../src/md5.ts"],"sourcesContent":["import { type ReadStream, createReadStream } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport crypto from \"node:crypto\";\nimport type { Ora } from \"ora\";\n\n// Recursively calculate the MD5 hash of all files in a directory\nexport async function md5Directory(directory: string, spinner?: Ora) {\n const shouldEndSpinner = !spinner;\n if (!spinner) {\n const { default: ora } = await import(\"ora\");\n spinner = ora(\"⚡️ Calculating MD5\").start();\n }\n spinner.suffixText = directory;\n const files = await readdir(directory, { withFileTypes: true });\n const hashes = await Promise.all(\n files.map(async (file) => {\n const filePath = join(directory, file.name);\n if (file.isDirectory()) {\n return md5Directory(filePath, spinner);\n }\n spinner.suffixText = filePath;\n return md5FilePath(filePath);\n }),\n );\n\n const hash = crypto.createHash(\"md5\");\n for (const fileHash of hashes) {\n hash.update(fileHash);\n }\n\n if (shouldEndSpinner) {\n spinner.succeed(\"MD5 calculated\");\n spinner.suffixText = directory;\n }\n return addDashesToUUID(hash.digest(\"hex\"));\n}\n\nexport async function md5FilePath(filePath: string) {\n const readStream = createReadStream(filePath);\n return md5ReadStream(readStream);\n}\n\nexport function md5ReadStream(readStream: ReadStream) {\n return new Promise<string>((resolve, reject) => {\n const hash = crypto.createHash(\"md5\");\n readStream.on(\"data\", (data) => {\n hash.update(data);\n });\n readStream.on(\"error\", reject);\n readStream.on(\"end\", () => {\n resolve(addDashesToUUID(hash.digest(\"hex\")));\n });\n });\n}\n\nexport function md5Buffer(buffer: Buffer) {\n const hash = crypto.createHash(\"md5\");\n hash.update(buffer);\n return addDashesToUUID(hash.digest(\"hex\"));\n}\n\nfunction addDashesToUUID(uuidWithoutDashes: string) {\n if (uuidWithoutDashes.length !== 32) {\n throw new Error(\"Invalid UUID without dashes. Expected 32 characters.\");\n }\n\n return (\n // biome-ignore lint/style/useTemplate: using a template makes a long line\n uuidWithoutDashes.slice(0, 8) +\n \"-\" +\n uuidWithoutDashes.slice(8, 12) +\n \"-\" +\n uuidWithoutDashes.slice(12, 16) +\n \"-\" +\n uuidWithoutDashes.slice(16, 20) +\n \"-\" +\n uuidWithoutDashes.slice(20, 32)\n );\n}\n"],"mappings":";;;;;;;;;;;AAOA,eAAsB,aAAa,WAAmB,SAAe;CACnE,MAAM,mBAAmB,CAAC;AAC1B,KAAI,CAAC,SAAS;EACZ,MAAM,EAAE,SAAS,QAAQ,MAAM,OAAO;AACtC,YAAU,IAAI,qBAAqB,CAAC,OAAO;;AAE7C,SAAQ,aAAa;CACrB,MAAM,QAAQ,oCAAc,WAAW,EAAE,eAAe,MAAM,CAAC;CAC/D,MAAM,SAAS,MAAM,QAAQ,IAC3B,MAAM,IAAI,OAAO,SAAS;EACxB,MAAM,+BAAgB,WAAW,KAAK,KAAK;AAC3C,MAAI,KAAK,aAAa,CACpB,QAAO,aAAa,UAAU,QAAQ;AAExC,UAAQ,aAAa;AACrB,SAAO,YAAY,SAAS;GAC5B,CACH;CAED,MAAM,OAAOA,oBAAO,WAAW,MAAM;AACrC,MAAK,MAAM,YAAY,OACrB,MAAK,OAAO,SAAS;AAGvB,KAAI,kBAAkB;AACpB,UAAQ,QAAQ,iBAAiB;AACjC,UAAQ,aAAa;;AAEvB,QAAO,gBAAgB,KAAK,OAAO,MAAM,CAAC;;AAG5C,eAAsB,YAAY,UAAkB;AAElD,QAAO,4CAD6B,SAAS,CACb;;AAGlC,SAAgB,cAAc,YAAwB;AACpD,QAAO,IAAI,SAAiB,SAAS,WAAW;EAC9C,MAAM,OAAOA,oBAAO,WAAW,MAAM;AACrC,aAAW,GAAG,SAAS,SAAS;AAC9B,QAAK,OAAO,KAAK;IACjB;AACF,aAAW,GAAG,SAAS,OAAO;AAC9B,aAAW,GAAG,aAAa;AACzB,WAAQ,gBAAgB,KAAK,OAAO,MAAM,CAAC,CAAC;IAC5C;GACF;;AAGJ,SAAgB,UAAU,QAAgB;CACxC,MAAM,OAAOA,oBAAO,WAAW,MAAM;AACrC,MAAK,OAAO,OAAO;AACnB,QAAO,gBAAgB,KAAK,OAAO,MAAM,CAAC;;AAG5C,SAAS,gBAAgB,mBAA2B;AAClD,KAAI,kBAAkB,WAAW,GAC/B,OAAM,IAAI,MAAM,uDAAuD;AAGzE,QAEE,kBAAkB,MAAM,GAAG,EAAE,GAC7B,MACA,kBAAkB,MAAM,GAAG,GAAG,GAC9B,MACA,kBAAkB,MAAM,IAAI,GAAG,GAC/B,MACA,kBAAkB,MAAM,IAAI,GAAG,GAC/B,MACA,kBAAkB,MAAM,IAAI,GAAG"}
1
+ {"version":3,"file":"md5.cjs","names":["crypto"],"sources":["../src/md5.ts"],"mappings":";;;;;;;AAOA,eAAsB,aAAa,WAAmB,SAAe;CACnE,MAAM,mBAAmB,CAAC;AAC1B,KAAI,CAAC,SAAS;EACZ,MAAM,EAAE,SAAS,QAAQ,MAAM,OAAO;AACtC,YAAU,IAAI,qBAAqB,CAAC,OAAO;;AAE7C,SAAQ,aAAa;CACrB,MAAM,QAAQ,OAAA,GAAA,iBAAA,SAAc,WAAW,EAAE,eAAe,MAAM,CAAC;CAC/D,MAAM,SAAS,MAAM,QAAQ,IAC3B,MAAM,IAAI,OAAO,SAAS;EACxB,MAAM,YAAA,GAAA,UAAA,MAAgB,WAAW,KAAK,KAAK;AAC3C,MAAI,KAAK,aAAa,CACpB,QAAO,aAAa,UAAU,QAAQ;AAExC,UAAQ,aAAa;AACrB,SAAO,YAAY,SAAS;GAC5B,CACH;CAED,MAAM,OAAOA,YAAAA,QAAO,WAAW,MAAM;AACrC,MAAK,MAAM,YAAY,OACrB,MAAK,OAAO,SAAS;AAGvB,KAAI,kBAAkB;AACpB,UAAQ,QAAQ,iBAAiB;AACjC,UAAQ,aAAa;;AAEvB,QAAO,gBAAgB,KAAK,OAAO,MAAM,CAAC;;AAG5C,eAAsB,YAAY,UAAkB;AAElD,QAAO,eAAA,GAAA,QAAA,kBAD6B,SAAS,CACb;;AAGlC,SAAgB,cAAc,YAAwB;AACpD,QAAO,IAAI,SAAiB,SAAS,WAAW;EAC9C,MAAM,OAAOA,YAAAA,QAAO,WAAW,MAAM;AACrC,aAAW,GAAG,SAAS,SAAS;AAC9B,QAAK,OAAO,KAAK;IACjB;AACF,aAAW,GAAG,SAAS,OAAO;AAC9B,aAAW,GAAG,aAAa;AACzB,WAAQ,gBAAgB,KAAK,OAAO,MAAM,CAAC,CAAC;IAC5C;GACF;;AAGJ,SAAgB,UAAU,QAAgB;CACxC,MAAM,OAAOA,YAAAA,QAAO,WAAW,MAAM;AACrC,MAAK,OAAO,OAAO;AACnB,QAAO,gBAAgB,KAAK,OAAO,MAAM,CAAC;;AAG5C,SAAS,gBAAgB,mBAA2B;AAClD,KAAI,kBAAkB,WAAW,GAC/B,OAAM,IAAI,MAAM,uDAAuD;AAGzE,QAEE,kBAAkB,MAAM,GAAG,EAAE,GAC7B,MACA,kBAAkB,MAAM,GAAG,GAAG,GAC9B,MACA,kBAAkB,MAAM,IAAI,GAAG,GAC/B,MACA,kBAAkB,MAAM,IAAI,GAAG,GAC/B,MACA,kBAAkB,MAAM,IAAI,GAAG"}
package/dist/md5.js CHANGED
@@ -2,7 +2,6 @@ import { createReadStream } from "node:fs";
2
2
  import { readdir } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  import crypto from "node:crypto";
5
-
6
5
  //#region src/md5.ts
7
6
  async function md5Directory(directory, spinner) {
8
7
  const shouldEndSpinner = !spinner;
@@ -50,7 +49,7 @@ function addDashesToUUID(uuidWithoutDashes) {
50
49
  if (uuidWithoutDashes.length !== 32) throw new Error("Invalid UUID without dashes. Expected 32 characters.");
51
50
  return uuidWithoutDashes.slice(0, 8) + "-" + uuidWithoutDashes.slice(8, 12) + "-" + uuidWithoutDashes.slice(12, 16) + "-" + uuidWithoutDashes.slice(16, 20) + "-" + uuidWithoutDashes.slice(20, 32);
52
51
  }
53
-
54
52
  //#endregion
55
53
  export { md5Buffer, md5Directory, md5FilePath, md5ReadStream };
54
+
56
55
  //# sourceMappingURL=md5.js.map
package/dist/md5.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"md5.js","names":[],"sources":["../src/md5.ts"],"sourcesContent":["import { type ReadStream, createReadStream } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport crypto from \"node:crypto\";\nimport type { Ora } from \"ora\";\n\n// Recursively calculate the MD5 hash of all files in a directory\nexport async function md5Directory(directory: string, spinner?: Ora) {\n const shouldEndSpinner = !spinner;\n if (!spinner) {\n const { default: ora } = await import(\"ora\");\n spinner = ora(\"⚡️ Calculating MD5\").start();\n }\n spinner.suffixText = directory;\n const files = await readdir(directory, { withFileTypes: true });\n const hashes = await Promise.all(\n files.map(async (file) => {\n const filePath = join(directory, file.name);\n if (file.isDirectory()) {\n return md5Directory(filePath, spinner);\n }\n spinner.suffixText = filePath;\n return md5FilePath(filePath);\n }),\n );\n\n const hash = crypto.createHash(\"md5\");\n for (const fileHash of hashes) {\n hash.update(fileHash);\n }\n\n if (shouldEndSpinner) {\n spinner.succeed(\"MD5 calculated\");\n spinner.suffixText = directory;\n }\n return addDashesToUUID(hash.digest(\"hex\"));\n}\n\nexport async function md5FilePath(filePath: string) {\n const readStream = createReadStream(filePath);\n return md5ReadStream(readStream);\n}\n\nexport function md5ReadStream(readStream: ReadStream) {\n return new Promise<string>((resolve, reject) => {\n const hash = crypto.createHash(\"md5\");\n readStream.on(\"data\", (data) => {\n hash.update(data);\n });\n readStream.on(\"error\", reject);\n readStream.on(\"end\", () => {\n resolve(addDashesToUUID(hash.digest(\"hex\")));\n });\n });\n}\n\nexport function md5Buffer(buffer: Buffer) {\n const hash = crypto.createHash(\"md5\");\n hash.update(buffer);\n return addDashesToUUID(hash.digest(\"hex\"));\n}\n\nfunction addDashesToUUID(uuidWithoutDashes: string) {\n if (uuidWithoutDashes.length !== 32) {\n throw new Error(\"Invalid UUID without dashes. Expected 32 characters.\");\n }\n\n return (\n // biome-ignore lint/style/useTemplate: using a template makes a long line\n uuidWithoutDashes.slice(0, 8) +\n \"-\" +\n uuidWithoutDashes.slice(8, 12) +\n \"-\" +\n uuidWithoutDashes.slice(12, 16) +\n \"-\" +\n uuidWithoutDashes.slice(16, 20) +\n \"-\" +\n uuidWithoutDashes.slice(20, 32)\n );\n}\n"],"mappings":";;;;;;AAOA,eAAsB,aAAa,WAAmB,SAAe;CACnE,MAAM,mBAAmB,CAAC;AAC1B,KAAI,CAAC,SAAS;EACZ,MAAM,EAAE,SAAS,QAAQ,MAAM,OAAO;AACtC,YAAU,IAAI,qBAAqB,CAAC,OAAO;;AAE7C,SAAQ,aAAa;CACrB,MAAM,QAAQ,MAAM,QAAQ,WAAW,EAAE,eAAe,MAAM,CAAC;CAC/D,MAAM,SAAS,MAAM,QAAQ,IAC3B,MAAM,IAAI,OAAO,SAAS;EACxB,MAAM,WAAW,KAAK,WAAW,KAAK,KAAK;AAC3C,MAAI,KAAK,aAAa,CACpB,QAAO,aAAa,UAAU,QAAQ;AAExC,UAAQ,aAAa;AACrB,SAAO,YAAY,SAAS;GAC5B,CACH;CAED,MAAM,OAAO,OAAO,WAAW,MAAM;AACrC,MAAK,MAAM,YAAY,OACrB,MAAK,OAAO,SAAS;AAGvB,KAAI,kBAAkB;AACpB,UAAQ,QAAQ,iBAAiB;AACjC,UAAQ,aAAa;;AAEvB,QAAO,gBAAgB,KAAK,OAAO,MAAM,CAAC;;AAG5C,eAAsB,YAAY,UAAkB;AAElD,QAAO,cADY,iBAAiB,SAAS,CACb;;AAGlC,SAAgB,cAAc,YAAwB;AACpD,QAAO,IAAI,SAAiB,SAAS,WAAW;EAC9C,MAAM,OAAO,OAAO,WAAW,MAAM;AACrC,aAAW,GAAG,SAAS,SAAS;AAC9B,QAAK,OAAO,KAAK;IACjB;AACF,aAAW,GAAG,SAAS,OAAO;AAC9B,aAAW,GAAG,aAAa;AACzB,WAAQ,gBAAgB,KAAK,OAAO,MAAM,CAAC,CAAC;IAC5C;GACF;;AAGJ,SAAgB,UAAU,QAAgB;CACxC,MAAM,OAAO,OAAO,WAAW,MAAM;AACrC,MAAK,OAAO,OAAO;AACnB,QAAO,gBAAgB,KAAK,OAAO,MAAM,CAAC;;AAG5C,SAAS,gBAAgB,mBAA2B;AAClD,KAAI,kBAAkB,WAAW,GAC/B,OAAM,IAAI,MAAM,uDAAuD;AAGzE,QAEE,kBAAkB,MAAM,GAAG,EAAE,GAC7B,MACA,kBAAkB,MAAM,GAAG,GAAG,GAC9B,MACA,kBAAkB,MAAM,IAAI,GAAG,GAC/B,MACA,kBAAkB,MAAM,IAAI,GAAG,GAC/B,MACA,kBAAkB,MAAM,IAAI,GAAG"}
1
+ {"version":3,"file":"md5.js","names":[],"sources":["../src/md5.ts"],"mappings":";;;;;AAOA,eAAsB,aAAa,WAAmB,SAAe;CACnE,MAAM,mBAAmB,CAAC;AAC1B,KAAI,CAAC,SAAS;EACZ,MAAM,EAAE,SAAS,QAAQ,MAAM,OAAO;AACtC,YAAU,IAAI,qBAAqB,CAAC,OAAO;;AAE7C,SAAQ,aAAa;CACrB,MAAM,QAAQ,MAAM,QAAQ,WAAW,EAAE,eAAe,MAAM,CAAC;CAC/D,MAAM,SAAS,MAAM,QAAQ,IAC3B,MAAM,IAAI,OAAO,SAAS;EACxB,MAAM,WAAW,KAAK,WAAW,KAAK,KAAK;AAC3C,MAAI,KAAK,aAAa,CACpB,QAAO,aAAa,UAAU,QAAQ;AAExC,UAAQ,aAAa;AACrB,SAAO,YAAY,SAAS;GAC5B,CACH;CAED,MAAM,OAAO,OAAO,WAAW,MAAM;AACrC,MAAK,MAAM,YAAY,OACrB,MAAK,OAAO,SAAS;AAGvB,KAAI,kBAAkB;AACpB,UAAQ,QAAQ,iBAAiB;AACjC,UAAQ,aAAa;;AAEvB,QAAO,gBAAgB,KAAK,OAAO,MAAM,CAAC;;AAG5C,eAAsB,YAAY,UAAkB;AAElD,QAAO,cADY,iBAAiB,SAAS,CACb;;AAGlC,SAAgB,cAAc,YAAwB;AACpD,QAAO,IAAI,SAAiB,SAAS,WAAW;EAC9C,MAAM,OAAO,OAAO,WAAW,MAAM;AACrC,aAAW,GAAG,SAAS,SAAS;AAC9B,QAAK,OAAO,KAAK;IACjB;AACF,aAAW,GAAG,SAAS,OAAO;AAC9B,aAAW,GAAG,aAAa;AACzB,WAAQ,gBAAgB,KAAK,OAAO,MAAM,CAAC,CAAC;IAC5C;GACF;;AAGJ,SAAgB,UAAU,QAAgB;CACxC,MAAM,OAAO,OAAO,WAAW,MAAM;AACrC,MAAK,OAAO,OAAO;AACnB,QAAO,gBAAgB,KAAK,OAAO,MAAM,CAAC;;AAG5C,SAAS,gBAAgB,mBAA2B;AAClD,KAAI,kBAAkB,WAAW,GAC/B,OAAM,IAAI,MAAM,uDAAuD;AAGzE,QAEE,kBAAkB,MAAM,GAAG,EAAE,GAC7B,MACA,kBAAkB,MAAM,GAAG,GAAG,GAC9B,MACA,kBAAkB,MAAM,IAAI,GAAG,GAC/B,MACA,kBAAkB,MAAM,IAAI,GAAG,GAC/B,MACA,kBAAkB,MAAM,IAAI,GAAG"}