@editframe/assets 0.47.2 → 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 (60) hide show
  1. package/dist/Probe.cjs +5 -8
  2. package/dist/Probe.cjs.map +1 -1
  3. package/dist/Probe.js +1 -2
  4. package/dist/Probe.js.map +1 -1
  5. package/dist/VideoRenderOptions.cjs +2 -4
  6. package/dist/VideoRenderOptions.cjs.map +1 -1
  7. package/dist/VideoRenderOptions.js +1 -2
  8. package/dist/VideoRenderOptions.js.map +1 -1
  9. package/dist/_virtual/{rolldown_runtime.cjs → _rolldown/runtime.cjs} +2 -4
  10. package/dist/generateFragmentIndex.cjs +4 -12
  11. package/dist/generateFragmentIndex.cjs.map +1 -1
  12. package/dist/generateFragmentIndex.d.cts +1 -2
  13. package/dist/generateFragmentIndex.d.ts +1 -2
  14. package/dist/generateFragmentIndex.js +1 -2
  15. package/dist/generateFragmentIndex.js.map +1 -1
  16. package/dist/generateSingleTrack.cjs +7 -10
  17. package/dist/generateSingleTrack.cjs.map +1 -1
  18. package/dist/generateSingleTrack.js +2 -3
  19. package/dist/generateSingleTrack.js.map +1 -1
  20. package/dist/generateWebmSegmentIndex.cjs +31 -8
  21. package/dist/generateWebmSegmentIndex.cjs.map +1 -1
  22. package/dist/generateWebmSegmentIndex.js +28 -4
  23. package/dist/generateWebmSegmentIndex.js.map +1 -1
  24. package/dist/idempotentTask.cjs +5 -10
  25. package/dist/idempotentTask.cjs.map +1 -1
  26. package/dist/idempotentTask.d.cts +0 -1
  27. package/dist/idempotentTask.d.ts +0 -1
  28. package/dist/idempotentTask.js +1 -2
  29. package/dist/idempotentTask.js.map +1 -1
  30. package/dist/index.cjs +11 -11
  31. package/dist/index.js +1 -2
  32. package/dist/md5.cjs +3 -7
  33. package/dist/md5.cjs.map +1 -1
  34. package/dist/md5.js +1 -2
  35. package/dist/md5.js.map +1 -1
  36. package/dist/tasks/cacheImage.cjs +4 -6
  37. package/dist/tasks/cacheImage.cjs.map +1 -1
  38. package/dist/tasks/cacheImage.js +1 -2
  39. package/dist/tasks/cacheImage.js.map +1 -1
  40. package/dist/tasks/findOrCreateCaptions.cjs +5 -10
  41. package/dist/tasks/findOrCreateCaptions.cjs.map +1 -1
  42. package/dist/tasks/findOrCreateCaptions.js +1 -2
  43. package/dist/tasks/findOrCreateCaptions.js.map +1 -1
  44. package/dist/tasks/generateScrubTrack.cjs +6 -9
  45. package/dist/tasks/generateScrubTrack.cjs.map +1 -1
  46. package/dist/tasks/generateScrubTrack.js +1 -2
  47. package/dist/tasks/generateScrubTrack.js.map +1 -1
  48. package/dist/tasks/generateTrack.cjs +7 -11
  49. package/dist/tasks/generateTrack.cjs.map +1 -1
  50. package/dist/tasks/generateTrack.js +1 -2
  51. package/dist/tasks/generateTrack.js.map +1 -1
  52. package/dist/tasks/generateTrackFragmentIndex.cjs +11 -13
  53. package/dist/tasks/generateTrackFragmentIndex.cjs.map +1 -1
  54. package/dist/tasks/generateTrackFragmentIndex.js +5 -6
  55. package/dist/tasks/generateTrackFragmentIndex.js.map +1 -1
  56. package/dist/truncateDecimal.cjs +1 -2
  57. package/dist/truncateDecimal.cjs.map +1 -1
  58. package/dist/truncateDecimal.js +1 -1
  59. package/dist/truncateDecimal.js.map +1 -1
  60. package/package.json +1 -1
@@ -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"}
@@ -1,10 +1,8 @@
1
- const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
- const require_idempotentTask = require('../idempotentTask.cjs');
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_idempotentTask = require("../idempotentTask.cjs");
3
3
  let node_fs = require("node:fs");
4
- node_fs = require_rolldown_runtime.__toESM(node_fs);
5
4
  let node_path = require("node:path");
6
- node_path = require_rolldown_runtime.__toESM(node_path);
7
-
5
+ node_path = require_runtime.__toESM(node_path);
8
6
  //#region src/tasks/cacheImage.ts
9
7
  const cacheImageTask = require_idempotentTask.idempotentTask({
10
8
  label: "image",
@@ -22,7 +20,7 @@ const cacheImage = async (cacheRoot, absolutePath) => {
22
20
  throw error;
23
21
  }
24
22
  };
25
-
26
23
  //#endregion
27
24
  exports.cacheImage = cacheImage;
25
+
28
26
  //# sourceMappingURL=cacheImage.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"cacheImage.cjs","names":["idempotentTask","path"],"sources":["../../src/tasks/cacheImage.ts"],"sourcesContent":["import { idempotentTask } from \"../idempotentTask.js\";\nimport { createReadStream } from \"node:fs\";\n\nimport path from \"node:path\";\n\nconst cacheImageTask = idempotentTask({\n label: \"image\",\n filename: (absolutePath: string) => path.basename(absolutePath),\n runner: async (absolutePath) => {\n return createReadStream(absolutePath);\n },\n});\n\nexport const cacheImage = async (cacheRoot: string, absolutePath: string) => {\n try {\n return await cacheImageTask(cacheRoot, absolutePath);\n } catch (error) {\n console.error(error);\n console.trace(\"Error caching image\", error);\n throw error;\n }\n};\n"],"mappings":";;;;;;;;AAKA,MAAM,iBAAiBA,sCAAe;CACpC,OAAO;CACP,WAAW,iBAAyBC,kBAAK,SAAS,aAAa;CAC/D,QAAQ,OAAO,iBAAiB;AAC9B,uCAAwB,aAAa;;CAExC,CAAC;AAEF,MAAa,aAAa,OAAO,WAAmB,iBAAyB;AAC3E,KAAI;AACF,SAAO,MAAM,eAAe,WAAW,aAAa;UAC7C,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,uBAAuB,MAAM;AAC3C,QAAM"}
1
+ {"version":3,"file":"cacheImage.cjs","names":["idempotentTask","path"],"sources":["../../src/tasks/cacheImage.ts"],"mappings":";;;;;;AAKA,MAAM,iBAAiBA,uBAAAA,eAAe;CACpC,OAAO;CACP,WAAW,iBAAyBC,UAAAA,QAAK,SAAS,aAAa;CAC/D,QAAQ,OAAO,iBAAiB;AAC9B,UAAA,GAAA,QAAA,kBAAwB,aAAa;;CAExC,CAAC;AAEF,MAAa,aAAa,OAAO,WAAmB,iBAAyB;AAC3E,KAAI;AACF,SAAO,MAAM,eAAe,WAAW,aAAa;UAC7C,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,uBAAuB,MAAM;AAC3C,QAAM"}
@@ -1,7 +1,6 @@
1
1
  import { idempotentTask } from "../idempotentTask.js";
2
2
  import { createReadStream } from "node:fs";
3
3
  import path from "node:path";
4
-
5
4
  //#region src/tasks/cacheImage.ts
6
5
  const cacheImageTask = idempotentTask({
7
6
  label: "image",
@@ -19,7 +18,7 @@ const cacheImage = async (cacheRoot, absolutePath) => {
19
18
  throw error;
20
19
  }
21
20
  };
22
-
23
21
  //#endregion
24
22
  export { cacheImage };
23
+
25
24
  //# sourceMappingURL=cacheImage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cacheImage.js","names":[],"sources":["../../src/tasks/cacheImage.ts"],"sourcesContent":["import { idempotentTask } from \"../idempotentTask.js\";\nimport { createReadStream } from \"node:fs\";\n\nimport path from \"node:path\";\n\nconst cacheImageTask = idempotentTask({\n label: \"image\",\n filename: (absolutePath: string) => path.basename(absolutePath),\n runner: async (absolutePath) => {\n return createReadStream(absolutePath);\n },\n});\n\nexport const cacheImage = async (cacheRoot: string, absolutePath: string) => {\n try {\n return await cacheImageTask(cacheRoot, absolutePath);\n } catch (error) {\n console.error(error);\n console.trace(\"Error caching image\", error);\n throw error;\n }\n};\n"],"mappings":";;;;;AAKA,MAAM,iBAAiB,eAAe;CACpC,OAAO;CACP,WAAW,iBAAyB,KAAK,SAAS,aAAa;CAC/D,QAAQ,OAAO,iBAAiB;AAC9B,SAAO,iBAAiB,aAAa;;CAExC,CAAC;AAEF,MAAa,aAAa,OAAO,WAAmB,iBAAyB;AAC3E,KAAI;AACF,SAAO,MAAM,eAAe,WAAW,aAAa;UAC7C,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,uBAAuB,MAAM;AAC3C,QAAM"}
1
+ {"version":3,"file":"cacheImage.js","names":[],"sources":["../../src/tasks/cacheImage.ts"],"mappings":";;;;AAKA,MAAM,iBAAiB,eAAe;CACpC,OAAO;CACP,WAAW,iBAAyB,KAAK,SAAS,aAAa;CAC/D,QAAQ,OAAO,iBAAiB;AAC9B,SAAO,iBAAiB,aAAa;;CAExC,CAAC;AAEF,MAAa,aAAa,OAAO,WAAmB,iBAAyB;AAC3E,KAAI;AACF,SAAO,MAAM,eAAe,WAAW,aAAa;UAC7C,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,uBAAuB,MAAM;AAC3C,QAAM"}
@@ -1,16 +1,11 @@
1
- const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
- const require_idempotentTask = require('../idempotentTask.cjs');
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_idempotentTask = require("../idempotentTask.cjs");
3
3
  let node_child_process = require("node:child_process");
4
- node_child_process = require_rolldown_runtime.__toESM(node_child_process);
5
4
  let debug = require("debug");
6
- debug = require_rolldown_runtime.__toESM(debug);
5
+ debug = require_runtime.__toESM(debug);
7
6
  let node_path = require("node:path");
8
- node_path = require_rolldown_runtime.__toESM(node_path);
9
- let node_util = require("node:util");
10
- node_util = require_rolldown_runtime.__toESM(node_util);
11
-
12
7
  //#region src/tasks/findOrCreateCaptions.ts
13
- const execFilePromise = (0, node_util.promisify)(node_child_process.execFile);
8
+ const execFilePromise = (0, require("node:util").promisify)(node_child_process.execFile);
14
9
  const log = (0, debug.default)("ef:generateCaptions");
15
10
  const convertWhisperToEditframeFormat = (whisperData) => {
16
11
  return {
@@ -58,8 +53,8 @@ const findOrCreateCaptions = async (cacheRoot, absolutePath) => {
58
53
  throw error;
59
54
  }
60
55
  };
61
-
62
56
  //#endregion
63
57
  exports.findOrCreateCaptions = findOrCreateCaptions;
64
58
  exports.generateCaptionDataFromPath = generateCaptionDataFromPath;
59
+
65
60
  //# sourceMappingURL=findOrCreateCaptions.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"findOrCreateCaptions.cjs","names":["execFile","idempotentTask"],"sources":["../../src/tasks/findOrCreateCaptions.ts"],"sourcesContent":["import { basename } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { execFile } from \"node:child_process\";\n\nimport debug from \"debug\";\n\nimport { idempotentTask } from \"../idempotentTask.js\";\n\nconst execFilePromise = promisify(execFile);\n\nconst log = debug(\"ef:generateCaptions\");\n\ninterface WhisperWord {\n text: string;\n start: number;\n end: number;\n confidence: number;\n}\n\ninterface WhisperSegment {\n text: string;\n start: number;\n end: number;\n words: WhisperWord[];\n}\n\ninterface WhisperOutput {\n segments: WhisperSegment[];\n}\n\ninterface CaptionOutput {\n segments: Array<{\n start: number;\n end: number;\n text: string;\n }>;\n word_segments: Array<{\n text: string;\n start: number;\n end: number;\n }>;\n}\n\nconst convertWhisperToEditframeFormat = (whisperData: WhisperOutput): CaptionOutput => {\n const segments = whisperData.segments.map((segment) => ({\n start: Math.round(segment.start * 1000), // Convert to milliseconds\n end: Math.round(segment.end * 1000),\n text: segment.text.trim(),\n }));\n\n const word_segments = whisperData.segments.flatMap((segment) =>\n segment.words.map((word) => ({\n text: word.text,\n start: Math.round(word.start * 1000), // Convert to milliseconds\n end: Math.round(word.end * 1000),\n })),\n );\n\n return { segments, word_segments };\n};\n\nexport const generateCaptionDataFromPath = async (absolutePath: string) => {\n const args = [\"--language\", \"en\", \"--efficient\", \"--output_format\", \"json\", absolutePath];\n log(\"Running whisper_timestamped\", args);\n const { stdout } = await execFilePromise(\"whisper_timestamped\", args);\n\n try {\n const whisperData = JSON.parse(stdout) as WhisperOutput;\n const captionData = convertWhisperToEditframeFormat(whisperData);\n return JSON.stringify(captionData, null, 2);\n } catch (error) {\n log(`Error parsing whisper output: ${error}`);\n throw new Error(`Failed to parse whisper_timestamped output: ${error}`);\n }\n};\n\nconst generateCaptionDataTask = idempotentTask({\n label: \"captions\",\n filename: (absolutePath) => `${basename(absolutePath)}.captions.json`,\n runner: generateCaptionDataFromPath,\n});\n\nexport const findOrCreateCaptions = async (cacheRoot: string, absolutePath: string) => {\n try {\n return await generateCaptionDataTask(cacheRoot, absolutePath);\n } catch (error) {\n console.trace(\"Error finding or creating captions\", error);\n throw error;\n }\n};\n"],"mappings":";;;;;;;;;;;;AAQA,MAAM,2CAA4BA,4BAAS;AAE3C,MAAM,yBAAY,sBAAsB;AAiCxC,MAAM,mCAAmC,gBAA8C;AAerF,QAAO;EAAE,UAdQ,YAAY,SAAS,KAAK,aAAa;GACtD,OAAO,KAAK,MAAM,QAAQ,QAAQ,IAAK;GACvC,KAAK,KAAK,MAAM,QAAQ,MAAM,IAAK;GACnC,MAAM,QAAQ,KAAK,MAAM;GAC1B,EAAE;EAUgB,eARG,YAAY,SAAS,SAAS,YAClD,QAAQ,MAAM,KAAK,UAAU;GAC3B,MAAM,KAAK;GACX,OAAO,KAAK,MAAM,KAAK,QAAQ,IAAK;GACpC,KAAK,KAAK,MAAM,KAAK,MAAM,IAAK;GACjC,EAAE,CACJ;EAEiC;;AAGpC,MAAa,8BAA8B,OAAO,iBAAyB;CACzE,MAAM,OAAO;EAAC;EAAc;EAAM;EAAe;EAAmB;EAAQ;EAAa;AACzF,KAAI,+BAA+B,KAAK;CACxC,MAAM,EAAE,WAAW,MAAM,gBAAgB,uBAAuB,KAAK;AAErE,KAAI;EAEF,MAAM,cAAc,gCADA,KAAK,MAAM,OAAO,CAC0B;AAChE,SAAO,KAAK,UAAU,aAAa,MAAM,EAAE;UACpC,OAAO;AACd,MAAI,iCAAiC,QAAQ;AAC7C,QAAM,IAAI,MAAM,+CAA+C,QAAQ;;;AAI3E,MAAM,0BAA0BC,sCAAe;CAC7C,OAAO;CACP,WAAW,iBAAiB,2BAAY,aAAa,CAAC;CACtD,QAAQ;CACT,CAAC;AAEF,MAAa,uBAAuB,OAAO,WAAmB,iBAAyB;AACrF,KAAI;AACF,SAAO,MAAM,wBAAwB,WAAW,aAAa;UACtD,OAAO;AACd,UAAQ,MAAM,sCAAsC,MAAM;AAC1D,QAAM"}
1
+ {"version":3,"file":"findOrCreateCaptions.cjs","names":["execFile","idempotentTask"],"sources":["../../src/tasks/findOrCreateCaptions.ts"],"mappings":";;;;;;;AAQA,MAAM,mBAAA,wBAAA,WAA4BA,mBAAAA,SAAS;AAE3C,MAAM,OAAA,GAAA,MAAA,SAAY,sBAAsB;AAiCxC,MAAM,mCAAmC,gBAA8C;AAerF,QAAO;EAAE,UAdQ,YAAY,SAAS,KAAK,aAAa;GACtD,OAAO,KAAK,MAAM,QAAQ,QAAQ,IAAK;GACvC,KAAK,KAAK,MAAM,QAAQ,MAAM,IAAK;GACnC,MAAM,QAAQ,KAAK,MAAM;GAC1B,EAAE;EAUgB,eARG,YAAY,SAAS,SAAS,YAClD,QAAQ,MAAM,KAAK,UAAU;GAC3B,MAAM,KAAK;GACX,OAAO,KAAK,MAAM,KAAK,QAAQ,IAAK;GACpC,KAAK,KAAK,MAAM,KAAK,MAAM,IAAK;GACjC,EAAE,CACJ;EAEiC;;AAGpC,MAAa,8BAA8B,OAAO,iBAAyB;CACzE,MAAM,OAAO;EAAC;EAAc;EAAM;EAAe;EAAmB;EAAQ;EAAa;AACzF,KAAI,+BAA+B,KAAK;CACxC,MAAM,EAAE,WAAW,MAAM,gBAAgB,uBAAuB,KAAK;AAErE,KAAI;EAEF,MAAM,cAAc,gCADA,KAAK,MAAM,OAAO,CAC0B;AAChE,SAAO,KAAK,UAAU,aAAa,MAAM,EAAE;UACpC,OAAO;AACd,MAAI,iCAAiC,QAAQ;AAC7C,QAAM,IAAI,MAAM,+CAA+C,QAAQ;;;AAI3E,MAAM,0BAA0BC,uBAAAA,eAAe;CAC7C,OAAO;CACP,WAAW,iBAAiB,IAAA,GAAA,UAAA,UAAY,aAAa,CAAC;CACtD,QAAQ;CACT,CAAC;AAEF,MAAa,uBAAuB,OAAO,WAAmB,iBAAyB;AACrF,KAAI;AACF,SAAO,MAAM,wBAAwB,WAAW,aAAa;UACtD,OAAO;AACd,UAAQ,MAAM,sCAAsC,MAAM;AAC1D,QAAM"}
@@ -3,7 +3,6 @@ import { execFile } from "node:child_process";
3
3
  import debug from "debug";
4
4
  import { basename } from "node:path";
5
5
  import { promisify } from "node:util";
6
-
7
6
  //#region src/tasks/findOrCreateCaptions.ts
8
7
  const execFilePromise = promisify(execFile);
9
8
  const log = debug("ef:generateCaptions");
@@ -53,7 +52,7 @@ const findOrCreateCaptions = async (cacheRoot, absolutePath) => {
53
52
  throw error;
54
53
  }
55
54
  };
56
-
57
55
  //#endregion
58
56
  export { findOrCreateCaptions, generateCaptionDataFromPath };
57
+
59
58
  //# sourceMappingURL=findOrCreateCaptions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"findOrCreateCaptions.js","names":[],"sources":["../../src/tasks/findOrCreateCaptions.ts"],"sourcesContent":["import { basename } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { execFile } from \"node:child_process\";\n\nimport debug from \"debug\";\n\nimport { idempotentTask } from \"../idempotentTask.js\";\n\nconst execFilePromise = promisify(execFile);\n\nconst log = debug(\"ef:generateCaptions\");\n\ninterface WhisperWord {\n text: string;\n start: number;\n end: number;\n confidence: number;\n}\n\ninterface WhisperSegment {\n text: string;\n start: number;\n end: number;\n words: WhisperWord[];\n}\n\ninterface WhisperOutput {\n segments: WhisperSegment[];\n}\n\ninterface CaptionOutput {\n segments: Array<{\n start: number;\n end: number;\n text: string;\n }>;\n word_segments: Array<{\n text: string;\n start: number;\n end: number;\n }>;\n}\n\nconst convertWhisperToEditframeFormat = (whisperData: WhisperOutput): CaptionOutput => {\n const segments = whisperData.segments.map((segment) => ({\n start: Math.round(segment.start * 1000), // Convert to milliseconds\n end: Math.round(segment.end * 1000),\n text: segment.text.trim(),\n }));\n\n const word_segments = whisperData.segments.flatMap((segment) =>\n segment.words.map((word) => ({\n text: word.text,\n start: Math.round(word.start * 1000), // Convert to milliseconds\n end: Math.round(word.end * 1000),\n })),\n );\n\n return { segments, word_segments };\n};\n\nexport const generateCaptionDataFromPath = async (absolutePath: string) => {\n const args = [\"--language\", \"en\", \"--efficient\", \"--output_format\", \"json\", absolutePath];\n log(\"Running whisper_timestamped\", args);\n const { stdout } = await execFilePromise(\"whisper_timestamped\", args);\n\n try {\n const whisperData = JSON.parse(stdout) as WhisperOutput;\n const captionData = convertWhisperToEditframeFormat(whisperData);\n return JSON.stringify(captionData, null, 2);\n } catch (error) {\n log(`Error parsing whisper output: ${error}`);\n throw new Error(`Failed to parse whisper_timestamped output: ${error}`);\n }\n};\n\nconst generateCaptionDataTask = idempotentTask({\n label: \"captions\",\n filename: (absolutePath) => `${basename(absolutePath)}.captions.json`,\n runner: generateCaptionDataFromPath,\n});\n\nexport const findOrCreateCaptions = async (cacheRoot: string, absolutePath: string) => {\n try {\n return await generateCaptionDataTask(cacheRoot, absolutePath);\n } catch (error) {\n console.trace(\"Error finding or creating captions\", error);\n throw error;\n }\n};\n"],"mappings":";;;;;;;AAQA,MAAM,kBAAkB,UAAU,SAAS;AAE3C,MAAM,MAAM,MAAM,sBAAsB;AAiCxC,MAAM,mCAAmC,gBAA8C;AAerF,QAAO;EAAE,UAdQ,YAAY,SAAS,KAAK,aAAa;GACtD,OAAO,KAAK,MAAM,QAAQ,QAAQ,IAAK;GACvC,KAAK,KAAK,MAAM,QAAQ,MAAM,IAAK;GACnC,MAAM,QAAQ,KAAK,MAAM;GAC1B,EAAE;EAUgB,eARG,YAAY,SAAS,SAAS,YAClD,QAAQ,MAAM,KAAK,UAAU;GAC3B,MAAM,KAAK;GACX,OAAO,KAAK,MAAM,KAAK,QAAQ,IAAK;GACpC,KAAK,KAAK,MAAM,KAAK,MAAM,IAAK;GACjC,EAAE,CACJ;EAEiC;;AAGpC,MAAa,8BAA8B,OAAO,iBAAyB;CACzE,MAAM,OAAO;EAAC;EAAc;EAAM;EAAe;EAAmB;EAAQ;EAAa;AACzF,KAAI,+BAA+B,KAAK;CACxC,MAAM,EAAE,WAAW,MAAM,gBAAgB,uBAAuB,KAAK;AAErE,KAAI;EAEF,MAAM,cAAc,gCADA,KAAK,MAAM,OAAO,CAC0B;AAChE,SAAO,KAAK,UAAU,aAAa,MAAM,EAAE;UACpC,OAAO;AACd,MAAI,iCAAiC,QAAQ;AAC7C,QAAM,IAAI,MAAM,+CAA+C,QAAQ;;;AAI3E,MAAM,0BAA0B,eAAe;CAC7C,OAAO;CACP,WAAW,iBAAiB,GAAG,SAAS,aAAa,CAAC;CACtD,QAAQ;CACT,CAAC;AAEF,MAAa,uBAAuB,OAAO,WAAmB,iBAAyB;AACrF,KAAI;AACF,SAAO,MAAM,wBAAwB,WAAW,aAAa;UACtD,OAAO;AACd,UAAQ,MAAM,sCAAsC,MAAM;AAC1D,QAAM"}
1
+ {"version":3,"file":"findOrCreateCaptions.js","names":[],"sources":["../../src/tasks/findOrCreateCaptions.ts"],"mappings":";;;;;;AAQA,MAAM,kBAAkB,UAAU,SAAS;AAE3C,MAAM,MAAM,MAAM,sBAAsB;AAiCxC,MAAM,mCAAmC,gBAA8C;AAerF,QAAO;EAAE,UAdQ,YAAY,SAAS,KAAK,aAAa;GACtD,OAAO,KAAK,MAAM,QAAQ,QAAQ,IAAK;GACvC,KAAK,KAAK,MAAM,QAAQ,MAAM,IAAK;GACnC,MAAM,QAAQ,KAAK,MAAM;GAC1B,EAAE;EAUgB,eARG,YAAY,SAAS,SAAS,YAClD,QAAQ,MAAM,KAAK,UAAU;GAC3B,MAAM,KAAK;GACX,OAAO,KAAK,MAAM,KAAK,QAAQ,IAAK;GACpC,KAAK,KAAK,MAAM,KAAK,MAAM,IAAK;GACjC,EAAE,CACJ;EAEiC;;AAGpC,MAAa,8BAA8B,OAAO,iBAAyB;CACzE,MAAM,OAAO;EAAC;EAAc;EAAM;EAAe;EAAmB;EAAQ;EAAa;AACzF,KAAI,+BAA+B,KAAK;CACxC,MAAM,EAAE,WAAW,MAAM,gBAAgB,uBAAuB,KAAK;AAErE,KAAI;EAEF,MAAM,cAAc,gCADA,KAAK,MAAM,OAAO,CAC0B;AAChE,SAAO,KAAK,UAAU,aAAa,MAAM,EAAE;UACpC,OAAO;AACd,MAAI,iCAAiC,QAAQ;AAC7C,QAAM,IAAI,MAAM,+CAA+C,QAAQ;;;AAI3E,MAAM,0BAA0B,eAAe;CAC7C,OAAO;CACP,WAAW,iBAAiB,GAAG,SAAS,aAAa,CAAC;CACtD,QAAQ;CACT,CAAC;AAEF,MAAa,uBAAuB,OAAO,WAAmB,iBAAyB;AACrF,KAAI;AACF,SAAO,MAAM,wBAAwB,WAAW,aAAa;UACtD,OAAO;AACd,UAAQ,MAAM,sCAAsC,MAAM;AAC1D,QAAM"}
@@ -1,14 +1,11 @@
1
- const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
- const require_Probe = require('../Probe.cjs');
3
- const require_generateFragmentIndex = require('../generateFragmentIndex.cjs');
4
- const require_idempotentTask = require('../idempotentTask.cjs');
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_Probe = require("../Probe.cjs");
3
+ const require_generateFragmentIndex = require("../generateFragmentIndex.cjs");
4
+ const require_idempotentTask = require("../idempotentTask.cjs");
5
5
  let debug = require("debug");
6
- debug = require_rolldown_runtime.__toESM(debug);
6
+ debug = require_runtime.__toESM(debug);
7
7
  let node_stream = require("node:stream");
8
- node_stream = require_rolldown_runtime.__toESM(node_stream);
9
8
  let node_path = require("node:path");
10
- node_path = require_rolldown_runtime.__toESM(node_path);
11
-
12
9
  //#region src/tasks/generateScrubTrack.ts
13
10
  const log = (0, debug.default)("ef:generateScrubTrack");
14
11
  const generateScrubTrackFromPath = async (absolutePath) => {
@@ -90,8 +87,8 @@ const generateScrubTrack = async (cacheRoot, absolutePath) => {
90
87
  throw error;
91
88
  }
92
89
  };
93
-
94
90
  //#endregion
95
91
  exports.generateScrubTrack = generateScrubTrack;
96
92
  exports.generateScrubTrackFromPath = generateScrubTrackFromPath;
93
+
97
94
  //# sourceMappingURL=generateScrubTrack.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateScrubTrack.cjs","names":["Probe","PassThrough","generateFragmentIndex","idempotentTask","progressTimeout: NodeJS.Timeout | null"],"sources":["../../src/tasks/generateScrubTrack.ts"],"sourcesContent":["import { idempotentTask } from \"../idempotentTask.js\";\nimport debug from \"debug\";\nimport { basename } from \"node:path\";\nimport { PassThrough } from \"node:stream\";\nimport { Probe } from \"../Probe.js\";\nimport { generateFragmentIndex } from \"../generateFragmentIndex.js\";\n\nconst log = debug(\"ef:generateScrubTrack\");\n\nexport const generateScrubTrackFromPath = async (absolutePath: string) => {\n log(`Generating scrub track for ${absolutePath}`);\n\n const probe = await Probe.probePath(absolutePath);\n\n // Check if video stream exists\n if (probe.videoStreams.length === 0) {\n throw new Error(\"No video stream found for scrub track generation\");\n }\n\n // Get the scrub track stream from FFmpeg (low-res transcoded video)\n const scrubStream = probe.createScrubTrackReadstream();\n\n const startTimeOffsetMs = probe.startTimeOffsetMs;\n\n // Create a PassThrough to tee the stream\n const outputStream = new PassThrough();\n const indexStream = new PassThrough();\n\n // Pipe data but DON'T end outputStream automatically - we'll control this\n scrubStream.pipe(outputStream, { end: false });\n scrubStream.pipe(indexStream);\n\n // Track when the source stream ends (but don't end output yet)\n let sourceStreamEnded = false;\n scrubStream.on(\"end\", () => {\n sourceStreamEnded = true;\n });\n\n scrubStream.on(\"error\", (error) => {\n outputStream.destroy(error);\n indexStream.destroy(error);\n });\n\n // Generate fragment index from the scrub track stream\n // Use a special track ID to identify scrub track (e.g., -1 or \"scrub\")\n // We'll use a negative track ID to distinguish from regular tracks\n const scrubTrackId = -1;\n const trackIdMapping = { 1: scrubTrackId }; // Single track 1 -> scrub track ID\n\n const fragmentIndexPromise = generateFragmentIndex(\n indexStream,\n startTimeOffsetMs,\n trackIdMapping,\n );\n\n // End outputStream only after BOTH source ends AND fragment index completes\n fragmentIndexPromise\n .then(() => {\n if (sourceStreamEnded) {\n outputStream.end();\n } else {\n // If fragment index completes first, wait for stream to end\n scrubStream.once(\"end\", () => {\n outputStream.end();\n });\n }\n })\n .catch((error) => {\n outputStream.destroy(error);\n });\n\n // Return both the stream and the index\n return {\n stream: outputStream,\n fragmentIndex: fragmentIndexPromise,\n };\n};\n\nexport const generateScrubTrackTask = idempotentTask({\n label: \"scrub-track\",\n filename: (absolutePath: string) => `${basename(absolutePath)}.scrub-track.mp4`,\n runner: async (absolutePath: string) => {\n const probe = await Probe.probePath(absolutePath);\n\n if (probe.videoStreams.length === 0) {\n throw new Error(\"No video stream found for scrub track generation\");\n }\n\n // Get the scrub track stream from FFmpeg\n const scrubStream = probe.createScrubTrackReadstream();\n\n // Wrap in PassThrough with timeout handling to ensure stream completes\n const finalStream = new PassThrough();\n\n // Monitor progress and extend timeout based on actual work\n let progressTimeout: NodeJS.Timeout | null = null;\n\n const resetProgressTimeout = () => {\n if (progressTimeout) {\n clearTimeout(progressTimeout);\n }\n\n progressTimeout = setTimeout(() => {\n if (!finalStream.destroyed) {\n console.warn(`Progress timeout triggered for scrub track - no activity for 30 seconds`);\n finalStream.destroy(new Error(\"Scrub track generation timeout\"));\n }\n }, 30000); // 30 second sliding timeout (longer for transcoding)\n };\n\n // Start the initial timeout\n resetProgressTimeout();\n\n // Monitor data flow to detect active work\n scrubStream.on(\"data\", () => {\n resetProgressTimeout(); // Reset timeout when we see data\n });\n\n scrubStream.on(\"end\", () => {\n resetProgressTimeout(); // Reset timeout when stream ends\n finalStream.end();\n });\n\n scrubStream.on(\"error\", (error) => {\n if (progressTimeout) {\n clearTimeout(progressTimeout);\n }\n finalStream.destroy(error);\n });\n\n // Pipe data through\n scrubStream.pipe(finalStream, { end: false });\n\n // Clean up timeout when stream ends\n finalStream.on(\"end\", () => {\n if (progressTimeout) {\n clearTimeout(progressTimeout);\n }\n });\n\n return finalStream;\n },\n});\n\nexport const generateScrubTrack = async (cacheRoot: string, absolutePath: string) => {\n try {\n return await generateScrubTrackTask(cacheRoot, absolutePath);\n } catch (error) {\n console.error(error);\n console.trace(\"Error generating scrub track\", error);\n throw error;\n }\n};\n"],"mappings":";;;;;;;;;;;;AAOA,MAAM,yBAAY,wBAAwB;AAE1C,MAAa,6BAA6B,OAAO,iBAAyB;AACxE,KAAI,8BAA8B,eAAe;CAEjD,MAAM,QAAQ,MAAMA,oBAAM,UAAU,aAAa;AAGjD,KAAI,MAAM,aAAa,WAAW,EAChC,OAAM,IAAI,MAAM,mDAAmD;CAIrE,MAAM,cAAc,MAAM,4BAA4B;CAEtD,MAAM,oBAAoB,MAAM;CAGhC,MAAM,eAAe,IAAIC,yBAAa;CACtC,MAAM,cAAc,IAAIA,yBAAa;AAGrC,aAAY,KAAK,cAAc,EAAE,KAAK,OAAO,CAAC;AAC9C,aAAY,KAAK,YAAY;CAG7B,IAAI,oBAAoB;AACxB,aAAY,GAAG,aAAa;AAC1B,sBAAoB;GACpB;AAEF,aAAY,GAAG,UAAU,UAAU;AACjC,eAAa,QAAQ,MAAM;AAC3B,cAAY,QAAQ,MAAM;GAC1B;CAKF,MAAM,eAAe;CAGrB,MAAM,uBAAuBC,oDAC3B,aACA,mBAJqB,EAAE,GAAG,cAAc,CAMzC;AAGD,sBACG,WAAW;AACV,MAAI,kBACF,cAAa,KAAK;MAGlB,aAAY,KAAK,aAAa;AAC5B,gBAAa,KAAK;IAClB;GAEJ,CACD,OAAO,UAAU;AAChB,eAAa,QAAQ,MAAM;GAC3B;AAGJ,QAAO;EACL,QAAQ;EACR,eAAe;EAChB;;AAGH,MAAa,yBAAyBC,sCAAe;CACnD,OAAO;CACP,WAAW,iBAAyB,2BAAY,aAAa,CAAC;CAC9D,QAAQ,OAAO,iBAAyB;EACtC,MAAM,QAAQ,MAAMH,oBAAM,UAAU,aAAa;AAEjD,MAAI,MAAM,aAAa,WAAW,EAChC,OAAM,IAAI,MAAM,mDAAmD;EAIrE,MAAM,cAAc,MAAM,4BAA4B;EAGtD,MAAM,cAAc,IAAIC,yBAAa;EAGrC,IAAIG,kBAAyC;EAE7C,MAAM,6BAA6B;AACjC,OAAI,gBACF,cAAa,gBAAgB;AAG/B,qBAAkB,iBAAiB;AACjC,QAAI,CAAC,YAAY,WAAW;AAC1B,aAAQ,KAAK,0EAA0E;AACvF,iBAAY,wBAAQ,IAAI,MAAM,iCAAiC,CAAC;;MAEjE,IAAM;;AAIX,wBAAsB;AAGtB,cAAY,GAAG,cAAc;AAC3B,yBAAsB;IACtB;AAEF,cAAY,GAAG,aAAa;AAC1B,yBAAsB;AACtB,eAAY,KAAK;IACjB;AAEF,cAAY,GAAG,UAAU,UAAU;AACjC,OAAI,gBACF,cAAa,gBAAgB;AAE/B,eAAY,QAAQ,MAAM;IAC1B;AAGF,cAAY,KAAK,aAAa,EAAE,KAAK,OAAO,CAAC;AAG7C,cAAY,GAAG,aAAa;AAC1B,OAAI,gBACF,cAAa,gBAAgB;IAE/B;AAEF,SAAO;;CAEV,CAAC;AAEF,MAAa,qBAAqB,OAAO,WAAmB,iBAAyB;AACnF,KAAI;AACF,SAAO,MAAM,uBAAuB,WAAW,aAAa;UACrD,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,gCAAgC,MAAM;AACpD,QAAM"}
1
+ {"version":3,"file":"generateScrubTrack.cjs","names":["Probe","PassThrough","generateFragmentIndex","idempotentTask"],"sources":["../../src/tasks/generateScrubTrack.ts"],"mappings":";;;;;;;;;AAOA,MAAM,OAAA,GAAA,MAAA,SAAY,wBAAwB;AAE1C,MAAa,6BAA6B,OAAO,iBAAyB;AACxE,KAAI,8BAA8B,eAAe;CAEjD,MAAM,QAAQ,MAAMA,cAAAA,MAAM,UAAU,aAAa;AAGjD,KAAI,MAAM,aAAa,WAAW,EAChC,OAAM,IAAI,MAAM,mDAAmD;CAIrE,MAAM,cAAc,MAAM,4BAA4B;CAEtD,MAAM,oBAAoB,MAAM;CAGhC,MAAM,eAAe,IAAIC,YAAAA,aAAa;CACtC,MAAM,cAAc,IAAIA,YAAAA,aAAa;AAGrC,aAAY,KAAK,cAAc,EAAE,KAAK,OAAO,CAAC;AAC9C,aAAY,KAAK,YAAY;CAG7B,IAAI,oBAAoB;AACxB,aAAY,GAAG,aAAa;AAC1B,sBAAoB;GACpB;AAEF,aAAY,GAAG,UAAU,UAAU;AACjC,eAAa,QAAQ,MAAM;AAC3B,cAAY,QAAQ,MAAM;GAC1B;CAKF,MAAM,eAAe;CAGrB,MAAM,uBAAuBC,8BAAAA,sBAC3B,aACA,mBAJqB,EAAE,GAAG,cAAc,CAMzC;AAGD,sBACG,WAAW;AACV,MAAI,kBACF,cAAa,KAAK;MAGlB,aAAY,KAAK,aAAa;AAC5B,gBAAa,KAAK;IAClB;GAEJ,CACD,OAAO,UAAU;AAChB,eAAa,QAAQ,MAAM;GAC3B;AAGJ,QAAO;EACL,QAAQ;EACR,eAAe;EAChB;;AAGH,MAAa,yBAAyBC,uBAAAA,eAAe;CACnD,OAAO;CACP,WAAW,iBAAyB,IAAA,GAAA,UAAA,UAAY,aAAa,CAAC;CAC9D,QAAQ,OAAO,iBAAyB;EACtC,MAAM,QAAQ,MAAMH,cAAAA,MAAM,UAAU,aAAa;AAEjD,MAAI,MAAM,aAAa,WAAW,EAChC,OAAM,IAAI,MAAM,mDAAmD;EAIrE,MAAM,cAAc,MAAM,4BAA4B;EAGtD,MAAM,cAAc,IAAIC,YAAAA,aAAa;EAGrC,IAAI,kBAAyC;EAE7C,MAAM,6BAA6B;AACjC,OAAI,gBACF,cAAa,gBAAgB;AAG/B,qBAAkB,iBAAiB;AACjC,QAAI,CAAC,YAAY,WAAW;AAC1B,aAAQ,KAAK,0EAA0E;AACvF,iBAAY,wBAAQ,IAAI,MAAM,iCAAiC,CAAC;;MAEjE,IAAM;;AAIX,wBAAsB;AAGtB,cAAY,GAAG,cAAc;AAC3B,yBAAsB;IACtB;AAEF,cAAY,GAAG,aAAa;AAC1B,yBAAsB;AACtB,eAAY,KAAK;IACjB;AAEF,cAAY,GAAG,UAAU,UAAU;AACjC,OAAI,gBACF,cAAa,gBAAgB;AAE/B,eAAY,QAAQ,MAAM;IAC1B;AAGF,cAAY,KAAK,aAAa,EAAE,KAAK,OAAO,CAAC;AAG7C,cAAY,GAAG,aAAa;AAC1B,OAAI,gBACF,cAAa,gBAAgB;IAE/B;AAEF,SAAO;;CAEV,CAAC;AAEF,MAAa,qBAAqB,OAAO,WAAmB,iBAAyB;AACnF,KAAI;AACF,SAAO,MAAM,uBAAuB,WAAW,aAAa;UACrD,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,gCAAgC,MAAM;AACpD,QAAM"}
@@ -4,7 +4,6 @@ import { idempotentTask } from "../idempotentTask.js";
4
4
  import debug from "debug";
5
5
  import { PassThrough } from "node:stream";
6
6
  import { basename } from "node:path";
7
-
8
7
  //#region src/tasks/generateScrubTrack.ts
9
8
  const log = debug("ef:generateScrubTrack");
10
9
  const generateScrubTrackFromPath = async (absolutePath) => {
@@ -86,7 +85,7 @@ const generateScrubTrack = async (cacheRoot, absolutePath) => {
86
85
  throw error;
87
86
  }
88
87
  };
89
-
90
88
  //#endregion
91
89
  export { generateScrubTrack, generateScrubTrackFromPath };
90
+
92
91
  //# sourceMappingURL=generateScrubTrack.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateScrubTrack.js","names":["progressTimeout: NodeJS.Timeout | null"],"sources":["../../src/tasks/generateScrubTrack.ts"],"sourcesContent":["import { idempotentTask } from \"../idempotentTask.js\";\nimport debug from \"debug\";\nimport { basename } from \"node:path\";\nimport { PassThrough } from \"node:stream\";\nimport { Probe } from \"../Probe.js\";\nimport { generateFragmentIndex } from \"../generateFragmentIndex.js\";\n\nconst log = debug(\"ef:generateScrubTrack\");\n\nexport const generateScrubTrackFromPath = async (absolutePath: string) => {\n log(`Generating scrub track for ${absolutePath}`);\n\n const probe = await Probe.probePath(absolutePath);\n\n // Check if video stream exists\n if (probe.videoStreams.length === 0) {\n throw new Error(\"No video stream found for scrub track generation\");\n }\n\n // Get the scrub track stream from FFmpeg (low-res transcoded video)\n const scrubStream = probe.createScrubTrackReadstream();\n\n const startTimeOffsetMs = probe.startTimeOffsetMs;\n\n // Create a PassThrough to tee the stream\n const outputStream = new PassThrough();\n const indexStream = new PassThrough();\n\n // Pipe data but DON'T end outputStream automatically - we'll control this\n scrubStream.pipe(outputStream, { end: false });\n scrubStream.pipe(indexStream);\n\n // Track when the source stream ends (but don't end output yet)\n let sourceStreamEnded = false;\n scrubStream.on(\"end\", () => {\n sourceStreamEnded = true;\n });\n\n scrubStream.on(\"error\", (error) => {\n outputStream.destroy(error);\n indexStream.destroy(error);\n });\n\n // Generate fragment index from the scrub track stream\n // Use a special track ID to identify scrub track (e.g., -1 or \"scrub\")\n // We'll use a negative track ID to distinguish from regular tracks\n const scrubTrackId = -1;\n const trackIdMapping = { 1: scrubTrackId }; // Single track 1 -> scrub track ID\n\n const fragmentIndexPromise = generateFragmentIndex(\n indexStream,\n startTimeOffsetMs,\n trackIdMapping,\n );\n\n // End outputStream only after BOTH source ends AND fragment index completes\n fragmentIndexPromise\n .then(() => {\n if (sourceStreamEnded) {\n outputStream.end();\n } else {\n // If fragment index completes first, wait for stream to end\n scrubStream.once(\"end\", () => {\n outputStream.end();\n });\n }\n })\n .catch((error) => {\n outputStream.destroy(error);\n });\n\n // Return both the stream and the index\n return {\n stream: outputStream,\n fragmentIndex: fragmentIndexPromise,\n };\n};\n\nexport const generateScrubTrackTask = idempotentTask({\n label: \"scrub-track\",\n filename: (absolutePath: string) => `${basename(absolutePath)}.scrub-track.mp4`,\n runner: async (absolutePath: string) => {\n const probe = await Probe.probePath(absolutePath);\n\n if (probe.videoStreams.length === 0) {\n throw new Error(\"No video stream found for scrub track generation\");\n }\n\n // Get the scrub track stream from FFmpeg\n const scrubStream = probe.createScrubTrackReadstream();\n\n // Wrap in PassThrough with timeout handling to ensure stream completes\n const finalStream = new PassThrough();\n\n // Monitor progress and extend timeout based on actual work\n let progressTimeout: NodeJS.Timeout | null = null;\n\n const resetProgressTimeout = () => {\n if (progressTimeout) {\n clearTimeout(progressTimeout);\n }\n\n progressTimeout = setTimeout(() => {\n if (!finalStream.destroyed) {\n console.warn(`Progress timeout triggered for scrub track - no activity for 30 seconds`);\n finalStream.destroy(new Error(\"Scrub track generation timeout\"));\n }\n }, 30000); // 30 second sliding timeout (longer for transcoding)\n };\n\n // Start the initial timeout\n resetProgressTimeout();\n\n // Monitor data flow to detect active work\n scrubStream.on(\"data\", () => {\n resetProgressTimeout(); // Reset timeout when we see data\n });\n\n scrubStream.on(\"end\", () => {\n resetProgressTimeout(); // Reset timeout when stream ends\n finalStream.end();\n });\n\n scrubStream.on(\"error\", (error) => {\n if (progressTimeout) {\n clearTimeout(progressTimeout);\n }\n finalStream.destroy(error);\n });\n\n // Pipe data through\n scrubStream.pipe(finalStream, { end: false });\n\n // Clean up timeout when stream ends\n finalStream.on(\"end\", () => {\n if (progressTimeout) {\n clearTimeout(progressTimeout);\n }\n });\n\n return finalStream;\n },\n});\n\nexport const generateScrubTrack = async (cacheRoot: string, absolutePath: string) => {\n try {\n return await generateScrubTrackTask(cacheRoot, absolutePath);\n } catch (error) {\n console.error(error);\n console.trace(\"Error generating scrub track\", error);\n throw error;\n }\n};\n"],"mappings":";;;;;;;;AAOA,MAAM,MAAM,MAAM,wBAAwB;AAE1C,MAAa,6BAA6B,OAAO,iBAAyB;AACxE,KAAI,8BAA8B,eAAe;CAEjD,MAAM,QAAQ,MAAM,MAAM,UAAU,aAAa;AAGjD,KAAI,MAAM,aAAa,WAAW,EAChC,OAAM,IAAI,MAAM,mDAAmD;CAIrE,MAAM,cAAc,MAAM,4BAA4B;CAEtD,MAAM,oBAAoB,MAAM;CAGhC,MAAM,eAAe,IAAI,aAAa;CACtC,MAAM,cAAc,IAAI,aAAa;AAGrC,aAAY,KAAK,cAAc,EAAE,KAAK,OAAO,CAAC;AAC9C,aAAY,KAAK,YAAY;CAG7B,IAAI,oBAAoB;AACxB,aAAY,GAAG,aAAa;AAC1B,sBAAoB;GACpB;AAEF,aAAY,GAAG,UAAU,UAAU;AACjC,eAAa,QAAQ,MAAM;AAC3B,cAAY,QAAQ,MAAM;GAC1B;CAKF,MAAM,eAAe;CAGrB,MAAM,uBAAuB,sBAC3B,aACA,mBAJqB,EAAE,GAAG,cAAc,CAMzC;AAGD,sBACG,WAAW;AACV,MAAI,kBACF,cAAa,KAAK;MAGlB,aAAY,KAAK,aAAa;AAC5B,gBAAa,KAAK;IAClB;GAEJ,CACD,OAAO,UAAU;AAChB,eAAa,QAAQ,MAAM;GAC3B;AAGJ,QAAO;EACL,QAAQ;EACR,eAAe;EAChB;;AAGH,MAAa,yBAAyB,eAAe;CACnD,OAAO;CACP,WAAW,iBAAyB,GAAG,SAAS,aAAa,CAAC;CAC9D,QAAQ,OAAO,iBAAyB;EACtC,MAAM,QAAQ,MAAM,MAAM,UAAU,aAAa;AAEjD,MAAI,MAAM,aAAa,WAAW,EAChC,OAAM,IAAI,MAAM,mDAAmD;EAIrE,MAAM,cAAc,MAAM,4BAA4B;EAGtD,MAAM,cAAc,IAAI,aAAa;EAGrC,IAAIA,kBAAyC;EAE7C,MAAM,6BAA6B;AACjC,OAAI,gBACF,cAAa,gBAAgB;AAG/B,qBAAkB,iBAAiB;AACjC,QAAI,CAAC,YAAY,WAAW;AAC1B,aAAQ,KAAK,0EAA0E;AACvF,iBAAY,wBAAQ,IAAI,MAAM,iCAAiC,CAAC;;MAEjE,IAAM;;AAIX,wBAAsB;AAGtB,cAAY,GAAG,cAAc;AAC3B,yBAAsB;IACtB;AAEF,cAAY,GAAG,aAAa;AAC1B,yBAAsB;AACtB,eAAY,KAAK;IACjB;AAEF,cAAY,GAAG,UAAU,UAAU;AACjC,OAAI,gBACF,cAAa,gBAAgB;AAE/B,eAAY,QAAQ,MAAM;IAC1B;AAGF,cAAY,KAAK,aAAa,EAAE,KAAK,OAAO,CAAC;AAG7C,cAAY,GAAG,aAAa;AAC1B,OAAI,gBACF,cAAa,gBAAgB;IAE/B;AAEF,SAAO;;CAEV,CAAC;AAEF,MAAa,qBAAqB,OAAO,WAAmB,iBAAyB;AACnF,KAAI;AACF,SAAO,MAAM,uBAAuB,WAAW,aAAa;UACrD,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,gCAAgC,MAAM;AACpD,QAAM"}
1
+ {"version":3,"file":"generateScrubTrack.js","names":[],"sources":["../../src/tasks/generateScrubTrack.ts"],"mappings":";;;;;;;AAOA,MAAM,MAAM,MAAM,wBAAwB;AAE1C,MAAa,6BAA6B,OAAO,iBAAyB;AACxE,KAAI,8BAA8B,eAAe;CAEjD,MAAM,QAAQ,MAAM,MAAM,UAAU,aAAa;AAGjD,KAAI,MAAM,aAAa,WAAW,EAChC,OAAM,IAAI,MAAM,mDAAmD;CAIrE,MAAM,cAAc,MAAM,4BAA4B;CAEtD,MAAM,oBAAoB,MAAM;CAGhC,MAAM,eAAe,IAAI,aAAa;CACtC,MAAM,cAAc,IAAI,aAAa;AAGrC,aAAY,KAAK,cAAc,EAAE,KAAK,OAAO,CAAC;AAC9C,aAAY,KAAK,YAAY;CAG7B,IAAI,oBAAoB;AACxB,aAAY,GAAG,aAAa;AAC1B,sBAAoB;GACpB;AAEF,aAAY,GAAG,UAAU,UAAU;AACjC,eAAa,QAAQ,MAAM;AAC3B,cAAY,QAAQ,MAAM;GAC1B;CAKF,MAAM,eAAe;CAGrB,MAAM,uBAAuB,sBAC3B,aACA,mBAJqB,EAAE,GAAG,cAAc,CAMzC;AAGD,sBACG,WAAW;AACV,MAAI,kBACF,cAAa,KAAK;MAGlB,aAAY,KAAK,aAAa;AAC5B,gBAAa,KAAK;IAClB;GAEJ,CACD,OAAO,UAAU;AAChB,eAAa,QAAQ,MAAM;GAC3B;AAGJ,QAAO;EACL,QAAQ;EACR,eAAe;EAChB;;AAGH,MAAa,yBAAyB,eAAe;CACnD,OAAO;CACP,WAAW,iBAAyB,GAAG,SAAS,aAAa,CAAC;CAC9D,QAAQ,OAAO,iBAAyB;EACtC,MAAM,QAAQ,MAAM,MAAM,UAAU,aAAa;AAEjD,MAAI,MAAM,aAAa,WAAW,EAChC,OAAM,IAAI,MAAM,mDAAmD;EAIrE,MAAM,cAAc,MAAM,4BAA4B;EAGtD,MAAM,cAAc,IAAI,aAAa;EAGrC,IAAI,kBAAyC;EAE7C,MAAM,6BAA6B;AACjC,OAAI,gBACF,cAAa,gBAAgB;AAG/B,qBAAkB,iBAAiB;AACjC,QAAI,CAAC,YAAY,WAAW;AAC1B,aAAQ,KAAK,0EAA0E;AACvF,iBAAY,wBAAQ,IAAI,MAAM,iCAAiC,CAAC;;MAEjE,IAAM;;AAIX,wBAAsB;AAGtB,cAAY,GAAG,cAAc;AAC3B,yBAAsB;IACtB;AAEF,cAAY,GAAG,aAAa;AAC1B,yBAAsB;AACtB,eAAY,KAAK;IACjB;AAEF,cAAY,GAAG,UAAU,UAAU;AACjC,OAAI,gBACF,cAAa,gBAAgB;AAE/B,eAAY,QAAQ,MAAM;IAC1B;AAGF,cAAY,KAAK,aAAa,EAAE,KAAK,OAAO,CAAC;AAG7C,cAAY,GAAG,aAAa;AAC1B,OAAI,gBACF,cAAa,gBAAgB;IAE/B;AAEF,SAAO;;CAEV,CAAC;AAEF,MAAa,qBAAqB,OAAO,WAAmB,iBAAyB;AACnF,KAAI;AACF,SAAO,MAAM,uBAAuB,WAAW,aAAa;UACrD,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,gCAAgC,MAAM;AACpD,QAAM"}
@@ -1,17 +1,13 @@
1
- const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
- const require_Probe = require('../Probe.cjs');
3
- const require_idempotentTask = require('../idempotentTask.cjs');
4
- const require_generateWebmSegmentIndex = require('../generateWebmSegmentIndex.cjs');
5
- const require_generateSingleTrack = require('../generateSingleTrack.cjs');
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_Probe = require("../Probe.cjs");
3
+ const require_idempotentTask = require("../idempotentTask.cjs");
4
+ const require_generateWebmSegmentIndex = require("../generateWebmSegmentIndex.cjs");
5
+ const require_generateSingleTrack = require("../generateSingleTrack.cjs");
6
6
  let debug = require("debug");
7
- debug = require_rolldown_runtime.__toESM(debug);
7
+ debug = require_runtime.__toESM(debug);
8
8
  let node_stream = require("node:stream");
9
- node_stream = require_rolldown_runtime.__toESM(node_stream);
10
9
  let node_fs_promises = require("node:fs/promises");
11
- node_fs_promises = require_rolldown_runtime.__toESM(node_fs_promises);
12
10
  let node_path = require("node:path");
13
- node_path = require_rolldown_runtime.__toESM(node_path);
14
-
15
11
  //#region src/tasks/generateTrack.ts
16
12
  const generateTrackFromPath = async (absolutePath, trackId) => {
17
13
  const log = (0, debug.default)("ef:generateTrackFragment");
@@ -43,8 +39,8 @@ const generateTrack = async (cacheRoot, absolutePath, url) => {
43
39
  throw error;
44
40
  }
45
41
  };
46
-
47
42
  //#endregion
48
43
  exports.generateTrack = generateTrack;
49
44
  exports.generateTrackFromPath = generateTrackFromPath;
45
+
50
46
  //# sourceMappingURL=generateTrack.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateTrack.cjs","names":["Probe","Readable","generateSingleTrackFromPath","idempotentTask"],"sources":["../../src/tasks/generateTrack.ts"],"sourcesContent":["import { idempotentTask } from \"../idempotentTask.js\";\nimport debug from \"debug\";\nimport { basename } from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { readFile } from \"node:fs/promises\";\nimport { Probe } from \"../Probe.js\";\nimport { generateSingleTrackFromPath } from \"../generateSingleTrack.js\";\nimport { patchWebmForSegmentedServing } from \"../generateWebmSegmentIndex.js\";\n\nexport const generateTrackFromPath = async (absolutePath: string, trackId: number) => {\n const log = debug(\"ef:generateTrackFragment\");\n log(`Generating track ${trackId} for ${absolutePath}`);\n\n const probe = await Probe.probePath(absolutePath);\n\n // For VP9-alpha WebM sources: no transcoding needed.\n // Copy the source to cache with two in-place patches so mediabunny can\n // parse partial (segment-sliced) chunks without expecting the full file:\n // 1. Segment-element size → EBML unknown-size (0x01FFFFFFFFFFFFFF)\n // 2. SeekHead → Void element of equal size (prevents stale seeks to\n // positions that don't exist in the sliced chunk, which was causing\n // de-sync in Scene A).\n // Alpha BlockAdditions travel untouched in every cluster.\n if (probe.hasAlphaVideo) {\n log(`VP9 alpha WebM: copying source with Segment size + SeekHead patched`);\n const buf = await readFile(absolutePath);\n patchWebmForSegmentedServing(buf);\n return Readable.from(buf);\n }\n\n const result = await generateSingleTrackFromPath(absolutePath, trackId);\n return result.stream;\n};\n\nexport const generateTrackTask = idempotentTask({\n label: \"track\",\n filename: (absolutePath: string, _trackId: number) => {\n // VP9-alpha WebM sources are cached as .webm; everything else is .mp4.\n const ext = absolutePath.endsWith(\".webm\") ? \"webm\" : \"mp4\";\n return `${basename(absolutePath)}.track-1.${ext}`;\n },\n runner: generateTrackFromPath,\n});\n\nexport const generateTrack = async (cacheRoot: string, absolutePath: string, url: string) => {\n try {\n const trackId = new URL(`http://localhost${url}`).searchParams.get(\"trackId\");\n if (trackId === null) {\n throw new Error(\n \"No trackId provided. It must be specified in the query string: ?trackId=1 (for video) or ?trackId=2 (for audio)\",\n );\n }\n return await generateTrackTask(cacheRoot, absolutePath, Number(trackId));\n } catch (error) {\n console.error(error);\n console.trace(\"Error generating track\", error);\n throw error;\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;AASA,MAAa,wBAAwB,OAAO,cAAsB,YAAoB;CACpF,MAAM,yBAAY,2BAA2B;AAC7C,KAAI,oBAAoB,QAAQ,OAAO,eAAe;AAYtD,MAVc,MAAMA,oBAAM,UAAU,aAAa,EAUvC,eAAe;AACvB,MAAI,sEAAsE;EAC1E,MAAM,MAAM,qCAAe,aAAa;AACxC,gEAA6B,IAAI;AACjC,SAAOC,qBAAS,KAAK,IAAI;;AAI3B,SADe,MAAMC,wDAA4B,cAAc,QAAQ,EACzD;;AAGhB,MAAa,oBAAoBC,sCAAe;CAC9C,OAAO;CACP,WAAW,cAAsB,aAAqB;EAEpD,MAAM,MAAM,aAAa,SAAS,QAAQ,GAAG,SAAS;AACtD,SAAO,2BAAY,aAAa,CAAC,WAAW;;CAE9C,QAAQ;CACT,CAAC;AAEF,MAAa,gBAAgB,OAAO,WAAmB,cAAsB,QAAgB;AAC3F,KAAI;EACF,MAAM,UAAU,IAAI,IAAI,mBAAmB,MAAM,CAAC,aAAa,IAAI,UAAU;AAC7E,MAAI,YAAY,KACd,OAAM,IAAI,MACR,kHACD;AAEH,SAAO,MAAM,kBAAkB,WAAW,cAAc,OAAO,QAAQ,CAAC;UACjE,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,0BAA0B,MAAM;AAC9C,QAAM"}
1
+ {"version":3,"file":"generateTrack.cjs","names":["Probe","Readable","generateSingleTrackFromPath","idempotentTask"],"sources":["../../src/tasks/generateTrack.ts"],"mappings":";;;;;;;;;;;AASA,MAAa,wBAAwB,OAAO,cAAsB,YAAoB;CACpF,MAAM,OAAA,GAAA,MAAA,SAAY,2BAA2B;AAC7C,KAAI,oBAAoB,QAAQ,OAAO,eAAe;AAYtD,MAVc,MAAMA,cAAAA,MAAM,UAAU,aAAa,EAUvC,eAAe;AACvB,MAAI,sEAAsE;EAC1E,MAAM,MAAM,OAAA,GAAA,iBAAA,UAAe,aAAa;AACxC,mCAAA,6BAA6B,IAAI;AACjC,SAAOC,YAAAA,SAAS,KAAK,IAAI;;AAI3B,SADe,MAAMC,4BAAAA,4BAA4B,cAAc,QAAQ,EACzD;;AAGhB,MAAa,oBAAoBC,uBAAAA,eAAe;CAC9C,OAAO;CACP,WAAW,cAAsB,aAAqB;EAEpD,MAAM,MAAM,aAAa,SAAS,QAAQ,GAAG,SAAS;AACtD,SAAO,IAAA,GAAA,UAAA,UAAY,aAAa,CAAC,WAAW;;CAE9C,QAAQ;CACT,CAAC;AAEF,MAAa,gBAAgB,OAAO,WAAmB,cAAsB,QAAgB;AAC3F,KAAI;EACF,MAAM,UAAU,IAAI,IAAI,mBAAmB,MAAM,CAAC,aAAa,IAAI,UAAU;AAC7E,MAAI,YAAY,KACd,OAAM,IAAI,MACR,kHACD;AAEH,SAAO,MAAM,kBAAkB,WAAW,cAAc,OAAO,QAAQ,CAAC;UACjE,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,0BAA0B,MAAM;AAC9C,QAAM"}
@@ -6,7 +6,6 @@ import debug from "debug";
6
6
  import { Readable } from "node:stream";
7
7
  import { readFile } from "node:fs/promises";
8
8
  import { basename } from "node:path";
9
-
10
9
  //#region src/tasks/generateTrack.ts
11
10
  const generateTrackFromPath = async (absolutePath, trackId) => {
12
11
  const log = debug("ef:generateTrackFragment");
@@ -38,7 +37,7 @@ const generateTrack = async (cacheRoot, absolutePath, url) => {
38
37
  throw error;
39
38
  }
40
39
  };
41
-
42
40
  //#endregion
43
41
  export { generateTrack, generateTrackFromPath };
42
+
44
43
  //# sourceMappingURL=generateTrack.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateTrack.js","names":[],"sources":["../../src/tasks/generateTrack.ts"],"sourcesContent":["import { idempotentTask } from \"../idempotentTask.js\";\nimport debug from \"debug\";\nimport { basename } from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { readFile } from \"node:fs/promises\";\nimport { Probe } from \"../Probe.js\";\nimport { generateSingleTrackFromPath } from \"../generateSingleTrack.js\";\nimport { patchWebmForSegmentedServing } from \"../generateWebmSegmentIndex.js\";\n\nexport const generateTrackFromPath = async (absolutePath: string, trackId: number) => {\n const log = debug(\"ef:generateTrackFragment\");\n log(`Generating track ${trackId} for ${absolutePath}`);\n\n const probe = await Probe.probePath(absolutePath);\n\n // For VP9-alpha WebM sources: no transcoding needed.\n // Copy the source to cache with two in-place patches so mediabunny can\n // parse partial (segment-sliced) chunks without expecting the full file:\n // 1. Segment-element size → EBML unknown-size (0x01FFFFFFFFFFFFFF)\n // 2. SeekHead → Void element of equal size (prevents stale seeks to\n // positions that don't exist in the sliced chunk, which was causing\n // de-sync in Scene A).\n // Alpha BlockAdditions travel untouched in every cluster.\n if (probe.hasAlphaVideo) {\n log(`VP9 alpha WebM: copying source with Segment size + SeekHead patched`);\n const buf = await readFile(absolutePath);\n patchWebmForSegmentedServing(buf);\n return Readable.from(buf);\n }\n\n const result = await generateSingleTrackFromPath(absolutePath, trackId);\n return result.stream;\n};\n\nexport const generateTrackTask = idempotentTask({\n label: \"track\",\n filename: (absolutePath: string, _trackId: number) => {\n // VP9-alpha WebM sources are cached as .webm; everything else is .mp4.\n const ext = absolutePath.endsWith(\".webm\") ? \"webm\" : \"mp4\";\n return `${basename(absolutePath)}.track-1.${ext}`;\n },\n runner: generateTrackFromPath,\n});\n\nexport const generateTrack = async (cacheRoot: string, absolutePath: string, url: string) => {\n try {\n const trackId = new URL(`http://localhost${url}`).searchParams.get(\"trackId\");\n if (trackId === null) {\n throw new Error(\n \"No trackId provided. It must be specified in the query string: ?trackId=1 (for video) or ?trackId=2 (for audio)\",\n );\n }\n return await generateTrackTask(cacheRoot, absolutePath, Number(trackId));\n } catch (error) {\n console.error(error);\n console.trace(\"Error generating track\", error);\n throw error;\n }\n};\n"],"mappings":";;;;;;;;;;AASA,MAAa,wBAAwB,OAAO,cAAsB,YAAoB;CACpF,MAAM,MAAM,MAAM,2BAA2B;AAC7C,KAAI,oBAAoB,QAAQ,OAAO,eAAe;AAYtD,MAVc,MAAM,MAAM,UAAU,aAAa,EAUvC,eAAe;AACvB,MAAI,sEAAsE;EAC1E,MAAM,MAAM,MAAM,SAAS,aAAa;AACxC,+BAA6B,IAAI;AACjC,SAAO,SAAS,KAAK,IAAI;;AAI3B,SADe,MAAM,4BAA4B,cAAc,QAAQ,EACzD;;AAGhB,MAAa,oBAAoB,eAAe;CAC9C,OAAO;CACP,WAAW,cAAsB,aAAqB;EAEpD,MAAM,MAAM,aAAa,SAAS,QAAQ,GAAG,SAAS;AACtD,SAAO,GAAG,SAAS,aAAa,CAAC,WAAW;;CAE9C,QAAQ;CACT,CAAC;AAEF,MAAa,gBAAgB,OAAO,WAAmB,cAAsB,QAAgB;AAC3F,KAAI;EACF,MAAM,UAAU,IAAI,IAAI,mBAAmB,MAAM,CAAC,aAAa,IAAI,UAAU;AAC7E,MAAI,YAAY,KACd,OAAM,IAAI,MACR,kHACD;AAEH,SAAO,MAAM,kBAAkB,WAAW,cAAc,OAAO,QAAQ,CAAC;UACjE,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,0BAA0B,MAAM;AAC9C,QAAM"}
1
+ {"version":3,"file":"generateTrack.js","names":[],"sources":["../../src/tasks/generateTrack.ts"],"mappings":";;;;;;;;;AASA,MAAa,wBAAwB,OAAO,cAAsB,YAAoB;CACpF,MAAM,MAAM,MAAM,2BAA2B;AAC7C,KAAI,oBAAoB,QAAQ,OAAO,eAAe;AAYtD,MAVc,MAAM,MAAM,UAAU,aAAa,EAUvC,eAAe;AACvB,MAAI,sEAAsE;EAC1E,MAAM,MAAM,MAAM,SAAS,aAAa;AACxC,+BAA6B,IAAI;AACjC,SAAO,SAAS,KAAK,IAAI;;AAI3B,SADe,MAAM,4BAA4B,cAAc,QAAQ,EACzD;;AAGhB,MAAa,oBAAoB,eAAe;CAC9C,OAAO;CACP,WAAW,cAAsB,aAAqB;EAEpD,MAAM,MAAM,aAAa,SAAS,QAAQ,GAAG,SAAS;AACtD,SAAO,GAAG,SAAS,aAAa,CAAC,WAAW;;CAE9C,QAAQ;CACT,CAAC;AAEF,MAAa,gBAAgB,OAAO,WAAmB,cAAsB,QAAgB;AAC3F,KAAI;EACF,MAAM,UAAU,IAAI,IAAI,mBAAmB,MAAM,CAAC,aAAa,IAAI,UAAU;AAC7E,MAAI,YAAY,KACd,OAAM,IAAI,MACR,kHACD;AAEH,SAAO,MAAM,kBAAkB,WAAW,cAAc,OAAO,QAAQ,CAAC;UACjE,OAAO;AACd,UAAQ,MAAM,MAAM;AACpB,UAAQ,MAAM,0BAA0B,MAAM;AAC9C,QAAM"}
@@ -1,13 +1,11 @@
1
- const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
- const require_Probe = require('../Probe.cjs');
3
- const require_generateFragmentIndex = require('../generateFragmentIndex.cjs');
4
- const require_idempotentTask = require('../idempotentTask.cjs');
5
- const require_generateWebmSegmentIndex = require('../generateWebmSegmentIndex.cjs');
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_Probe = require("../Probe.cjs");
3
+ const require_generateFragmentIndex = require("../generateFragmentIndex.cjs");
4
+ const require_idempotentTask = require("../idempotentTask.cjs");
5
+ const require_generateWebmSegmentIndex = require("../generateWebmSegmentIndex.cjs");
6
6
  let debug = require("debug");
7
- debug = require_rolldown_runtime.__toESM(debug);
7
+ debug = require_runtime.__toESM(debug);
8
8
  let node_path = require("node:path");
9
- node_path = require_rolldown_runtime.__toESM(node_path);
10
-
11
9
  //#region src/tasks/generateTrackFragmentIndex.ts
12
10
  const generateTrackFragmentIndexFromPath = async (absolutePath) => {
13
11
  const log = (0, debug.default)("ef:generateTrackFragment");
@@ -18,7 +16,7 @@ const generateTrackFragmentIndexFromPath = async (absolutePath) => {
18
16
  if (probe.hasAlphaVideo) {
19
17
  log(`VP9 alpha WebM: using EBML cluster index (no transcoding)`);
20
18
  const webmIndex = await require_generateWebmSegmentIndex.generateWebmSegmentIndex(absolutePath, startTimeOffsetMs);
21
- const scrubResult$1 = await (async () => {
19
+ const scrubResult = await (async () => {
22
20
  try {
23
21
  log("Generating scrub track fragment index for alpha WebM");
24
22
  const result = await require_generateFragmentIndex.generateFragmentIndex(probe.createScrubTrackReadstream(), startTimeOffsetMs, { 0: -1 });
@@ -29,9 +27,9 @@ const generateTrackFragmentIndexFromPath = async (absolutePath) => {
29
27
  return null;
30
28
  }
31
29
  })();
32
- const trackFragmentIndexes$1 = { ...webmIndex };
33
- if (scrubResult$1) Object.assign(trackFragmentIndexes$1, scrubResult$1);
34
- return trackFragmentIndexes$1;
30
+ const trackFragmentIndexes = { ...webmIndex };
31
+ if (scrubResult) Object.assign(trackFragmentIndexes, scrubResult);
32
+ return trackFragmentIndexes;
35
33
  }
36
34
  log(`Generating track fragment index for ${absolutePath} using single-track approach`);
37
35
  const trackTasks = probe.streams.map((stream, streamIndex) => {
@@ -73,8 +71,8 @@ const generateTrackFragmentIndex = async (cacheRoot, absolutePath) => {
73
71
  throw error;
74
72
  }
75
73
  };
76
-
77
74
  //#endregion
78
75
  exports.generateTrackFragmentIndex = generateTrackFragmentIndex;
79
76
  exports.generateTrackFragmentIndexFromPath = generateTrackFragmentIndexFromPath;
77
+
80
78
  //# sourceMappingURL=generateTrackFragmentIndex.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateTrackFragmentIndex.cjs","names":["Probe","generateWebmSegmentIndex","scrubResult","generateFragmentIndex","trackFragmentIndexes: Record<number, TrackFragmentIndex>","trackFragmentIndexes","scrubTask: Promise<Record<number, TrackFragmentIndex> | null>","idempotentTask"],"sources":["../../src/tasks/generateTrackFragmentIndex.ts"],"sourcesContent":["import { idempotentTask } from \"../idempotentTask.js\";\nimport debug from \"debug\";\nimport { basename } from \"node:path\";\nimport { Probe } from \"../Probe.js\";\nimport { generateFragmentIndex } from \"../generateFragmentIndex.js\";\nimport { generateWebmSegmentIndex } from \"../generateWebmSegmentIndex.js\";\nimport type { TrackFragmentIndex } from \"../Probe.js\";\n\nexport const generateTrackFragmentIndexFromPath = async (absolutePath: string) => {\n const log = debug(\"ef:generateTrackFragment\");\n const probe = await Probe.probePath(absolutePath);\n\n const startTimeOffsetMs = probe.startTimeOffsetMs;\n if (startTimeOffsetMs !== undefined) {\n log(`Extracted start_time offset: ${startTimeOffsetMs}ms`);\n } else {\n log(\"No format/stream timing offset found - will detect from composition time\");\n }\n\n // ── VP9-alpha WebM fast path ─────────────────────────────────────────────\n // For VP9-alpha WebM sources we skip all transcoding and instead build a\n // byte-range index directly from the source file's EBML cluster structure.\n // Alpha BlockAdditions are preserved in every cluster — no H264 matte needed.\n if (probe.hasAlphaVideo) {\n log(`VP9 alpha WebM: using EBML cluster index (no transcoding)`);\n const webmIndex = await generateWebmSegmentIndex(absolutePath, startTimeOffsetMs);\n\n // Scrub track still needs transcoding (low-res H264 thumbnails)\n const scrubTask: Promise<Record<number, TrackFragmentIndex> | null> = (async () => {\n try {\n log(\"Generating scrub track fragment index for alpha WebM\");\n const scrubStream = probe.createScrubTrackReadstream();\n const result = await generateFragmentIndex(scrubStream, startTimeOffsetMs, { 0: -1 });\n log(\"Scrub track fragment index generated successfully\");\n return result;\n } catch (error) {\n log(`Failed to generate scrub track fragment index: ${error}`);\n return null;\n }\n })();\n\n const scrubResult = await scrubTask;\n const trackFragmentIndexes: Record<number, TrackFragmentIndex> = { ...webmIndex };\n if (scrubResult) Object.assign(trackFragmentIndexes, scrubResult);\n return trackFragmentIndexes;\n }\n\n // ── Standard MP4 path ────────────────────────────────────────────────────\n log(`Generating track fragment index for ${absolutePath} using single-track approach`);\n\n const trackTasks = probe.streams\n .map((stream, streamIndex) => {\n if (stream.codec_type !== \"audio\" && stream.codec_type !== \"video\") {\n return null;\n }\n const trackId = streamIndex + 1;\n log(`Processing track ${trackId} (${stream.codec_type})`);\n const trackStream = probe.createTrackReadstream(streamIndex);\n const trackIdMapping = { 0: trackId };\n return generateFragmentIndex(trackStream, startTimeOffsetMs, trackIdMapping);\n })\n .filter((task): task is Promise<Record<number, TrackFragmentIndex>> => task !== null);\n\n const scrubTask: Promise<Record<number, TrackFragmentIndex> | null> =\n probe.videoStreams.length > 0\n ? (async () => {\n try {\n log(\"Generating scrub track fragment index\");\n const scrubStream = probe.createScrubTrackReadstream();\n const result = await generateFragmentIndex(scrubStream, startTimeOffsetMs, { 0: -1 });\n log(\"Scrub track fragment index generated successfully\");\n return result;\n } catch (error) {\n log(`Failed to generate scrub track fragment index: ${error}`);\n return null;\n }\n })()\n : Promise.resolve(null);\n\n const [trackResults, scrubResult] = await Promise.all([Promise.all(trackTasks), scrubTask]);\n\n const trackFragmentIndexes: Record<number, TrackFragmentIndex> = {};\n for (const result of trackResults) {\n Object.assign(trackFragmentIndexes, result);\n }\n if (scrubResult) {\n Object.assign(trackFragmentIndexes, scrubResult);\n }\n\n return trackFragmentIndexes;\n};\n\nconst generateTrackFragmentIndexTask = idempotentTask({\n label: \"trackFragmentIndex\",\n filename: (absolutePath) => `${basename(absolutePath)}.tracks.json`,\n runner: async (absolutePath: string) => {\n const index = await generateTrackFragmentIndexFromPath(absolutePath);\n return JSON.stringify(index, null, 2);\n },\n});\n\nexport const generateTrackFragmentIndex = async (cacheRoot: string, absolutePath: string) => {\n try {\n return await generateTrackFragmentIndexTask(cacheRoot, absolutePath);\n } catch (error) {\n console.trace(\"Error generating track fragment index\", error);\n throw error;\n }\n};\n"],"mappings":";;;;;;;;;;;AAQA,MAAa,qCAAqC,OAAO,iBAAyB;CAChF,MAAM,yBAAY,2BAA2B;CAC7C,MAAM,QAAQ,MAAMA,oBAAM,UAAU,aAAa;CAEjD,MAAM,oBAAoB,MAAM;AAChC,KAAI,sBAAsB,OACxB,KAAI,gCAAgC,kBAAkB,IAAI;KAE1D,KAAI,2EAA2E;AAOjF,KAAI,MAAM,eAAe;AACvB,MAAI,4DAA4D;EAChE,MAAM,YAAY,MAAMC,0DAAyB,cAAc,kBAAkB;EAgBjF,MAAMC,gBAAc,OAbmD,YAAY;AACjF,OAAI;AACF,QAAI,uDAAuD;IAE3D,MAAM,SAAS,MAAMC,oDADD,MAAM,4BAA4B,EACE,mBAAmB,EAAE,GAAG,IAAI,CAAC;AACrF,QAAI,oDAAoD;AACxD,WAAO;YACA,OAAO;AACd,QAAI,kDAAkD,QAAQ;AAC9D,WAAO;;MAEP;EAGJ,MAAMC,yBAA2D,EAAE,GAAG,WAAW;AACjF,MAAIF,cAAa,QAAO,OAAOG,wBAAsBH,cAAY;AACjE,SAAOG;;AAIT,KAAI,uCAAuC,aAAa,8BAA8B;CAEtF,MAAM,aAAa,MAAM,QACtB,KAAK,QAAQ,gBAAgB;AAC5B,MAAI,OAAO,eAAe,WAAW,OAAO,eAAe,QACzD,QAAO;EAET,MAAM,UAAU,cAAc;AAC9B,MAAI,oBAAoB,QAAQ,IAAI,OAAO,WAAW,GAAG;AAGzD,SAAOF,oDAFa,MAAM,sBAAsB,YAAY,EAElB,mBADnB,EAAE,GAAG,SAAS,CACuC;GAC5E,CACD,QAAQ,SAA8D,SAAS,KAAK;CAEvF,MAAMG,YACJ,MAAM,aAAa,SAAS,KACvB,YAAY;AACX,MAAI;AACF,OAAI,wCAAwC;GAE5C,MAAM,SAAS,MAAMH,oDADD,MAAM,4BAA4B,EACE,mBAAmB,EAAE,GAAG,IAAI,CAAC;AACrF,OAAI,oDAAoD;AACxD,UAAO;WACA,OAAO;AACd,OAAI,kDAAkD,QAAQ;AAC9D,UAAO;;KAEP,GACJ,QAAQ,QAAQ,KAAK;CAE3B,MAAM,CAAC,cAAc,eAAe,MAAM,QAAQ,IAAI,CAAC,QAAQ,IAAI,WAAW,EAAE,UAAU,CAAC;CAE3F,MAAMC,uBAA2D,EAAE;AACnE,MAAK,MAAM,UAAU,aACnB,QAAO,OAAO,sBAAsB,OAAO;AAE7C,KAAI,YACF,QAAO,OAAO,sBAAsB,YAAY;AAGlD,QAAO;;AAGT,MAAM,iCAAiCG,sCAAe;CACpD,OAAO;CACP,WAAW,iBAAiB,2BAAY,aAAa,CAAC;CACtD,QAAQ,OAAO,iBAAyB;EACtC,MAAM,QAAQ,MAAM,mCAAmC,aAAa;AACpE,SAAO,KAAK,UAAU,OAAO,MAAM,EAAE;;CAExC,CAAC;AAEF,MAAa,6BAA6B,OAAO,WAAmB,iBAAyB;AAC3F,KAAI;AACF,SAAO,MAAM,+BAA+B,WAAW,aAAa;UAC7D,OAAO;AACd,UAAQ,MAAM,yCAAyC,MAAM;AAC7D,QAAM"}
1
+ {"version":3,"file":"generateTrackFragmentIndex.cjs","names":["Probe","generateWebmSegmentIndex","generateFragmentIndex","idempotentTask"],"sources":["../../src/tasks/generateTrackFragmentIndex.ts"],"mappings":";;;;;;;;;AAQA,MAAa,qCAAqC,OAAO,iBAAyB;CAChF,MAAM,OAAA,GAAA,MAAA,SAAY,2BAA2B;CAC7C,MAAM,QAAQ,MAAMA,cAAAA,MAAM,UAAU,aAAa;CAEjD,MAAM,oBAAoB,MAAM;AAChC,KAAI,sBAAsB,KAAA,EACxB,KAAI,gCAAgC,kBAAkB,IAAI;KAE1D,KAAI,2EAA2E;AAOjF,KAAI,MAAM,eAAe;AACvB,MAAI,4DAA4D;EAChE,MAAM,YAAY,MAAMC,iCAAAA,yBAAyB,cAAc,kBAAkB;EAgBjF,MAAM,cAAc,OAbmD,YAAY;AACjF,OAAI;AACF,QAAI,uDAAuD;IAE3D,MAAM,SAAS,MAAMC,8BAAAA,sBADD,MAAM,4BAA4B,EACE,mBAAmB,EAAE,GAAG,IAAI,CAAC;AACrF,QAAI,oDAAoD;AACxD,WAAO;YACA,OAAO;AACd,QAAI,kDAAkD,QAAQ;AAC9D,WAAO;;MAEP;EAGJ,MAAM,uBAA2D,EAAE,GAAG,WAAW;AACjF,MAAI,YAAa,QAAO,OAAO,sBAAsB,YAAY;AACjE,SAAO;;AAIT,KAAI,uCAAuC,aAAa,8BAA8B;CAEtF,MAAM,aAAa,MAAM,QACtB,KAAK,QAAQ,gBAAgB;AAC5B,MAAI,OAAO,eAAe,WAAW,OAAO,eAAe,QACzD,QAAO;EAET,MAAM,UAAU,cAAc;AAC9B,MAAI,oBAAoB,QAAQ,IAAI,OAAO,WAAW,GAAG;AAGzD,SAAOA,8BAAAA,sBAFa,MAAM,sBAAsB,YAAY,EAElB,mBADnB,EAAE,GAAG,SAAS,CACuC;GAC5E,CACD,QAAQ,SAA8D,SAAS,KAAK;CAEvF,MAAM,YACJ,MAAM,aAAa,SAAS,KACvB,YAAY;AACX,MAAI;AACF,OAAI,wCAAwC;GAE5C,MAAM,SAAS,MAAMA,8BAAAA,sBADD,MAAM,4BAA4B,EACE,mBAAmB,EAAE,GAAG,IAAI,CAAC;AACrF,OAAI,oDAAoD;AACxD,UAAO;WACA,OAAO;AACd,OAAI,kDAAkD,QAAQ;AAC9D,UAAO;;KAEP,GACJ,QAAQ,QAAQ,KAAK;CAE3B,MAAM,CAAC,cAAc,eAAe,MAAM,QAAQ,IAAI,CAAC,QAAQ,IAAI,WAAW,EAAE,UAAU,CAAC;CAE3F,MAAM,uBAA2D,EAAE;AACnE,MAAK,MAAM,UAAU,aACnB,QAAO,OAAO,sBAAsB,OAAO;AAE7C,KAAI,YACF,QAAO,OAAO,sBAAsB,YAAY;AAGlD,QAAO;;AAGT,MAAM,iCAAiCC,uBAAAA,eAAe;CACpD,OAAO;CACP,WAAW,iBAAiB,IAAA,GAAA,UAAA,UAAY,aAAa,CAAC;CACtD,QAAQ,OAAO,iBAAyB;EACtC,MAAM,QAAQ,MAAM,mCAAmC,aAAa;AACpE,SAAO,KAAK,UAAU,OAAO,MAAM,EAAE;;CAExC,CAAC;AAEF,MAAa,6BAA6B,OAAO,WAAmB,iBAAyB;AAC3F,KAAI;AACF,SAAO,MAAM,+BAA+B,WAAW,aAAa;UAC7D,OAAO;AACd,UAAQ,MAAM,yCAAyC,MAAM;AAC7D,QAAM"}