@hyperframes/producer 0.4.19 → 0.4.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7906,7 +7906,7 @@ function inertIfDisposed(target, _) {
7906
7906
  };
7907
7907
  }
7908
7908
  function invokeAtMostOnceForArguments(target, _) {
7909
- const cache = /* @__PURE__ */ new WeakMap();
7909
+ const cache2 = /* @__PURE__ */ new WeakMap();
7910
7910
  let cacheDepth = -1;
7911
7911
  return function(...args) {
7912
7912
  if (cacheDepth === -1) {
@@ -7916,7 +7916,7 @@ function invokeAtMostOnceForArguments(target, _) {
7916
7916
  throw new Error("Memoized method was called with the wrong number of arguments");
7917
7917
  }
7918
7918
  let freshArguments = false;
7919
- let cacheIterator = cache;
7919
+ let cacheIterator = cache2;
7920
7920
  for (const arg of args) {
7921
7921
  if (cacheIterator.has(arg)) {
7922
7922
  cacheIterator = cacheIterator.get(arg);
@@ -45139,7 +45139,7 @@ var require_websocket = __commonJS({
45139
45139
  var http2 = __require("http");
45140
45140
  var net = __require("net");
45141
45141
  var tls = __require("tls");
45142
- var { randomBytes, createHash: createHash3 } = __require("crypto");
45142
+ var { randomBytes, createHash: createHash4 } = __require("crypto");
45143
45143
  var { Duplex, Readable: Readable3 } = __require("stream");
45144
45144
  var { URL: URL3 } = __require("url");
45145
45145
  var PerMessageDeflate = require_permessage_deflate();
@@ -45799,7 +45799,7 @@ var require_websocket = __commonJS({
45799
45799
  abortHandshake(websocket, socket, "Invalid Upgrade header");
45800
45800
  return;
45801
45801
  }
45802
- const digest = createHash3("sha1").update(key2 + GUID).digest("base64");
45802
+ const digest = createHash4("sha1").update(key2 + GUID).digest("base64");
45803
45803
  if (res.headers["sec-websocket-accept"] !== digest) {
45804
45804
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
45805
45805
  return;
@@ -46166,7 +46166,7 @@ var require_websocket_server = __commonJS({
46166
46166
  var EventEmitter4 = __require("events");
46167
46167
  var http2 = __require("http");
46168
46168
  var { Duplex } = __require("stream");
46169
- var { createHash: createHash3 } = __require("crypto");
46169
+ var { createHash: createHash4 } = __require("crypto");
46170
46170
  var extension = require_extension();
46171
46171
  var PerMessageDeflate = require_permessage_deflate();
46172
46172
  var subprotocol = require_subprotocol();
@@ -46467,7 +46467,7 @@ var require_websocket_server = __commonJS({
46467
46467
  );
46468
46468
  }
46469
46469
  if (this._state > RUNNING) return abortHandshake(socket, 503);
46470
- const digest = createHash3("sha1").update(key2 + GUID).digest("base64");
46470
+ const digest = createHash4("sha1").update(key2 + GUID).digest("base64");
46471
46471
  const headers = [
46472
46472
  "HTTP/1.1 101 Switching Protocols",
46473
46473
  "Upgrade: websocket",
@@ -47603,7 +47603,7 @@ var require_range = __commonJS({
47603
47603
  parseRange(range) {
47604
47604
  const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE);
47605
47605
  const memoKey = memoOpts + ":" + range;
47606
- const cached = cache.get(memoKey);
47606
+ const cached = cache2.get(memoKey);
47607
47607
  if (cached) {
47608
47608
  return cached;
47609
47609
  }
@@ -47637,7 +47637,7 @@ var require_range = __commonJS({
47637
47637
  rangeMap.delete("");
47638
47638
  }
47639
47639
  const result = [...rangeMap.values()];
47640
- cache.set(memoKey, result);
47640
+ cache2.set(memoKey, result);
47641
47641
  return result;
47642
47642
  }
47643
47643
  intersects(range, options) {
@@ -47676,7 +47676,7 @@ var require_range = __commonJS({
47676
47676
  };
47677
47677
  module.exports = Range2;
47678
47678
  var LRU = require_lrucache();
47679
- var cache = new LRU();
47679
+ var cache2 = new LRU();
47680
47680
  var parseOptions = require_parse_options();
47681
47681
  var Comparator = require_comparator();
47682
47682
  var debug6 = require_debug();
@@ -54356,12 +54356,12 @@ var require_data = __commonJS({
54356
54356
  this.hash = hash2;
54357
54357
  }
54358
54358
  };
54359
- var data = async ({ href: uri }, { cache } = {}) => {
54359
+ var data = async ({ href: uri }, { cache: cache2 } = {}) => {
54360
54360
  const shasum = (0, crypto_1.createHash)("sha1");
54361
54361
  shasum.update(uri);
54362
54362
  const hash2 = shasum.digest("hex");
54363
54363
  debug6('generated SHA1 hash for "data:" URI: %o', hash2);
54364
- if (cache?.hash === hash2) {
54364
+ if (cache2?.hash === hash2) {
54365
54365
  debug6("got matching cache SHA1 hash: %o", hash2);
54366
54366
  throw new notmodified_1.default();
54367
54367
  } else {
@@ -54406,7 +54406,7 @@ var require_file = __commonJS({
54406
54406
  var debug6 = (0, debug_1.default)("get-uri:file");
54407
54407
  var file = async ({ href: uri }, opts = {}) => {
54408
54408
  const {
54409
- cache,
54409
+ cache: cache2,
54410
54410
  flags = "r",
54411
54411
  mode = 438
54412
54412
  // =0666
@@ -54417,7 +54417,7 @@ var require_file = __commonJS({
54417
54417
  const fdHandle = await fs_1.promises.open(filepath, flags, mode);
54418
54418
  const fd = fdHandle.fd;
54419
54419
  const stat = await fdHandle.stat();
54420
- if (cache && cache.stat && stat && isNotModified(cache.stat, stat)) {
54420
+ if (cache2 && cache2.stat && stat && isNotModified(cache2.stat, stat)) {
54421
54421
  await fdHandle.close();
54422
54422
  throw new notmodified_1.default();
54423
54423
  }
@@ -56437,7 +56437,7 @@ var require_ftp = __commonJS({
56437
56437
  var notmodified_1 = __importDefault2(require_notmodified());
56438
56438
  var debug6 = (0, debug_1.default)("get-uri:ftp");
56439
56439
  var ftp = async (url, opts = {}) => {
56440
- const { cache } = opts;
56440
+ const { cache: cache2 } = opts;
56441
56441
  const filepath = decodeURIComponent(url.pathname);
56442
56442
  let lastModified;
56443
56443
  if (!filepath) {
@@ -56491,8 +56491,8 @@ var require_ftp = __commonJS({
56491
56491
  throw err;
56492
56492
  }
56493
56493
  function isNotModified() {
56494
- if (cache?.lastModified && lastModified) {
56495
- return +cache.lastModified === +lastModified;
56494
+ if (cache2?.lastModified && lastModified) {
56495
+ return +cache2.lastModified === +lastModified;
56496
56496
  }
56497
56497
  return false;
56498
56498
  }
@@ -56537,10 +56537,10 @@ var require_http = __commonJS({
56537
56537
  var debug6 = (0, debug_1.default)("get-uri:http");
56538
56538
  var http2 = async (url, opts = {}) => {
56539
56539
  debug6("GET %o", url.href);
56540
- const cache = getCache(url, opts.cache);
56541
- if (cache && isFresh(cache) && typeof cache.statusCode === "number") {
56542
- const type2 = cache.statusCode / 100 | 0;
56543
- if (type2 === 3 && cache.headers.location) {
56540
+ const cache2 = getCache(url, opts.cache);
56541
+ if (cache2 && isFresh(cache2) && typeof cache2.statusCode === "number") {
56542
+ const type2 = cache2.statusCode / 100 | 0;
56543
+ if (type2 === 3 && cache2.headers.location) {
56544
56544
  debug6("cached redirect");
56545
56545
  throw new Error("TODO: implement cached redirects!");
56546
56546
  }
@@ -56557,16 +56557,16 @@ var require_http = __commonJS({
56557
56557
  debug6("using `http` core module");
56558
56558
  }
56559
56559
  const options = { ...opts };
56560
- if (cache) {
56560
+ if (cache2) {
56561
56561
  if (!options.headers) {
56562
56562
  options.headers = {};
56563
56563
  }
56564
- const lastModified = cache.headers["last-modified"];
56564
+ const lastModified = cache2.headers["last-modified"];
56565
56565
  if (lastModified) {
56566
56566
  options.headers["If-Modified-Since"] = lastModified;
56567
56567
  debug6('added "If-Modified-Since" request header: %o', lastModified);
56568
56568
  }
56569
- const etag = cache.headers.etag;
56569
+ const etag = cache2.headers.etag;
56570
56570
  if (etag) {
56571
56571
  options.headers["If-None-Match"] = etag;
56572
56572
  debug6('added "If-None-Match" request header: %o', etag);
@@ -56613,10 +56613,10 @@ var require_http = __commonJS({
56613
56613
  return res;
56614
56614
  };
56615
56615
  exports.http = http2;
56616
- function isFresh(cache) {
56616
+ function isFresh(cache2) {
56617
56617
  let fresh = false;
56618
- let expires = parseInt(cache.headers.expires || "", 10);
56619
- const cacheControl = cache.headers["cache-control"];
56618
+ let expires = parseInt(cache2.headers.expires || "", 10);
56619
+ const cacheControl = cache2.headers["cache-control"];
56620
56620
  if (cacheControl) {
56621
56621
  debug6("Cache-Control: %o", cacheControl);
56622
56622
  const parts = cacheControl.split(/,\s*?\b/);
@@ -56626,7 +56626,7 @@ var require_http = __commonJS({
56626
56626
  const name = subparts[0];
56627
56627
  switch (name) {
56628
56628
  case "max-age":
56629
- expires = (cache.date || 0) + parseInt(subparts[1], 10) * 1e3;
56629
+ expires = (cache2.date || 0) + parseInt(subparts[1], 10) * 1e3;
56630
56630
  fresh = Date.now() < expires;
56631
56631
  if (fresh) {
56632
56632
  debug6('cache is "fresh" due to previous %o Cache-Control param', part);
@@ -56652,14 +56652,14 @@ var require_http = __commonJS({
56652
56652
  }
56653
56653
  return false;
56654
56654
  }
56655
- function getCache(url, cache) {
56656
- if (cache) {
56657
- if (cache.parsed && cache.parsed.href === url.href) {
56658
- return cache;
56655
+ function getCache(url, cache2) {
56656
+ if (cache2) {
56657
+ if (cache2.parsed && cache2.parsed.href === url.href) {
56658
+ return cache2;
56659
56659
  }
56660
- if (cache.redirects) {
56661
- for (let i = 0; i < cache.redirects.length; i++) {
56662
- const c = getCache(url, cache.redirects[i]);
56660
+ if (cache2.redirects) {
56661
+ for (let i = 0; i < cache2.redirects.length; i++) {
56662
+ const c = getCache(url, cache2.redirects[i]);
56663
56663
  if (c) {
56664
56664
  return c;
56665
56665
  }
@@ -57894,7 +57894,7 @@ var require_util2 = __commonJS({
57894
57894
  return path12;
57895
57895
  }
57896
57896
  exports.normalize = normalize2;
57897
- function join18(aRoot, aPath) {
57897
+ function join19(aRoot, aPath) {
57898
57898
  if (aRoot === "") {
57899
57899
  aRoot = ".";
57900
57900
  }
@@ -57926,7 +57926,7 @@ var require_util2 = __commonJS({
57926
57926
  }
57927
57927
  return joined;
57928
57928
  }
57929
- exports.join = join18;
57929
+ exports.join = join19;
57930
57930
  exports.isAbsolute = function(aPath) {
57931
57931
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
57932
57932
  };
@@ -58099,7 +58099,7 @@ var require_util2 = __commonJS({
58099
58099
  parsed.path = parsed.path.substring(0, index + 1);
58100
58100
  }
58101
58101
  }
58102
- sourceURL = join18(urlGenerate(parsed), sourceURL);
58102
+ sourceURL = join19(urlGenerate(parsed), sourceURL);
58103
58103
  }
58104
58104
  return normalize2(sourceURL);
58105
58105
  }
@@ -59901,7 +59901,7 @@ var require_escodegen = __commonJS({
59901
59901
  function noEmptySpace() {
59902
59902
  return space ? space : " ";
59903
59903
  }
59904
- function join18(left2, right2) {
59904
+ function join19(left2, right2) {
59905
59905
  var leftSource, rightSource, leftCharCode, rightCharCode;
59906
59906
  leftSource = toSourceNodeWhenNeeded(left2).toString();
59907
59907
  if (leftSource.length === 0) {
@@ -60232,8 +60232,8 @@ var require_escodegen = __commonJS({
60232
60232
  } else {
60233
60233
  result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));
60234
60234
  }
60235
- result = join18(result, operator);
60236
- result = [join18(
60235
+ result = join19(result, operator);
60236
+ result = [join19(
60237
60237
  result,
60238
60238
  that.generateExpression(stmt.right, Precedence.Assignment, E_TTT)
60239
60239
  ), ")"];
@@ -60376,11 +60376,11 @@ var require_escodegen = __commonJS({
60376
60376
  var result, fragment;
60377
60377
  result = ["class"];
60378
60378
  if (stmt.id) {
60379
- result = join18(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
60379
+ result = join19(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
60380
60380
  }
60381
60381
  if (stmt.superClass) {
60382
- fragment = join18("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
60383
- result = join18(result, fragment);
60382
+ fragment = join19("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
60383
+ result = join19(result, fragment);
60384
60384
  }
60385
60385
  result.push(space);
60386
60386
  result.push(this.generateStatement(stmt.body, S_TFFT));
@@ -60393,9 +60393,9 @@ var require_escodegen = __commonJS({
60393
60393
  return escapeDirective(stmt.directive) + this.semicolon(flags);
60394
60394
  },
60395
60395
  DoWhileStatement: function(stmt, flags) {
60396
- var result = join18("do", this.maybeBlock(stmt.body, S_TFFF));
60396
+ var result = join19("do", this.maybeBlock(stmt.body, S_TFFF));
60397
60397
  result = this.maybeBlockSuffix(stmt.body, result);
60398
- return join18(result, [
60398
+ return join19(result, [
60399
60399
  "while" + space + "(",
60400
60400
  this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
60401
60401
  ")" + this.semicolon(flags)
@@ -60431,11 +60431,11 @@ var require_escodegen = __commonJS({
60431
60431
  ExportDefaultDeclaration: function(stmt, flags) {
60432
60432
  var result = ["export"], bodyFlags;
60433
60433
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
60434
- result = join18(result, "default");
60434
+ result = join19(result, "default");
60435
60435
  if (isStatement(stmt.declaration)) {
60436
- result = join18(result, this.generateStatement(stmt.declaration, bodyFlags));
60436
+ result = join19(result, this.generateStatement(stmt.declaration, bodyFlags));
60437
60437
  } else {
60438
- result = join18(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
60438
+ result = join19(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
60439
60439
  }
60440
60440
  return result;
60441
60441
  },
@@ -60443,15 +60443,15 @@ var require_escodegen = __commonJS({
60443
60443
  var result = ["export"], bodyFlags, that = this;
60444
60444
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
60445
60445
  if (stmt.declaration) {
60446
- return join18(result, this.generateStatement(stmt.declaration, bodyFlags));
60446
+ return join19(result, this.generateStatement(stmt.declaration, bodyFlags));
60447
60447
  }
60448
60448
  if (stmt.specifiers) {
60449
60449
  if (stmt.specifiers.length === 0) {
60450
- result = join18(result, "{" + space + "}");
60450
+ result = join19(result, "{" + space + "}");
60451
60451
  } else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {
60452
- result = join18(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
60452
+ result = join19(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
60453
60453
  } else {
60454
- result = join18(result, "{");
60454
+ result = join19(result, "{");
60455
60455
  withIndent(function(indent2) {
60456
60456
  var i, iz;
60457
60457
  result.push(newline);
@@ -60469,7 +60469,7 @@ var require_escodegen = __commonJS({
60469
60469
  result.push(base + "}");
60470
60470
  }
60471
60471
  if (stmt.source) {
60472
- result = join18(result, [
60472
+ result = join19(result, [
60473
60473
  "from" + space,
60474
60474
  // ModuleSpecifier
60475
60475
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -60557,7 +60557,7 @@ var require_escodegen = __commonJS({
60557
60557
  ];
60558
60558
  cursor = 0;
60559
60559
  if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {
60560
- result = join18(result, [
60560
+ result = join19(result, [
60561
60561
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
60562
60562
  ]);
60563
60563
  ++cursor;
@@ -60567,7 +60567,7 @@ var require_escodegen = __commonJS({
60567
60567
  result.push(",");
60568
60568
  }
60569
60569
  if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {
60570
- result = join18(result, [
60570
+ result = join19(result, [
60571
60571
  space,
60572
60572
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
60573
60573
  ]);
@@ -60596,7 +60596,7 @@ var require_escodegen = __commonJS({
60596
60596
  }
60597
60597
  }
60598
60598
  }
60599
- result = join18(result, [
60599
+ result = join19(result, [
60600
60600
  "from" + space,
60601
60601
  // ModuleSpecifier
60602
60602
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -60650,7 +60650,7 @@ var require_escodegen = __commonJS({
60650
60650
  return result;
60651
60651
  },
60652
60652
  ThrowStatement: function(stmt, flags) {
60653
- return [join18(
60653
+ return [join19(
60654
60654
  "throw",
60655
60655
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
60656
60656
  ), this.semicolon(flags)];
@@ -60661,7 +60661,7 @@ var require_escodegen = __commonJS({
60661
60661
  result = this.maybeBlockSuffix(stmt.block, result);
60662
60662
  if (stmt.handlers) {
60663
60663
  for (i = 0, iz = stmt.handlers.length; i < iz; ++i) {
60664
- result = join18(result, this.generateStatement(stmt.handlers[i], S_TFFF));
60664
+ result = join19(result, this.generateStatement(stmt.handlers[i], S_TFFF));
60665
60665
  if (stmt.finalizer || i + 1 !== iz) {
60666
60666
  result = this.maybeBlockSuffix(stmt.handlers[i].body, result);
60667
60667
  }
@@ -60669,7 +60669,7 @@ var require_escodegen = __commonJS({
60669
60669
  } else {
60670
60670
  guardedHandlers = stmt.guardedHandlers || [];
60671
60671
  for (i = 0, iz = guardedHandlers.length; i < iz; ++i) {
60672
- result = join18(result, this.generateStatement(guardedHandlers[i], S_TFFF));
60672
+ result = join19(result, this.generateStatement(guardedHandlers[i], S_TFFF));
60673
60673
  if (stmt.finalizer || i + 1 !== iz) {
60674
60674
  result = this.maybeBlockSuffix(guardedHandlers[i].body, result);
60675
60675
  }
@@ -60677,13 +60677,13 @@ var require_escodegen = __commonJS({
60677
60677
  if (stmt.handler) {
60678
60678
  if (Array.isArray(stmt.handler)) {
60679
60679
  for (i = 0, iz = stmt.handler.length; i < iz; ++i) {
60680
- result = join18(result, this.generateStatement(stmt.handler[i], S_TFFF));
60680
+ result = join19(result, this.generateStatement(stmt.handler[i], S_TFFF));
60681
60681
  if (stmt.finalizer || i + 1 !== iz) {
60682
60682
  result = this.maybeBlockSuffix(stmt.handler[i].body, result);
60683
60683
  }
60684
60684
  }
60685
60685
  } else {
60686
- result = join18(result, this.generateStatement(stmt.handler, S_TFFF));
60686
+ result = join19(result, this.generateStatement(stmt.handler, S_TFFF));
60687
60687
  if (stmt.finalizer) {
60688
60688
  result = this.maybeBlockSuffix(stmt.handler.body, result);
60689
60689
  }
@@ -60691,7 +60691,7 @@ var require_escodegen = __commonJS({
60691
60691
  }
60692
60692
  }
60693
60693
  if (stmt.finalizer) {
60694
- result = join18(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
60694
+ result = join19(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
60695
60695
  }
60696
60696
  return result;
60697
60697
  },
@@ -60725,7 +60725,7 @@ var require_escodegen = __commonJS({
60725
60725
  withIndent(function() {
60726
60726
  if (stmt.test) {
60727
60727
  result = [
60728
- join18("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
60728
+ join19("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
60729
60729
  ":"
60730
60730
  ];
60731
60731
  } else {
@@ -60773,9 +60773,9 @@ var require_escodegen = __commonJS({
60773
60773
  result.push(this.maybeBlock(stmt.consequent, S_TFFF));
60774
60774
  result = this.maybeBlockSuffix(stmt.consequent, result);
60775
60775
  if (stmt.alternate.type === Syntax.IfStatement) {
60776
- result = join18(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
60776
+ result = join19(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
60777
60777
  } else {
60778
- result = join18(result, join18("else", this.maybeBlock(stmt.alternate, bodyFlags)));
60778
+ result = join19(result, join19("else", this.maybeBlock(stmt.alternate, bodyFlags)));
60779
60779
  }
60780
60780
  } else {
60781
60781
  result.push(this.maybeBlock(stmt.consequent, bodyFlags));
@@ -60876,7 +60876,7 @@ var require_escodegen = __commonJS({
60876
60876
  },
60877
60877
  ReturnStatement: function(stmt, flags) {
60878
60878
  if (stmt.argument) {
60879
- return [join18(
60879
+ return [join19(
60880
60880
  "return",
60881
60881
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
60882
60882
  ), this.semicolon(flags)];
@@ -60965,14 +60965,14 @@ var require_escodegen = __commonJS({
60965
60965
  if (leftSource.charCodeAt(leftSource.length - 1) === 47 && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {
60966
60966
  result = [fragment, noEmptySpace(), expr.operator];
60967
60967
  } else {
60968
- result = join18(fragment, expr.operator);
60968
+ result = join19(fragment, expr.operator);
60969
60969
  }
60970
60970
  fragment = this.generateExpression(expr.right, rightPrecedence, flags);
60971
60971
  if (expr.operator === "/" && fragment.toString().charAt(0) === "/" || expr.operator.slice(-1) === "<" && fragment.toString().slice(0, 3) === "!--") {
60972
60972
  result.push(noEmptySpace());
60973
60973
  result.push(fragment);
60974
60974
  } else {
60975
- result = join18(result, fragment);
60975
+ result = join19(result, fragment);
60976
60976
  }
60977
60977
  if (expr.operator === "in" && !(flags & F_ALLOW_IN)) {
60978
60978
  return ["(", result, ")"];
@@ -61012,7 +61012,7 @@ var require_escodegen = __commonJS({
61012
61012
  var result, length, i, iz, itemFlags;
61013
61013
  length = expr["arguments"].length;
61014
61014
  itemFlags = flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0 ? E_TFT : E_TFF;
61015
- result = join18(
61015
+ result = join19(
61016
61016
  "new",
61017
61017
  this.generateExpression(expr.callee, Precedence.New, itemFlags)
61018
61018
  );
@@ -61062,11 +61062,11 @@ var require_escodegen = __commonJS({
61062
61062
  var result, fragment, rightCharCode, leftSource, leftCharCode;
61063
61063
  fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);
61064
61064
  if (space === "") {
61065
- result = join18(expr.operator, fragment);
61065
+ result = join19(expr.operator, fragment);
61066
61066
  } else {
61067
61067
  result = [expr.operator];
61068
61068
  if (expr.operator.length > 2) {
61069
- result = join18(result, fragment);
61069
+ result = join19(result, fragment);
61070
61070
  } else {
61071
61071
  leftSource = toSourceNodeWhenNeeded(result).toString();
61072
61072
  leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
@@ -61089,7 +61089,7 @@ var require_escodegen = __commonJS({
61089
61089
  result = "yield";
61090
61090
  }
61091
61091
  if (expr.argument) {
61092
- result = join18(
61092
+ result = join19(
61093
61093
  result,
61094
61094
  this.generateExpression(expr.argument, Precedence.Yield, E_TTT)
61095
61095
  );
@@ -61097,7 +61097,7 @@ var require_escodegen = __commonJS({
61097
61097
  return parenthesize(result, Precedence.Yield, precedence);
61098
61098
  },
61099
61099
  AwaitExpression: function(expr, precedence, flags) {
61100
- var result = join18(
61100
+ var result = join19(
61101
61101
  expr.all ? "await*" : "await",
61102
61102
  this.generateExpression(expr.argument, Precedence.Await, E_TTT)
61103
61103
  );
@@ -61180,11 +61180,11 @@ var require_escodegen = __commonJS({
61180
61180
  var result, fragment;
61181
61181
  result = ["class"];
61182
61182
  if (expr.id) {
61183
- result = join18(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
61183
+ result = join19(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
61184
61184
  }
61185
61185
  if (expr.superClass) {
61186
- fragment = join18("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
61187
- result = join18(result, fragment);
61186
+ fragment = join19("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
61187
+ result = join19(result, fragment);
61188
61188
  }
61189
61189
  result.push(space);
61190
61190
  result.push(this.generateStatement(expr.body, S_TFFT));
@@ -61199,7 +61199,7 @@ var require_escodegen = __commonJS({
61199
61199
  }
61200
61200
  if (expr.kind === "get" || expr.kind === "set") {
61201
61201
  fragment = [
61202
- join18(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
61202
+ join19(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
61203
61203
  this.generateFunctionBody(expr.value)
61204
61204
  ];
61205
61205
  } else {
@@ -61209,7 +61209,7 @@ var require_escodegen = __commonJS({
61209
61209
  this.generateFunctionBody(expr.value)
61210
61210
  ];
61211
61211
  }
61212
- return join18(result, fragment);
61212
+ return join19(result, fragment);
61213
61213
  },
61214
61214
  Property: function(expr, precedence, flags) {
61215
61215
  if (expr.kind === "get" || expr.kind === "set") {
@@ -61404,7 +61404,7 @@ var require_escodegen = __commonJS({
61404
61404
  for (i = 0, iz = expr.blocks.length; i < iz; ++i) {
61405
61405
  fragment = that.generateExpression(expr.blocks[i], Precedence.Sequence, E_TTT);
61406
61406
  if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
61407
- result = join18(result, fragment);
61407
+ result = join19(result, fragment);
61408
61408
  } else {
61409
61409
  result.push(fragment);
61410
61410
  }
@@ -61412,13 +61412,13 @@ var require_escodegen = __commonJS({
61412
61412
  });
61413
61413
  }
61414
61414
  if (expr.filter) {
61415
- result = join18(result, "if" + space);
61415
+ result = join19(result, "if" + space);
61416
61416
  fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);
61417
- result = join18(result, ["(", fragment, ")"]);
61417
+ result = join19(result, ["(", fragment, ")"]);
61418
61418
  }
61419
61419
  if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
61420
61420
  fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
61421
- result = join18(result, fragment);
61421
+ result = join19(result, fragment);
61422
61422
  }
61423
61423
  result.push(expr.type === Syntax.GeneratorExpression ? ")" : "]");
61424
61424
  return result;
@@ -61434,8 +61434,8 @@ var require_escodegen = __commonJS({
61434
61434
  } else {
61435
61435
  fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);
61436
61436
  }
61437
- fragment = join18(fragment, expr.of ? "of" : "in");
61438
- fragment = join18(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
61437
+ fragment = join19(fragment, expr.of ? "of" : "in");
61438
+ fragment = join19(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
61439
61439
  return ["for" + space + "(", fragment, ")"];
61440
61440
  },
61441
61441
  SpreadElement: function(expr, precedence, flags) {
@@ -69092,12 +69092,12 @@ var require_path = __commonJS({
69092
69092
  return path12.__childCache || (path12.__childCache = /* @__PURE__ */ Object.create(null));
69093
69093
  }
69094
69094
  function getChildPath(path12, name) {
69095
- var cache = getChildCache(path12);
69095
+ var cache2 = getChildCache(path12);
69096
69096
  var actualChildValue = path12.getValueProperty(name);
69097
- var childPath = cache[name];
69098
- if (!hasOwn.call(cache, name) || // Ensure consistency between cache and reality.
69097
+ var childPath = cache2[name];
69098
+ if (!hasOwn.call(cache2, name) || // Ensure consistency between cache and reality.
69099
69099
  childPath.value !== actualChildValue) {
69100
- childPath = cache[name] = new path12.constructor(actualChildValue, path12, name);
69100
+ childPath = cache2[name] = new path12.constructor(actualChildValue, path12, name);
69101
69101
  }
69102
69102
  return childPath;
69103
69103
  }
@@ -69173,7 +69173,7 @@ var require_path = __commonJS({
69173
69173
  isNumber4.assert(start);
69174
69174
  isNumber4.assert(end);
69175
69175
  var moves = /* @__PURE__ */ Object.create(null);
69176
- var cache = getChildCache(path12);
69176
+ var cache2 = getChildCache(path12);
69177
69177
  for (var i = start; i < end; ++i) {
69178
69178
  if (hasOwn.call(path12.value, i)) {
69179
69179
  var childPath = path12.get(i);
@@ -69183,17 +69183,17 @@ var require_path = __commonJS({
69183
69183
  var newIndex = i + offset;
69184
69184
  childPath.name = newIndex;
69185
69185
  moves[newIndex] = childPath;
69186
- delete cache[i];
69186
+ delete cache2[i];
69187
69187
  }
69188
69188
  }
69189
- delete cache.length;
69189
+ delete cache2.length;
69190
69190
  return function() {
69191
69191
  for (var newIndex2 in moves) {
69192
69192
  var childPath2 = moves[newIndex2];
69193
69193
  if (childPath2.name !== +newIndex2) {
69194
69194
  throw new Error("");
69195
69195
  }
69196
- cache[newIndex2] = childPath2;
69196
+ cache2[newIndex2] = childPath2;
69197
69197
  path12.value[newIndex2] = childPath2.value;
69198
69198
  }
69199
69199
  };
@@ -69225,9 +69225,9 @@ var require_path = __commonJS({
69225
69225
  };
69226
69226
  Pp.pop = function pop() {
69227
69227
  isArray4.assert(this.value);
69228
- var cache = getChildCache(this);
69229
- delete cache[this.value.length - 1];
69230
- delete cache.length;
69228
+ var cache2 = getChildCache(this);
69229
+ delete cache2[this.value.length - 1];
69230
+ delete cache2.length;
69231
69231
  return this.value.pop();
69232
69232
  };
69233
69233
  Pp.insertAt = function insertAt(index) {
@@ -76739,12 +76739,12 @@ var init_Cache = __esm({
76739
76739
  /**
76740
76740
  * @internal
76741
76741
  */
76742
- constructor(cache, browser, buildId, platform) {
76743
- this.#cache = cache;
76742
+ constructor(cache2, browser, buildId, platform) {
76743
+ this.#cache = cache2;
76744
76744
  this.browser = browser;
76745
76745
  this.buildId = buildId;
76746
76746
  this.platform = platform;
76747
- this.executablePath = cache.computeExecutablePath({
76747
+ this.executablePath = cache2.computeExecutablePath({
76748
76748
  browser,
76749
76749
  buildId,
76750
76750
  platform
@@ -81914,8 +81914,8 @@ async function installWithProviders(options) {
81914
81914
  if (!options.platform) {
81915
81915
  throw new Error("Platform must be defined");
81916
81916
  }
81917
- const cache = new Cache(options.cacheDir);
81918
- const browserRoot = cache.browserRoot(options.browser);
81917
+ const cache2 = new Cache(options.cacheDir);
81918
+ const browserRoot = cache2.browserRoot(options.browser);
81919
81919
  const providers = [...options.providers || []];
81920
81920
  if (options.baseUrl) {
81921
81921
  providers.push(new DefaultProvider(options.baseUrl));
@@ -82017,8 +82017,8 @@ async function installUrl(url, options, provider) {
82017
82017
  }
82018
82018
  const fileName = decodeURIComponent(url.toString()).split("/").pop();
82019
82019
  assert2(fileName, `A malformed download URL was found: ${url}.`);
82020
- const cache = new Cache(options.cacheDir);
82021
- const browserRoot = cache.browserRoot(options.browser);
82020
+ const cache2 = new Cache(options.cacheDir);
82021
+ const browserRoot = cache2.browserRoot(options.browser);
82022
82022
  const archivePath = path8.join(browserRoot, `${options.buildId}-${fileName}`);
82023
82023
  if (!existsSync(browserRoot)) {
82024
82024
  await mkdir2(browserRoot, { recursive: true });
@@ -82033,16 +82033,16 @@ async function installUrl(url, options, provider) {
82033
82033
  debugTimeEnd("download");
82034
82034
  return archivePath;
82035
82035
  }
82036
- const outputPath = cache.installationDir(options.browser, options.platform, options.buildId);
82036
+ const outputPath = cache2.installationDir(options.browser, options.platform, options.buildId);
82037
82037
  const relativeExecutablePath6 = await provider.getExecutablePath({
82038
82038
  browser: options.browser,
82039
82039
  buildId: options.buildId,
82040
82040
  platform: options.platform
82041
82041
  });
82042
82042
  debugInstall(`Using executable path from provider: ${relativeExecutablePath6}`);
82043
- const installedBrowser = new InstalledBrowser(cache, options.browser, options.buildId, options.platform);
82043
+ const installedBrowser = new InstalledBrowser(cache2, options.browser, options.buildId, options.platform);
82044
82044
  if (!(provider instanceof DefaultProvider)) {
82045
- cache.writeExecutablePath(options.browser, options.platform, options.buildId, relativeExecutablePath6);
82045
+ cache2.writeExecutablePath(options.browser, options.platform, options.buildId, relativeExecutablePath6);
82046
82046
  }
82047
82047
  try {
82048
82048
  if (existsSync(outputPath)) {
@@ -87414,8 +87414,8 @@ var init_CLI = __esm({
87414
87414
  console.log("Cancelled.");
87415
87415
  return;
87416
87416
  }
87417
- const cache = new Cache(cacheDir);
87418
- cache.clear();
87417
+ const cache2 = new Cache(cacheDir);
87418
+ cache2.clear();
87419
87419
  console.log(`${cacheDir} cleared.`);
87420
87420
  });
87421
87421
  }).command("list", "List all installed browsers in the cache directory", (yargs2) => {
@@ -87426,8 +87426,8 @@ var init_CLI = __esm({
87426
87426
  return this.#definePathParameter(yargs2);
87427
87427
  }, async (args) => {
87428
87428
  const cacheDir = args.path ?? this.#cachePath;
87429
- const cache = new Cache(cacheDir);
87430
- const browsers = cache.getInstalledBrowsers();
87429
+ const cache2 = new Cache(cacheDir);
87430
+ const browsers = cache2.getInstalledBrowsers();
87431
87431
  for (const browser of browsers) {
87432
87432
  console.log(`${browser.browser}@${browser.buildId} (${browser.platform}) ${browser.executablePath}`);
87433
87433
  }
@@ -87597,9 +87597,9 @@ async function getConnectionTransport(options) {
87597
87597
  throw new Error("Could not detect required browser platform");
87598
87598
  }
87599
87599
  const { convertPuppeteerChannelToBrowsersChannel: convertPuppeteerChannelToBrowsersChannel2 } = await Promise.resolve().then(() => (init_LaunchOptions(), LaunchOptions_exports));
87600
- const { join: join18 } = await import("node:path");
87600
+ const { join: join19 } = await import("node:path");
87601
87601
  const userDataDir = resolveDefaultUserDataDir3(Browser4.CHROME, platform, convertPuppeteerChannelToBrowsersChannel2(options.channel));
87602
- const portPath = join18(userDataDir, "DevToolsActivePort");
87602
+ const portPath = join19(userDataDir, "DevToolsActivePort");
87603
87603
  try {
87604
87604
  const fileContent = await environment.value.fs.promises.readFile(portPath, "ascii");
87605
87605
  const [rawPort, rawPath] = fileContent.split("\n").map((line) => {
@@ -89417,12 +89417,13 @@ var init_puppeteer_core = __esm({
89417
89417
 
89418
89418
  // src/services/renderOrchestrator.ts
89419
89419
  import {
89420
- existsSync as existsSync15,
89421
- mkdirSync as mkdirSync10,
89420
+ existsSync as existsSync16,
89421
+ mkdirSync as mkdirSync11,
89422
89422
  rmSync as rmSync3,
89423
89423
  readFileSync as readFileSync10,
89424
- readdirSync as readdirSync6,
89425
- writeFileSync as writeFileSync4,
89424
+ readdirSync as readdirSync8,
89425
+ statSync as statSync7,
89426
+ writeFileSync as writeFileSync5,
89426
89427
  copyFileSync as copyFileSync2,
89427
89428
  appendFileSync
89428
89429
  } from "fs";
@@ -98747,7 +98748,8 @@ function resolveConfig(overrides) {
98747
98748
  DEFAULT_CONFIG.renderReadyTimeout
98748
98749
  ),
98749
98750
  verifyRuntime: env2("PRODUCER_VERIFY_HYPERFRAME_RUNTIME") !== "false",
98750
- runtimeManifestPath: env2("PRODUCER_HYPERFRAME_MANIFEST_PATH")
98751
+ runtimeManifestPath: env2("PRODUCER_HYPERFRAME_MANIFEST_PATH"),
98752
+ extractCacheDir: env2("HYPERFRAMES_EXTRACT_CACHE_DIR")
98751
98753
  };
98752
98754
  const cleanEnv = Object.fromEntries(Object.entries(fromEnv).filter(([, v]) => v !== void 0));
98753
98755
  return {
@@ -99903,6 +99905,7 @@ var mediaRules = [
99903
99905
 
99904
99906
  // ../core/src/lint/rules/gsap.ts
99905
99907
  var META_GSAP_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "repeat", "yoyo", "overwrite", "delay"]);
99908
+ var SCENE_BOUNDARY_EPSILON_SECONDS = 0.05;
99906
99909
  function countClassUsage(tags) {
99907
99910
  const counts = /* @__PURE__ */ new Map();
99908
99911
  for (const tag of tags) {
@@ -99943,6 +99946,7 @@ function extractGsapWindows(script) {
99943
99946
  position: animation.position,
99944
99947
  end: animation.position + meta.effectiveDuration,
99945
99948
  properties: meta.properties.length > 0 ? meta.properties : Object.keys(animation.properties),
99949
+ propertyValues: meta.propertyValues,
99946
99950
  overwriteAuto: meta.overwriteAuto,
99947
99951
  method: match2[1] ?? "to",
99948
99952
  raw: raw2
@@ -99951,8 +99955,14 @@ function extractGsapWindows(script) {
99951
99955
  return windows;
99952
99956
  }
99953
99957
  function parseGsapWindowMeta(method, argsStr) {
99958
+ const emptyMeta = {
99959
+ effectiveDuration: 0,
99960
+ properties: [],
99961
+ propertyValues: {},
99962
+ overwriteAuto: false
99963
+ };
99954
99964
  const selectorMatch = argsStr.match(/^\s*["']([^"']+)["']\s*,/);
99955
- if (!selectorMatch) return { effectiveDuration: 0, properties: [], overwriteAuto: false };
99965
+ if (!selectorMatch) return emptyMeta;
99956
99966
  const afterSelector = argsStr.slice(selectorMatch[0].length);
99957
99967
  let properties = {};
99958
99968
  let fromProperties = {};
@@ -99990,6 +100000,7 @@ function parseGsapWindowMeta(method, argsStr) {
99990
100000
  return {
99991
100001
  effectiveDuration: method === "set" ? 0 : effectiveDuration,
99992
100002
  properties: [...propertyNames],
100003
+ propertyValues: properties,
99993
100004
  overwriteAuto
99994
100005
  };
99995
100006
  }
@@ -100037,6 +100048,94 @@ function stringValue(value) {
100037
100048
  if (typeof value === "number") return String(value);
100038
100049
  return null;
100039
100050
  }
100051
+ function zeroValue(value) {
100052
+ if (typeof value === "number") return value === 0;
100053
+ if (typeof value !== "string") return false;
100054
+ return Number(value.trim()) === 0;
100055
+ }
100056
+ function isHiddenGsapState(values) {
100057
+ const visibility = stringValue(values.visibility)?.toLowerCase();
100058
+ const display = stringValue(values.display)?.toLowerCase();
100059
+ return zeroValue(values.opacity) || zeroValue(values.autoAlpha) || visibility === "hidden" || display === "none";
100060
+ }
100061
+ function isSceneBoundaryExit(win) {
100062
+ if (win.end <= win.position) return false;
100063
+ if (win.method !== "to" && win.method !== "fromTo") return false;
100064
+ return isHiddenGsapState(win.propertyValues);
100065
+ }
100066
+ function isHardKillSet(win, selector, boundary) {
100067
+ return win.method === "set" && win.targetSelector === selector && Math.abs(win.position - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS && isHiddenGsapState(win.propertyValues);
100068
+ }
100069
+ function hiddenStateLiteral(values) {
100070
+ if (zeroValue(values.autoAlpha)) return "{ autoAlpha: 0 }";
100071
+ if (zeroValue(values.opacity)) return "{ opacity: 0 }";
100072
+ if (stringValue(values.visibility)?.toLowerCase() === "hidden") return '{ visibility: "hidden" }';
100073
+ if (stringValue(values.display)?.toLowerCase() === "none") return '{ display: "none" }';
100074
+ return "{ opacity: 0 }";
100075
+ }
100076
+ function findTagEnd(source2, tag) {
100077
+ const escapedTagName = tag.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
100078
+ const pattern = new RegExp(`<\\/?${escapedTagName}\\b[^>]*>`, "gi");
100079
+ pattern.lastIndex = tag.index;
100080
+ let depth = 0;
100081
+ let match2;
100082
+ while ((match2 = pattern.exec(source2)) !== null) {
100083
+ const raw2 = match2[0];
100084
+ const isClosing = /^<\s*\//.test(raw2);
100085
+ const isSelfClosing = /\/\s*>$/.test(raw2);
100086
+ if (!isClosing && !isSelfClosing) depth += 1;
100087
+ if (isClosing) depth -= 1;
100088
+ if (depth === 0) return pattern.lastIndex;
100089
+ }
100090
+ return source2.length;
100091
+ }
100092
+ function collectCompositionRanges(source2, tags) {
100093
+ return tags.map((tag) => {
100094
+ const id = readAttr(tag.raw, "data-composition-id");
100095
+ if (!id) return null;
100096
+ return {
100097
+ id,
100098
+ start: tag.index,
100099
+ end: findTagEnd(source2, tag)
100100
+ };
100101
+ }).filter((range) => range !== null);
100102
+ }
100103
+ function findContainingCompositionId(tag, ranges) {
100104
+ let match2 = null;
100105
+ for (const range of ranges) {
100106
+ if (tag.index < range.start || tag.index >= range.end) continue;
100107
+ if (!match2 || range.start >= match2.start) match2 = range;
100108
+ }
100109
+ return match2?.id || null;
100110
+ }
100111
+ function collectClipStartBoundariesByComposition(source2, tags) {
100112
+ const ranges = collectCompositionRanges(source2, tags);
100113
+ const boundaries = /* @__PURE__ */ new Map();
100114
+ for (const tag of tags) {
100115
+ const classAttr = readAttr(tag.raw, "class") || "";
100116
+ const classes = classAttr.split(/\s+/).filter(Boolean);
100117
+ if (!classes.includes("clip")) continue;
100118
+ const compositionId = findContainingCompositionId(tag, ranges);
100119
+ if (!compositionId) continue;
100120
+ const start = numberValue(readAttr(tag.raw, "data-start") ?? void 0);
100121
+ if (start == null || start <= 0) continue;
100122
+ const compositionBoundaries = boundaries.get(compositionId) ?? /* @__PURE__ */ new Set();
100123
+ compositionBoundaries.add(start);
100124
+ boundaries.set(compositionId, compositionBoundaries);
100125
+ }
100126
+ return new Map(
100127
+ [...boundaries.entries()].map(([compositionId, values]) => [
100128
+ compositionId,
100129
+ [...values].sort((a, b) => a - b)
100130
+ ])
100131
+ );
100132
+ }
100133
+ function findMatchingSceneBoundary(time, boundaries) {
100134
+ for (const boundary of boundaries) {
100135
+ if (Math.abs(time - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS) return boundary;
100136
+ }
100137
+ return null;
100138
+ }
100040
100139
  function isSuspiciousGlobalSelector(selector) {
100041
100140
  if (!selector) return false;
100042
100141
  if (selector.includes("[data-composition-id=")) return false;
@@ -100077,7 +100176,7 @@ function cssTransformToGsapProps(cssTransform) {
100077
100176
  }
100078
100177
  var gsapRules = [
100079
100178
  // overlapping_gsap_tweens + gsap_animates_clip_element + unscoped_gsap_selector
100080
- ({ tags, scripts, rootCompositionId }) => {
100179
+ ({ source: source2, tags, scripts, rootCompositionId }) => {
100081
100180
  const findings = [];
100082
100181
  const clipIds = /* @__PURE__ */ new Map();
100083
100182
  const clipClasses = /* @__PURE__ */ new Map();
@@ -100097,9 +100196,11 @@ var gsapRules = [
100097
100196
  }
100098
100197
  }
100099
100198
  const classUsage = countClassUsage(tags);
100199
+ const clipStartBoundariesByComposition = collectClipStartBoundariesByComposition(source2, tags);
100100
100200
  for (const script of scripts) {
100101
100201
  const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);
100102
100202
  const gsapWindows = extractGsapWindows(script.content);
100203
+ const clipStartBoundaries = clipStartBoundariesByComposition.get(localTimelineCompId || rootCompositionId || "") ?? [];
100103
100204
  for (let i = 0; i < gsapWindows.length; i++) {
100104
100205
  const left2 = gsapWindows[i];
100105
100206
  if (!left2) continue;
@@ -100128,6 +100229,25 @@ ${right2.raw}`)
100128
100229
  });
100129
100230
  }
100130
100231
  }
100232
+ if (clipStartBoundaries.length > 0) {
100233
+ for (const win of gsapWindows) {
100234
+ if (!isSceneBoundaryExit(win)) continue;
100235
+ const boundary = findMatchingSceneBoundary(win.end, clipStartBoundaries);
100236
+ if (boundary == null) continue;
100237
+ const hasHardKill = gsapWindows.some(
100238
+ (candidate) => isHardKillSet(candidate, win.targetSelector, boundary)
100239
+ );
100240
+ if (hasHardKill) continue;
100241
+ findings.push({
100242
+ code: "gsap_exit_missing_hard_kill",
100243
+ severity: "warning",
100244
+ message: `GSAP exit on "${win.targetSelector}" ends at the ${boundary.toFixed(2)}s clip start boundary without a matching tl.set hard kill. Non-linear seeking can land after the fade and leave stale visibility state.`,
100245
+ selector: win.targetSelector,
100246
+ fixHint: `Add \`tl.set("${win.targetSelector}", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\` after the exit tween.`,
100247
+ snippet: truncateSnippet(win.raw)
100248
+ });
100249
+ }
100250
+ }
100131
100251
  for (const win of gsapWindows) {
100132
100252
  const sel = win.targetSelector;
100133
100253
  const clipInfo = clipIds.get(sel) || clipClasses.get(sel);
@@ -102442,8 +102562,8 @@ Process error: ${err.message}`;
102442
102562
 
102443
102563
  // ../engine/src/services/videoFrameExtractor.ts
102444
102564
  import { spawn as spawn8 } from "child_process";
102445
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync4, rmSync } from "fs";
102446
- import { isAbsolute as isAbsolute2, join as join8 } from "path";
102565
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync5, rmSync } from "fs";
102566
+ import { isAbsolute as isAbsolute2, join as join9 } from "path";
102447
102567
 
102448
102568
  // ../engine/src/utils/ffprobe.ts
102449
102569
  import { spawn as spawn7 } from "child_process";
@@ -102773,10 +102893,115 @@ function isHttpUrl(path12) {
102773
102893
  return path12.startsWith("http://") || path12.startsWith("https://");
102774
102894
  }
102775
102895
 
102896
+ // ../engine/src/utils/htmlTemplate.ts
102897
+ function parseHTMLContent(html) {
102898
+ const trimmed = html.trimStart().toLowerCase();
102899
+ if (trimmed.startsWith("<!doctype") || trimmed.startsWith("<html")) {
102900
+ return parseHTML(html).document;
102901
+ }
102902
+ return parseHTML(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`).document;
102903
+ }
102904
+ function getSingleMeaningfulChild(container) {
102905
+ let child = null;
102906
+ for (const node of Array.from(container.childNodes)) {
102907
+ if (node.nodeType === 3 && !(node.textContent || "").trim()) continue;
102908
+ if (node.nodeType === 8) continue;
102909
+ if (node.nodeType !== 1) return null;
102910
+ if (child) return null;
102911
+ child = node;
102912
+ }
102913
+ return child;
102914
+ }
102915
+ function unwrapTemplate(html) {
102916
+ const lowered = html.toLowerCase();
102917
+ if (!lowered.includes("<template") || !lowered.includes("</template>")) {
102918
+ return html;
102919
+ }
102920
+ const { body } = parseHTMLContent(html);
102921
+ if (!body) return html;
102922
+ let container = body;
102923
+ const bodyWrapper = getSingleMeaningfulChild(container);
102924
+ if (bodyWrapper?.tagName === "BODY") {
102925
+ container = bodyWrapper;
102926
+ }
102927
+ const template = getSingleMeaningfulChild(container);
102928
+ if (template?.tagName !== "TEMPLATE") {
102929
+ return html;
102930
+ }
102931
+ return template.innerHTML ?? html;
102932
+ }
102933
+
102934
+ // ../engine/src/services/extractionCache.ts
102935
+ import { createHash as createHash2 } from "node:crypto";
102936
+ import { mkdirSync as mkdirSync5, readdirSync as readdirSync4, statSync as statSync5, writeFileSync as writeFileSync3 } from "node:fs";
102937
+ import { existsSync as existsSync8 } from "node:fs";
102938
+ import { join as join8 } from "node:path";
102939
+ var FRAME_FILENAME_PREFIX = "frame_";
102940
+ var COMPLETE_SENTINEL = ".hf-complete";
102941
+ var SCHEMA_PREFIX = "hfcache-v2-";
102942
+ var KEY_HEX_CHARS = 16;
102943
+ function readKeyStat(videoPath) {
102944
+ try {
102945
+ const stat = statSync5(videoPath);
102946
+ return { mtimeMs: Math.floor(stat.mtimeMs), size: stat.size };
102947
+ } catch {
102948
+ return null;
102949
+ }
102950
+ }
102951
+ function canonicalKeyBlob(input2) {
102952
+ const durationForKey = Number.isFinite(input2.duration) ? input2.duration : -1;
102953
+ return JSON.stringify({
102954
+ p: input2.videoPath,
102955
+ m: input2.mtimeMs,
102956
+ s: input2.size,
102957
+ ms: input2.mediaStart,
102958
+ d: durationForKey,
102959
+ f: input2.fps,
102960
+ fmt: input2.format
102961
+ });
102962
+ }
102963
+ function computeCacheKey(input2) {
102964
+ return createHash2("sha256").update(canonicalKeyBlob(input2)).digest("hex");
102965
+ }
102966
+ function cacheEntryDirName(keyHash) {
102967
+ return SCHEMA_PREFIX + keyHash.slice(0, KEY_HEX_CHARS);
102968
+ }
102969
+ function lookupCacheEntry(rootDir, input2) {
102970
+ const keyHash = computeCacheKey(input2);
102971
+ const dir = join8(rootDir, cacheEntryDirName(keyHash));
102972
+ const complete = existsSync8(join8(dir, COMPLETE_SENTINEL));
102973
+ return { entry: { dir, keyHash }, hit: complete };
102974
+ }
102975
+ function ensureCacheEntryDir(entry) {
102976
+ mkdirSync5(entry.dir, { recursive: true });
102977
+ }
102978
+ function markCacheEntryComplete(entry) {
102979
+ writeFileSync3(join8(entry.dir, COMPLETE_SENTINEL), "", "utf-8");
102980
+ }
102981
+ function rehydrateCacheEntry(entry, options) {
102982
+ const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${options.format}`;
102983
+ const framePaths = /* @__PURE__ */ new Map();
102984
+ const suffix = `.${options.format}`;
102985
+ const files = readdirSync4(entry.dir).filter((f) => f.startsWith(FRAME_FILENAME_PREFIX) && f.endsWith(suffix)).sort();
102986
+ files.forEach((file, idx) => {
102987
+ framePaths.set(idx, join8(entry.dir, file));
102988
+ });
102989
+ return {
102990
+ videoId: options.videoId,
102991
+ srcPath: options.srcPath,
102992
+ outputDir: entry.dir,
102993
+ framePattern,
102994
+ fps: options.fps,
102995
+ totalFrames: framePaths.size,
102996
+ metadata: options.metadata,
102997
+ framePaths
102998
+ };
102999
+ }
103000
+
102776
103001
  // ../engine/src/services/videoFrameExtractor.ts
102777
103002
  function parseVideoElements(html) {
102778
103003
  const videos = [];
102779
- const { document: document2 } = parseHTML(html);
103004
+ const { document: document2 } = parseHTML(unwrapTemplate(html));
102780
103005
  const videoEls = document2.querySelectorAll("video[src]");
102781
103006
  let autoIdCounter = 0;
102782
103007
  for (const el of videoEls) {
@@ -102813,7 +103038,7 @@ function parseVideoElements(html) {
102813
103038
  }
102814
103039
  function parseImageElements(html) {
102815
103040
  const images = [];
102816
- const { document: document2 } = parseHTML(html);
103041
+ const { document: document2 } = parseHTML(unwrapTemplate(html));
102817
103042
  const imgEls = document2.querySelectorAll("img[src]");
102818
103043
  let autoIdCounter = 0;
102819
103044
  for (const el of imgEls) {
@@ -102839,14 +103064,14 @@ function parseImageElements(html) {
102839
103064
  }
102840
103065
  return images;
102841
103066
  }
102842
- async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config2) {
103067
+ async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config2, outputDirOverride) {
102843
103068
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
102844
103069
  const { fps, outputDir, quality = 95, format: format3 = "jpg" } = options;
102845
- const videoOutputDir = join8(outputDir, videoId);
102846
- if (!existsSync8(videoOutputDir)) mkdirSync5(videoOutputDir, { recursive: true });
103070
+ const videoOutputDir = outputDirOverride ?? join9(outputDir, videoId);
103071
+ if (!existsSync9(videoOutputDir)) mkdirSync6(videoOutputDir, { recursive: true });
102847
103072
  const metadata = await extractMediaMetadata(videoPath);
102848
- const framePattern = `frame_%05d.${format3}`;
102849
- const outputPattern = join8(videoOutputDir, framePattern);
103073
+ const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format3}`;
103074
+ const outputPattern = join9(videoOutputDir, framePattern);
102850
103075
  const isHdr = isHdrColorSpace(metadata.colorSpace);
102851
103076
  const isMacOS = process.platform === "darwin";
102852
103077
  const args = [];
@@ -102894,9 +103119,9 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
102894
103119
  return;
102895
103120
  }
102896
103121
  const framePaths = /* @__PURE__ */ new Map();
102897
- const files = readdirSync4(videoOutputDir).filter((f) => f.startsWith("frame_") && f.endsWith(`.${format3}`)).sort();
103122
+ const files = readdirSync5(videoOutputDir).filter((f) => f.startsWith(FRAME_FILENAME_PREFIX) && f.endsWith(`.${format3}`)).sort();
102898
103123
  files.forEach((file, index) => {
102899
- framePaths.set(index, join8(videoOutputDir, file));
103124
+ framePaths.set(index, join9(videoOutputDir, file));
102900
103125
  });
102901
103126
  resolve14({
102902
103127
  videoId,
@@ -102920,12 +103145,19 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
102920
103145
  });
102921
103146
  });
102922
103147
  }
102923
- async function convertSdrToHdr(inputPath, outputPath, targetTransfer, signal, config2) {
103148
+ async function convertSdrToHdr(inputPath, outputPath, startTime, duration, targetTransfer, signal, config2) {
103149
+ if (duration <= 0) {
103150
+ throw new Error(`convertSdrToHdr: duration must be positive (got ${duration})`);
103151
+ }
102924
103152
  const timeout2 = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
102925
103153
  const colorTrc = targetTransfer === "pq" ? "smpte2084" : "arib-std-b67";
102926
103154
  const args = [
103155
+ "-ss",
103156
+ String(startTime),
102927
103157
  "-i",
102928
103158
  inputPath,
103159
+ "-t",
103160
+ String(duration),
102929
103161
  "-vf",
102930
103162
  "colorspace=all=bt2020:iall=bt709:range=tv",
102931
103163
  "-color_primaries",
@@ -102952,6 +103184,11 @@ async function convertSdrToHdr(inputPath, outputPath, targetTransfer, signal, co
102952
103184
  );
102953
103185
  }
102954
103186
  }
103187
+ function resolveSegmentDuration(requested, mediaStart, metadata) {
103188
+ if (Number.isFinite(requested) && requested > 0) return requested;
103189
+ const sourceRemaining = metadata.durationSeconds - mediaStart;
103190
+ return sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
103191
+ }
102955
103192
  async function convertVfrToCfr(inputPath, outputPath, targetFps, startTime, duration, signal, config2) {
102956
103193
  const timeout2 = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
102957
103194
  const args = [
@@ -102988,21 +103225,34 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
102988
103225
  const extracted = [];
102989
103226
  const errors = [];
102990
103227
  let totalFramesExtracted = 0;
103228
+ const breakdown = {
103229
+ resolveMs: 0,
103230
+ hdrProbeMs: 0,
103231
+ hdrPreflightMs: 0,
103232
+ hdrPreflightCount: 0,
103233
+ vfrProbeMs: 0,
103234
+ vfrPreflightMs: 0,
103235
+ vfrPreflightCount: 0,
103236
+ extractMs: 0,
103237
+ cacheHits: 0,
103238
+ cacheMisses: 0
103239
+ };
103240
+ const phase1Start = Date.now();
102991
103241
  const resolvedVideos = [];
102992
103242
  for (const video of videos) {
102993
103243
  if (signal?.aborted) break;
102994
103244
  try {
102995
103245
  let videoPath = video.src;
102996
103246
  if (!isAbsolute2(videoPath) && !isHttpUrl(videoPath)) {
102997
- const fromCompiled = compiledDir ? join8(compiledDir, videoPath) : null;
102998
- videoPath = fromCompiled && existsSync8(fromCompiled) ? fromCompiled : join8(baseDir, videoPath);
103247
+ const fromCompiled = compiledDir ? join9(compiledDir, videoPath) : null;
103248
+ videoPath = fromCompiled && existsSync9(fromCompiled) ? fromCompiled : join9(baseDir, videoPath);
102999
103249
  }
103000
103250
  if (isHttpUrl(videoPath)) {
103001
- const downloadDir = join8(options.outputDir, "_downloads");
103002
- mkdirSync5(downloadDir, { recursive: true });
103251
+ const downloadDir = join9(options.outputDir, "_downloads");
103252
+ mkdirSync6(downloadDir, { recursive: true });
103003
103253
  videoPath = await downloadToTemp(videoPath, downloadDir);
103004
103254
  }
103005
- if (!existsSync8(videoPath)) {
103255
+ if (!existsSync9(videoPath)) {
103006
103256
  errors.push({ videoId: video.id, error: `Video file not found: ${videoPath}` });
103007
103257
  continue;
103008
103258
  }
@@ -103011,27 +103261,66 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
103011
103261
  errors.push({ videoId: video.id, error: err instanceof Error ? err.message : String(err) });
103012
103262
  }
103013
103263
  }
103014
- const videoColorSpaces = await Promise.all(
103015
- resolvedVideos.map(async ({ videoPath }) => {
103016
- const metadata = await extractMediaMetadata(videoPath);
103017
- return metadata.colorSpace;
103018
- })
103264
+ breakdown.resolveMs = Date.now() - phase1Start;
103265
+ const cacheKeyInputs = resolvedVideos.map(({ video, videoPath }) => {
103266
+ const stat = readKeyStat(videoPath);
103267
+ if (!stat) return null;
103268
+ return {
103269
+ videoPath,
103270
+ mtimeMs: stat.mtimeMs,
103271
+ size: stat.size,
103272
+ mediaStart: video.mediaStart,
103273
+ start: video.start,
103274
+ end: video.end
103275
+ };
103276
+ });
103277
+ const phase2ProbeStart = Date.now();
103278
+ const videoMetadata = await Promise.all(
103279
+ resolvedVideos.map(({ videoPath }) => extractMediaMetadata(videoPath))
103019
103280
  );
103281
+ const videoColorSpaces = videoMetadata.map((m) => m.colorSpace);
103282
+ breakdown.hdrProbeMs = Date.now() - phase2ProbeStart;
103283
+ const hdrPreflightStart = Date.now();
103020
103284
  const hdrInfo = analyzeCompositionHdr(videoColorSpaces);
103285
+ const hdrSkippedIndices = /* @__PURE__ */ new Set();
103021
103286
  if (hdrInfo.hasHdr && hdrInfo.dominantTransfer) {
103022
103287
  const targetTransfer = hdrInfo.dominantTransfer;
103023
- const convertDir = join8(options.outputDir, "_hdr_normalized");
103024
- mkdirSync5(convertDir, { recursive: true });
103288
+ const convertDir = join9(options.outputDir, "_hdr_normalized");
103289
+ mkdirSync6(convertDir, { recursive: true });
103025
103290
  for (let i = 0; i < resolvedVideos.length; i++) {
103026
103291
  if (signal?.aborted) break;
103027
103292
  const cs = videoColorSpaces[i] ?? null;
103028
103293
  if (!isHdrColorSpace(cs)) {
103029
103294
  const entry = resolvedVideos[i];
103030
- if (!entry) continue;
103031
- const convertedPath = join8(convertDir, `${entry.video.id}_hdr.mp4`);
103295
+ const metadata = videoMetadata[i];
103296
+ if (!entry || !metadata) continue;
103297
+ if (entry.video.mediaStart >= metadata.durationSeconds) {
103298
+ errors.push({
103299
+ videoId: entry.video.id,
103300
+ error: `SDR\u2192HDR conversion skipped: mediaStart (${entry.video.mediaStart}s) \u2265 source duration (${metadata.durationSeconds}s)`
103301
+ });
103302
+ hdrSkippedIndices.add(i);
103303
+ continue;
103304
+ }
103305
+ let segDuration = entry.video.end - entry.video.start;
103306
+ if (!Number.isFinite(segDuration) || segDuration <= 0) {
103307
+ const sourceRemaining = metadata.durationSeconds - entry.video.mediaStart;
103308
+ segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
103309
+ }
103310
+ const convertedPath = join9(convertDir, `${entry.video.id}_hdr.mp4`);
103032
103311
  try {
103033
- await convertSdrToHdr(entry.videoPath, convertedPath, targetTransfer, signal, config2);
103312
+ await convertSdrToHdr(
103313
+ entry.videoPath,
103314
+ convertedPath,
103315
+ entry.video.mediaStart,
103316
+ segDuration,
103317
+ targetTransfer,
103318
+ signal,
103319
+ config2
103320
+ );
103034
103321
  entry.videoPath = convertedPath;
103322
+ entry.video = { ...entry.video, mediaStart: 0 };
103323
+ breakdown.hdrPreflightCount += 1;
103035
103324
  } catch (err) {
103036
103325
  errors.push({
103037
103326
  videoId: entry.video.id,
@@ -103041,20 +103330,34 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
103041
103330
  }
103042
103331
  }
103043
103332
  }
103044
- const vfrNormDir = join8(options.outputDir, "_vfr_normalized");
103333
+ breakdown.hdrPreflightMs = Date.now() - hdrPreflightStart;
103334
+ if (hdrSkippedIndices.size > 0) {
103335
+ for (let i = resolvedVideos.length - 1; i >= 0; i--) {
103336
+ if (hdrSkippedIndices.has(i)) {
103337
+ resolvedVideos.splice(i, 1);
103338
+ videoMetadata.splice(i, 1);
103339
+ videoColorSpaces.splice(i, 1);
103340
+ cacheKeyInputs.splice(i, 1);
103341
+ }
103342
+ }
103343
+ }
103344
+ const vfrPreflightStart = Date.now();
103345
+ const vfrNormDir = join9(options.outputDir, "_vfr_normalized");
103045
103346
  for (let i = 0; i < resolvedVideos.length; i++) {
103046
103347
  if (signal?.aborted) break;
103047
103348
  const entry = resolvedVideos[i];
103048
103349
  if (!entry) continue;
103350
+ const vfrProbeStart = Date.now();
103049
103351
  const metadata = await extractMediaMetadata(entry.videoPath);
103352
+ breakdown.vfrProbeMs += Date.now() - vfrProbeStart;
103050
103353
  if (!metadata.isVFR) continue;
103051
103354
  let segDuration = entry.video.end - entry.video.start;
103052
103355
  if (!Number.isFinite(segDuration) || segDuration <= 0) {
103053
103356
  const sourceRemaining = metadata.durationSeconds - entry.video.mediaStart;
103054
103357
  segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
103055
103358
  }
103056
- mkdirSync5(vfrNormDir, { recursive: true });
103057
- const normalizedPath = join8(vfrNormDir, `${entry.video.id}_cfr.mp4`);
103359
+ mkdirSync6(vfrNormDir, { recursive: true });
103360
+ const normalizedPath = join9(vfrNormDir, `${entry.video.id}_cfr.mp4`);
103058
103361
  try {
103059
103362
  await convertVfrToCfr(
103060
103363
  entry.videoPath,
@@ -103067,6 +103370,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
103067
103370
  );
103068
103371
  entry.videoPath = normalizedPath;
103069
103372
  entry.video = { ...entry.video, mediaStart: 0 };
103373
+ breakdown.vfrPreflightCount += 1;
103070
103374
  } catch (err) {
103071
103375
  errors.push({
103072
103376
  videoId: entry.video.id,
@@ -103074,19 +103378,72 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
103074
103378
  });
103075
103379
  }
103076
103380
  }
103381
+ breakdown.vfrPreflightMs = Date.now() - vfrPreflightStart;
103382
+ const phase3Start = Date.now();
103383
+ const cacheRootDir = config2?.extractCacheDir;
103384
+ const cacheFormat = options.format ?? "jpg";
103385
+ async function tryCachedExtract(video, videoPath, videoDuration, i) {
103386
+ if (!cacheRootDir) return null;
103387
+ const keyInput = cacheKeyInputs[i];
103388
+ const probedMeta = videoMetadata[i];
103389
+ if (!keyInput || !probedMeta) return null;
103390
+ const keyDuration = resolveSegmentDuration(
103391
+ keyInput.end - keyInput.start,
103392
+ keyInput.mediaStart,
103393
+ probedMeta
103394
+ );
103395
+ const lookup = lookupCacheEntry(cacheRootDir, {
103396
+ videoPath: keyInput.videoPath,
103397
+ mtimeMs: keyInput.mtimeMs,
103398
+ size: keyInput.size,
103399
+ mediaStart: keyInput.mediaStart,
103400
+ duration: keyDuration,
103401
+ fps: options.fps,
103402
+ format: cacheFormat
103403
+ });
103404
+ if (lookup.hit) {
103405
+ breakdown.cacheHits += 1;
103406
+ const rehydrated = rehydrateCacheEntry(lookup.entry, {
103407
+ videoId: video.id,
103408
+ srcPath: keyInput.videoPath,
103409
+ fps: options.fps,
103410
+ format: cacheFormat,
103411
+ metadata: probedMeta
103412
+ });
103413
+ return { ...rehydrated, ownedByLookup: true };
103414
+ }
103415
+ breakdown.cacheMisses += 1;
103416
+ ensureCacheEntryDir(lookup.entry);
103417
+ const result = await extractVideoFramesRange(
103418
+ videoPath,
103419
+ video.id,
103420
+ video.mediaStart,
103421
+ videoDuration,
103422
+ options,
103423
+ signal,
103424
+ config2,
103425
+ lookup.entry.dir
103426
+ );
103427
+ markCacheEntryComplete(lookup.entry);
103428
+ return { ...result, ownedByLookup: true };
103429
+ }
103077
103430
  const results = await Promise.all(
103078
- resolvedVideos.map(async ({ video, videoPath }) => {
103431
+ resolvedVideos.map(async ({ video, videoPath }, i) => {
103079
103432
  if (signal?.aborted) {
103080
103433
  throw new Error("Video frame extraction cancelled");
103081
103434
  }
103082
103435
  try {
103083
- let videoDuration = video.end - video.start;
103084
- if (!Number.isFinite(videoDuration) || videoDuration <= 0) {
103085
- const metadata = await extractMediaMetadata(videoPath);
103086
- const sourceDuration = metadata.durationSeconds - video.mediaStart;
103087
- videoDuration = sourceDuration > 0 ? sourceDuration : metadata.durationSeconds;
103436
+ const probedMeta = videoMetadata[i] ?? await extractMediaMetadata(videoPath);
103437
+ const videoDuration = resolveSegmentDuration(
103438
+ video.end - video.start,
103439
+ video.mediaStart,
103440
+ probedMeta
103441
+ );
103442
+ if (video.end - video.start !== videoDuration) {
103088
103443
  video.end = video.start + videoDuration;
103089
103444
  }
103445
+ const cached = await tryCachedExtract(video, videoPath, videoDuration, i);
103446
+ if (cached) return { result: cached };
103090
103447
  const result = await extractVideoFramesRange(
103091
103448
  videoPath,
103092
103449
  video.id,
@@ -103107,6 +103464,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
103107
103464
  }
103108
103465
  })
103109
103466
  );
103467
+ breakdown.extractMs = Date.now() - phase3Start;
103110
103468
  for (const item of results) {
103111
103469
  if ("error" in item && item.error) {
103112
103470
  errors.push(item.error);
@@ -103120,7 +103478,8 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
103120
103478
  extracted,
103121
103479
  errors,
103122
103480
  totalFramesExtracted,
103123
- durationMs: Date.now() - startTime
103481
+ durationMs: Date.now() - startTime,
103482
+ phaseBreakdown: breakdown
103124
103483
  };
103125
103484
  }
103126
103485
  function getFrameAtTime(extracted, globalTime, videoStart) {
@@ -103213,7 +103572,8 @@ var FrameLookupTable = class {
103213
103572
  }
103214
103573
  cleanup() {
103215
103574
  for (const video of this.videos.values()) {
103216
- if (existsSync8(video.extracted.outputDir)) {
103575
+ if (video.extracted.ownedByLookup) continue;
103576
+ if (existsSync9(video.extracted.outputDir)) {
103217
103577
  rmSync(video.extracted.outputDir, { recursive: true, force: true });
103218
103578
  }
103219
103579
  }
@@ -103236,23 +103596,23 @@ function createFrameLookupTable(videos, extracted) {
103236
103596
  // ../engine/src/services/videoFrameInjector.ts
103237
103597
  import { promises as fs7 } from "fs";
103238
103598
  function createFrameDataUriCache(cacheLimit) {
103239
- const cache = /* @__PURE__ */ new Map();
103599
+ const cache2 = /* @__PURE__ */ new Map();
103240
103600
  const inFlight = /* @__PURE__ */ new Map();
103241
103601
  function remember(framePath, dataUri) {
103242
- if (cache.has(framePath)) {
103243
- cache.delete(framePath);
103602
+ if (cache2.has(framePath)) {
103603
+ cache2.delete(framePath);
103244
103604
  }
103245
- cache.set(framePath, dataUri);
103246
- if (cache.size > cacheLimit) {
103247
- const oldestKey = cache.keys().next().value;
103605
+ cache2.set(framePath, dataUri);
103606
+ if (cache2.size > cacheLimit) {
103607
+ const oldestKey = cache2.keys().next().value;
103248
103608
  if (oldestKey) {
103249
- cache.delete(oldestKey);
103609
+ cache2.delete(oldestKey);
103250
103610
  }
103251
103611
  }
103252
103612
  return dataUri;
103253
103613
  }
103254
103614
  async function get(framePath) {
103255
- const cached = cache.get(framePath);
103615
+ const cached = cache2.get(framePath);
103256
103616
  if (cached) {
103257
103617
  remember(framePath, cached);
103258
103618
  return cached;
@@ -103456,11 +103816,11 @@ async function queryElementStacking(page, nativeHdrIds) {
103456
103816
  }
103457
103817
 
103458
103818
  // ../engine/src/services/audioMixer.ts
103459
- import { existsSync as existsSync9, mkdirSync as mkdirSync6, rmSync as rmSync2 } from "fs";
103460
- import { isAbsolute as isAbsolute3, join as join9, dirname as dirname7 } from "path";
103819
+ import { existsSync as existsSync10, mkdirSync as mkdirSync7, rmSync as rmSync2 } from "fs";
103820
+ import { isAbsolute as isAbsolute3, join as join10, dirname as dirname7 } from "path";
103461
103821
  function parseAudioElements(html) {
103462
103822
  const elements = [];
103463
- const { document: document2 } = parseHTML(html);
103823
+ const { document: document2 } = parseHTML(unwrapTemplate(html));
103464
103824
  const audioEls = document2.querySelectorAll("audio[id][src]");
103465
103825
  for (const el of audioEls) {
103466
103826
  const id = el.getAttribute("id");
@@ -103508,7 +103868,7 @@ function parseAudioElements(html) {
103508
103868
  async function extractAudioFromVideo(videoPath, outputPath, options, signal, config2) {
103509
103869
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
103510
103870
  const outputDir = dirname7(outputPath);
103511
- if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
103871
+ if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
103512
103872
  const args = ["-i", videoPath];
103513
103873
  if (options?.startTime !== void 0) args.push("-ss", String(options.startTime));
103514
103874
  if (options?.duration !== void 0) args.push("-t", String(options.duration));
@@ -103535,7 +103895,7 @@ async function extractAudioFromVideo(videoPath, outputPath, options, signal, con
103535
103895
  async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, signal, config2) {
103536
103896
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
103537
103897
  const outputDir = dirname7(outputPath);
103538
- if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
103898
+ if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
103539
103899
  const args = [
103540
103900
  "-ss",
103541
103901
  String(mediaStart),
@@ -103571,7 +103931,7 @@ async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, sign
103571
103931
  async function generateSilence(outputPath, duration, signal, config2) {
103572
103932
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
103573
103933
  const outputDir = dirname7(outputPath);
103574
- if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
103934
+ if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
103575
103935
  const args = [
103576
103936
  "-f",
103577
103937
  "lavfi",
@@ -103614,7 +103974,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config2
103614
103974
  };
103615
103975
  }
103616
103976
  const outputDir = dirname7(outputPath);
103617
- if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
103977
+ if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
103618
103978
  const inputs = [];
103619
103979
  const filterParts = [];
103620
103980
  tracks.forEach((track, i) => {
@@ -103675,7 +104035,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
103675
104035
  const startMs = Date.now();
103676
104036
  const tracks = [];
103677
104037
  const errors = [];
103678
- if (!existsSync9(workDir)) mkdirSync6(workDir, { recursive: true });
104038
+ if (!existsSync10(workDir)) mkdirSync7(workDir, { recursive: true });
103679
104039
  await Promise.all(
103680
104040
  elements.map(async (element) => {
103681
104041
  if (signal?.aborted) {
@@ -103685,8 +104045,8 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
103685
104045
  try {
103686
104046
  let srcPath = element.src;
103687
104047
  if (!isAbsolute3(srcPath) && !isHttpUrl(srcPath)) {
103688
- const fromCompiled = compiledDir ? join9(compiledDir, srcPath) : null;
103689
- srcPath = fromCompiled && existsSync9(fromCompiled) ? fromCompiled : join9(baseDir, srcPath);
104048
+ const fromCompiled = compiledDir ? join10(compiledDir, srcPath) : null;
104049
+ srcPath = fromCompiled && existsSync10(fromCompiled) ? fromCompiled : join10(baseDir, srcPath);
103690
104050
  }
103691
104051
  if (isHttpUrl(srcPath)) {
103692
104052
  try {
@@ -103698,7 +104058,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
103698
104058
  return;
103699
104059
  }
103700
104060
  }
103701
- if (!existsSync9(srcPath)) {
104061
+ if (!existsSync10(srcPath)) {
103702
104062
  errors.push(`Source not found: ${element.id} (${element.src})`);
103703
104063
  return;
103704
104064
  }
@@ -103709,7 +104069,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
103709
104069
  }
103710
104070
  let audioSrcPath = srcPath;
103711
104071
  if (element.type === "video") {
103712
- const extractedPath = join9(workDir, `${element.id}-extracted.wav`);
104072
+ const extractedPath = join10(workDir, `${element.id}-extracted.wav`);
103713
104073
  const extractResult = await extractAudioFromVideo(
103714
104074
  srcPath,
103715
104075
  extractedPath,
@@ -103726,7 +104086,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
103726
104086
  }
103727
104087
  audioSrcPath = extractedPath;
103728
104088
  } else {
103729
- const trimmedPath = join9(workDir, `${element.id}-trimmed.wav`);
104089
+ const trimmedPath = join10(workDir, `${element.id}-trimmed.wav`);
103730
104090
  const prepResult = await prepareAudioTrack(
103731
104091
  srcPath,
103732
104092
  trimmedPath,
@@ -103769,9 +104129,9 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
103769
104129
 
103770
104130
  // ../engine/src/services/parallelCoordinator.ts
103771
104131
  import { cpus, freemem, totalmem } from "os";
103772
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, readdirSync as readdirSync5 } from "fs";
104132
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, readdirSync as readdirSync6 } from "fs";
103773
104133
  import { copyFile, rename as rename2 } from "fs/promises";
103774
- import { join as join10 } from "path";
104134
+ import { join as join11 } from "path";
103775
104135
  var MEMORY_PER_WORKER_MB = 256;
103776
104136
  var MIN_WORKERS = 1;
103777
104137
  var ABSOLUTE_MAX_WORKERS = 10;
@@ -103819,7 +104179,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
103819
104179
  workerId: i,
103820
104180
  startFrame,
103821
104181
  endFrame,
103822
- outputDir: join10(workDir, `worker-${i}`)
104182
+ outputDir: join11(workDir, `worker-${i}`)
103823
104183
  });
103824
104184
  }
103825
104185
  return tasks;
@@ -103827,7 +104187,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
103827
104187
  async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCaptureHook, signal, onFrameCaptured, onFrameBuffer, config2) {
103828
104188
  const startTime = Date.now();
103829
104189
  let framesCaptured = 0;
103830
- if (!existsSync10(task.outputDir)) mkdirSync7(task.outputDir, { recursive: true });
104190
+ if (!existsSync11(task.outputDir)) mkdirSync8(task.outputDir, { recursive: true });
103831
104191
  let session = null;
103832
104192
  let perf;
103833
104193
  try {
@@ -103917,17 +104277,17 @@ async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions,
103917
104277
  return results;
103918
104278
  }
103919
104279
  async function mergeWorkerFrames(workDir, tasks, outputDir) {
103920
- if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
104280
+ if (!existsSync11(outputDir)) mkdirSync8(outputDir, { recursive: true });
103921
104281
  let totalFrames = 0;
103922
104282
  const sortedTasks = [...tasks].sort((a, b) => a.startFrame - b.startFrame);
103923
104283
  for (const task of sortedTasks) {
103924
- if (!existsSync10(task.outputDir)) {
104284
+ if (!existsSync11(task.outputDir)) {
103925
104285
  continue;
103926
104286
  }
103927
- const files = readdirSync5(task.outputDir).filter((f) => f.startsWith("frame_") && (f.endsWith(".jpg") || f.endsWith(".png"))).sort();
104287
+ const files = readdirSync6(task.outputDir).filter((f) => f.startsWith("frame_") && (f.endsWith(".jpg") || f.endsWith(".png"))).sort();
103928
104288
  const copyTasks = files.map(async (file) => {
103929
- const sourcePath = join10(task.outputDir, file);
103930
- const targetPath = join10(outputDir, file);
104289
+ const sourcePath = join11(task.outputDir, file);
104290
+ const targetPath = join11(outputDir, file);
103931
104291
  try {
103932
104292
  await rename2(sourcePath, targetPath);
103933
104293
  } catch {
@@ -106214,14 +106574,14 @@ var Response2 = class _Response {
106214
106574
  }
106215
106575
  }
106216
106576
  get headers() {
106217
- const cache = this[cacheKey];
106218
- if (cache) {
106219
- if (!(cache[2] instanceof Headers)) {
106220
- cache[2] = new Headers(
106221
- cache[2] || { "content-type": "text/plain; charset=UTF-8" }
106577
+ const cache2 = this[cacheKey];
106578
+ if (cache2) {
106579
+ if (!(cache2[2] instanceof Headers)) {
106580
+ cache2[2] = new Headers(
106581
+ cache2[2] || { "content-type": "text/plain; charset=UTF-8" }
106222
106582
  );
106223
106583
  }
106224
- return cache[2];
106584
+ return cache2[2];
106225
106585
  }
106226
106586
  return this[getResponseCache]().headers;
106227
106587
  }
@@ -107732,18 +108092,18 @@ var ridgedBurn = (from2, to, out, w, h, p) => {
107732
108092
  TRANSITIONS["ridged-burn"] = ridgedBurn;
107733
108093
 
107734
108094
  // src/services/renderOrchestrator.ts
107735
- import { join as join15, dirname as dirname10, resolve as resolve11 } from "path";
108095
+ import { join as join16, dirname as dirname10, resolve as resolve11 } from "path";
107736
108096
  import { randomUUID } from "crypto";
107737
108097
  import { freemem as freemem2 } from "os";
107738
108098
  import { fileURLToPath as fileURLToPath3 } from "url";
107739
108099
 
107740
108100
  // src/services/fileServer.ts
107741
- import { readFileSync as readFileSync7, existsSync as existsSync12, realpathSync, statSync as statSync5 } from "node:fs";
107742
- import { join as join11, extname as extname4, resolve as resolve8, sep } from "node:path";
108101
+ import { readFileSync as readFileSync7, existsSync as existsSync13, realpathSync, statSync as statSync6 } from "node:fs";
108102
+ import { join as join12, extname as extname4, resolve as resolve8, sep } from "node:path";
107743
108103
 
107744
108104
  // src/services/hyperframeRuntimeLoader.ts
107745
- import { createHash as createHash2 } from "node:crypto";
107746
- import { existsSync as existsSync11, readFileSync as readFileSync6 } from "node:fs";
108105
+ import { createHash as createHash3 } from "node:crypto";
108106
+ import { existsSync as existsSync12, readFileSync as readFileSync6 } from "node:fs";
107747
108107
  import { dirname as dirname8, resolve as resolve7 } from "node:path";
107748
108108
  import { fileURLToPath as fileURLToPath2 } from "node:url";
107749
108109
  var PRODUCER_DIR = dirname8(fileURLToPath2(import.meta.url));
@@ -107770,7 +108130,7 @@ function resolveHyperframeManifestPath() {
107770
108130
  MODULE_RELATIVE_MANIFEST_PATH
107771
108131
  ];
107772
108132
  for (const candidate of candidates) {
107773
- if (existsSync11(candidate)) {
108133
+ if (existsSync12(candidate)) {
107774
108134
  return candidate;
107775
108135
  }
107776
108136
  }
@@ -107781,7 +108141,7 @@ function getVerifiedHyperframeRuntimeSource() {
107781
108141
  }
107782
108142
  function resolveVerifiedHyperframeRuntime() {
107783
108143
  const manifestPath = resolveHyperframeManifestPath();
107784
- if (!existsSync11(manifestPath)) {
108144
+ if (!existsSync12(manifestPath)) {
107785
108145
  throw new Error(
107786
108146
  `[HyperframeRuntimeLoader] Missing manifest at ${manifestPath}. Build core runtime artifacts before rendering.`
107787
108147
  );
@@ -107795,11 +108155,11 @@ function resolveVerifiedHyperframeRuntime() {
107795
108155
  );
107796
108156
  }
107797
108157
  const runtimePath = resolve7(dirname8(manifestPath), runtimeFileName);
107798
- if (!existsSync11(runtimePath)) {
108158
+ if (!existsSync12(runtimePath)) {
107799
108159
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
107800
108160
  }
107801
108161
  const runtimeSource = readFileSync6(runtimePath, "utf8");
107802
- const runtimeSha = createHash2("sha256").update(runtimeSource, "utf8").digest("hex");
108162
+ const runtimeSha = createHash3("sha256").update(runtimeSource, "utf8").digest("hex");
107803
108163
  if (runtimeSha !== manifest.sha256) {
107804
108164
  throw new Error(
107805
108165
  `[HyperframeRuntimeLoader] Runtime checksum mismatch. expected=${manifest.sha256} actual=${runtimeSha}`
@@ -107821,8 +108181,8 @@ function isPathInside(child, parent, options = {}) {
107821
108181
  const separator = pathModule?.sep ?? sep;
107822
108182
  const resolvedChild = resolveFn(child);
107823
108183
  const resolvedParent = resolveFn(parent);
107824
- const normalizedChild = resolveSymlinks && existsSync12(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
107825
- const normalizedParent = resolveSymlinks && existsSync12(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
108184
+ const normalizedChild = resolveSymlinks && existsSync13(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
108185
+ const normalizedParent = resolveSymlinks && existsSync13(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
107826
108186
  if (normalizedChild === normalizedParent) return true;
107827
108187
  const parentWithSep = normalizedParent.endsWith(separator) ? normalizedParent : normalizedParent + separator;
107828
108188
  return normalizedChild.startsWith(parentWithSep);
@@ -108221,14 +108581,14 @@ function createFileServer2(options) {
108221
108581
  const relativePath = requestPath.replace(/^\//, "");
108222
108582
  let filePath = null;
108223
108583
  if (compiledDir) {
108224
- const candidate = join11(compiledDir, relativePath);
108225
- if (existsSync12(candidate) && isPathInside(candidate, compiledDir, { resolveSymlinks: true }) && statSync5(candidate).isFile()) {
108584
+ const candidate = join12(compiledDir, relativePath);
108585
+ if (existsSync13(candidate) && isPathInside(candidate, compiledDir, { resolveSymlinks: true }) && statSync6(candidate).isFile()) {
108226
108586
  filePath = candidate;
108227
108587
  }
108228
108588
  }
108229
108589
  if (!filePath) {
108230
- const candidate = join11(projectDir, relativePath);
108231
- if (existsSync12(candidate) && isPathInside(candidate, projectDir, { resolveSymlinks: true }) && statSync5(candidate).isFile()) {
108590
+ const candidate = join12(projectDir, relativePath);
108591
+ if (existsSync13(candidate) && isPathInside(candidate, projectDir, { resolveSymlinks: true }) && statSync6(candidate).isFile()) {
108232
108592
  filePath = candidate;
108233
108593
  }
108234
108594
  }
@@ -108277,12 +108637,12 @@ function createFileServer2(options) {
108277
108637
  }
108278
108638
 
108279
108639
  // src/services/htmlCompiler.ts
108280
- import { readFileSync as readFileSync9, existsSync as existsSync14, mkdirSync as mkdirSync9 } from "fs";
108281
- import { join as join14, dirname as dirname9, resolve as resolve10 } from "path";
108640
+ import { readFileSync as readFileSync9, existsSync as existsSync15, mkdirSync as mkdirSync10 } from "fs";
108641
+ import { join as join15, dirname as dirname9, resolve as resolve10 } from "path";
108282
108642
  import postcss from "postcss";
108283
108643
 
108284
108644
  // src/utils/paths.ts
108285
- import { resolve as resolve9, basename as basename2, join as join12, relative as relative2, isAbsolute as isAbsolute4 } from "node:path";
108645
+ import { resolve as resolve9, basename as basename2, join as join13, relative as relative2, isAbsolute as isAbsolute4 } from "node:path";
108286
108646
  var DEFAULT_RENDERS_DIR = process.env.PRODUCER_RENDERS_DIR ?? resolve9(new URL(import.meta.url).pathname, "../../..", "renders");
108287
108647
  function isPathInside2(childPath, parentPath) {
108288
108648
  const absChild = resolve9(childPath);
@@ -108304,15 +108664,15 @@ function toExternalAssetKey(absPath) {
108304
108664
  function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
108305
108665
  const absoluteProjectDir = resolve9(projectDir);
108306
108666
  const projectName = basename2(absoluteProjectDir);
108307
- const resolvedOutputPath = outputPath ?? join12(rendersDir, `${projectName}.mp4`);
108667
+ const resolvedOutputPath = outputPath ?? join13(rendersDir, `${projectName}.mp4`);
108308
108668
  const absoluteOutputPath = resolve9(resolvedOutputPath);
108309
108669
  return { absoluteProjectDir, absoluteOutputPath };
108310
108670
  }
108311
108671
 
108312
108672
  // src/services/deterministicFonts.ts
108313
- import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "node:fs";
108673
+ import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "node:fs";
108314
108674
  import { homedir as homedir2 } from "node:os";
108315
- import { join as join13 } from "node:path";
108675
+ import { join as join14 } from "node:path";
108316
108676
 
108317
108677
  // src/services/fontData.generated.ts
108318
108678
  var EMBEDDED_FONT_DATA = /* @__PURE__ */ new Map([
@@ -108590,20 +108950,20 @@ function warnUnresolvedFonts(unresolved) {
108590
108950
  Docs: https://hyperframes.heygen.com/docs/fonts`
108591
108951
  );
108592
108952
  }
108593
- var GOOGLE_FONTS_CACHE_DIR = join13(homedir2(), ".cache", "hyperframes", "fonts");
108953
+ var GOOGLE_FONTS_CACHE_DIR = join14(homedir2(), ".cache", "hyperframes", "fonts");
108594
108954
  var WOFF2_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
108595
108955
  function fontSlug(familyName) {
108596
108956
  return familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
108597
108957
  }
108598
108958
  function fontCacheDir(slug) {
108599
- const dir = join13(GOOGLE_FONTS_CACHE_DIR, slug);
108600
- if (!existsSync13(dir)) {
108601
- mkdirSync8(dir, { recursive: true });
108959
+ const dir = join14(GOOGLE_FONTS_CACHE_DIR, slug);
108960
+ if (!existsSync14(dir)) {
108961
+ mkdirSync9(dir, { recursive: true });
108602
108962
  }
108603
108963
  return dir;
108604
108964
  }
108605
108965
  function cachedWoff2Path(slug, weight, style) {
108606
- return join13(fontCacheDir(slug), `${weight}-${style}.woff2`);
108966
+ return join14(fontCacheDir(slug), `${weight}-${style}.woff2`);
108607
108967
  }
108608
108968
  async function fetchGoogleFont(familyName) {
108609
108969
  const slug = fontSlug(familyName);
@@ -108629,12 +108989,12 @@ async function fetchGoogleFont(familyName) {
108629
108989
  const woff2Url = match2[3] || "";
108630
108990
  if (!woff2Url) continue;
108631
108991
  const cachePath = cachedWoff2Path(slug, weight, style);
108632
- if (!existsSync13(cachePath)) {
108992
+ if (!existsSync14(cachePath)) {
108633
108993
  try {
108634
108994
  const fontRes = await fetch(woff2Url);
108635
108995
  if (!fontRes.ok) continue;
108636
108996
  const buffer = Buffer.from(await fontRes.arrayBuffer());
108637
- writeFileSync3(cachePath, buffer);
108997
+ writeFileSync4(cachePath, buffer);
108638
108998
  } catch {
108639
108999
  continue;
108640
109000
  }
@@ -108740,16 +109100,16 @@ function detectRenderModeHints(html) {
108740
109100
  async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagName19) {
108741
109101
  let filePath = src;
108742
109102
  if (isHttpUrl(src)) {
108743
- if (!existsSync14(downloadDir)) mkdirSync9(downloadDir, { recursive: true });
109103
+ if (!existsSync15(downloadDir)) mkdirSync10(downloadDir, { recursive: true });
108744
109104
  try {
108745
109105
  filePath = await downloadToTemp(src, downloadDir);
108746
109106
  } catch {
108747
109107
  return { duration: 0, resolvedPath: src };
108748
109108
  }
108749
109109
  } else if (!filePath.startsWith("/")) {
108750
- filePath = join14(baseDir, filePath);
109110
+ filePath = join15(baseDir, filePath);
108751
109111
  }
108752
- if (!existsSync14(filePath)) {
109112
+ if (!existsSync15(filePath)) {
108753
109113
  return { duration: 0, resolvedPath: filePath };
108754
109114
  }
108755
109115
  const metadata = tagName19 === "video" ? await extractMediaMetadata(filePath) : await extractAudioMetadata(filePath);
@@ -108818,7 +109178,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
108818
109178
  if (visited.has(filePath)) {
108819
109179
  continue;
108820
109180
  }
108821
- if (!existsSync14(filePath)) {
109181
+ if (!existsSync15(filePath)) {
108822
109182
  continue;
108823
109183
  }
108824
109184
  const rawSubHtml = readFileSync9(filePath, "utf-8");
@@ -109028,7 +109388,7 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
109028
109388
  let compHtml = subCompositions.get(srcPath) || null;
109029
109389
  if (!compHtml) {
109030
109390
  const filePath = resolve10(projectDir, srcPath);
109031
- if (existsSync14(filePath)) {
109391
+ if (existsSync15(filePath)) {
109032
109392
  compHtml = readFileSync9(filePath, "utf-8");
109033
109393
  }
109034
109394
  }
@@ -109256,7 +109616,7 @@ function collectExternalAssets(html, projectDir) {
109256
109616
  if (isPathInside2(absPath, absProjectDir)) {
109257
109617
  return null;
109258
109618
  }
109259
- if (!existsSync14(absPath)) return null;
109619
+ if (!existsSync15(absPath)) return null;
109260
109620
  const safeKey = toExternalAssetKey(absPath);
109261
109621
  externalAssets.set(safeKey, absPath);
109262
109622
  return safeKey;
@@ -109452,9 +109812,10 @@ async function recompileWithResolutions(compiled, resolutions, projectDir, downl
109452
109812
  const mainVideos = parseVideoElements(html);
109453
109813
  const mainAudios = parseAudioElements(html);
109454
109814
  const mainImages = parseImageElements(html);
109455
- const videos = dedupeElementsById([...mainVideos, ...subVideos]);
109456
- const audios = dedupeElementsById([...mainAudios, ...subAudios]);
109457
- const images = dedupeElementsById([...mainImages, ...subImages]);
109815
+ const hasSubMedia = subVideos.length > 0 || subAudios.length > 0 || subImages.length > 0;
109816
+ const videos = hasSubMedia ? dedupeElementsById([...mainVideos, ...subVideos]) : compiled.videos;
109817
+ const audios = hasSubMedia ? dedupeElementsById([...mainAudios, ...subAudios]) : compiled.audios;
109818
+ const images = hasSubMedia ? dedupeElementsById([...mainImages, ...subImages]) : compiled.images;
109458
109819
  const remaining = compiled.unresolvedCompositions.filter(
109459
109820
  (c) => !resolutions.some((r) => r.id === c.id)
109460
109821
  );
@@ -109509,24 +109870,21 @@ function createConsoleLogger(level = "info") {
109509
109870
  }
109510
109871
  var defaultLogger = createConsoleLogger("info");
109511
109872
 
109512
- // src/services/renderOrchestrator.ts
109513
- async function safeCleanup(label, fn, log = defaultLogger) {
109514
- try {
109515
- await fn();
109516
- } catch (err) {
109517
- log.debug(`Cleanup failed (${label})`, {
109518
- error: err instanceof Error ? err.message : String(err)
109519
- });
109520
- }
109521
- }
109522
- var frameDirMaxIndexCache = /* @__PURE__ */ new Map();
109873
+ // src/services/frameDirCache.ts
109874
+ import { readdirSync as readdirSync7 } from "fs";
109875
+ var cache = /* @__PURE__ */ new Map();
109523
109876
  var FRAME_FILENAME_RE = /^frame_(\d+)\.png$/;
109877
+ var MAX_ENTRIES = 1e3;
109524
109878
  function getMaxFrameIndex(frameDir) {
109525
- const cached = frameDirMaxIndexCache.get(frameDir);
109526
- if (cached !== void 0) return cached;
109879
+ const cached = cache.get(frameDir);
109880
+ if (cached !== void 0) {
109881
+ cache.delete(frameDir);
109882
+ cache.set(frameDir, cached);
109883
+ return cached;
109884
+ }
109527
109885
  let max = 0;
109528
109886
  try {
109529
- for (const name of readdirSync6(frameDir)) {
109887
+ for (const name of readdirSync7(frameDir)) {
109530
109888
  const m = FRAME_FILENAME_RE.exec(name);
109531
109889
  if (!m) continue;
109532
109890
  const n = Number(m[1]);
@@ -109534,9 +109892,113 @@ function getMaxFrameIndex(frameDir) {
109534
109892
  }
109535
109893
  } catch {
109536
109894
  }
109537
- frameDirMaxIndexCache.set(frameDir, max);
109895
+ if (cache.size >= MAX_ENTRIES) {
109896
+ const oldest = cache.keys().next().value;
109897
+ if (oldest !== void 0) cache.delete(oldest);
109898
+ }
109899
+ cache.set(frameDir, max);
109538
109900
  return max;
109539
109901
  }
109902
+ function clearMaxFrameIndex(frameDir) {
109903
+ return cache.delete(frameDir);
109904
+ }
109905
+
109906
+ // src/services/hdrImageTransferCache.ts
109907
+ var DEFAULT_MAX_BYTES = 200 * 1024 * 1024;
109908
+ function createHdrImageTransferCache(options = {}) {
109909
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
109910
+ if (!Number.isInteger(maxBytes) || maxBytes < 0) {
109911
+ throw new Error(
109912
+ `createHdrImageTransferCache: maxBytes must be a non-negative integer, got ${String(maxBytes)}`
109913
+ );
109914
+ }
109915
+ const entries2 = /* @__PURE__ */ new Map();
109916
+ let totalBytes = 0;
109917
+ function makeKey(imageId, targetTransfer) {
109918
+ return `${imageId}|${targetTransfer}`;
109919
+ }
109920
+ function evictUntilRoom(needed) {
109921
+ while (totalBytes + needed > maxBytes && entries2.size > 0) {
109922
+ const lruKey = entries2.keys().next().value;
109923
+ if (lruKey === void 0) break;
109924
+ const evicted = entries2.get(lruKey);
109925
+ if (evicted) totalBytes -= evicted.byteLength;
109926
+ entries2.delete(lruKey);
109927
+ }
109928
+ }
109929
+ return {
109930
+ getConverted(imageId, sourceTransfer, targetTransfer, source2) {
109931
+ if (sourceTransfer === targetTransfer) {
109932
+ return source2;
109933
+ }
109934
+ if (maxBytes === 0) {
109935
+ const fresh = Buffer.from(source2);
109936
+ convertTransfer(fresh, sourceTransfer, targetTransfer);
109937
+ return fresh;
109938
+ }
109939
+ const key2 = makeKey(imageId, targetTransfer);
109940
+ const existing = entries2.get(key2);
109941
+ if (existing) {
109942
+ entries2.delete(key2);
109943
+ entries2.set(key2, existing);
109944
+ return existing;
109945
+ }
109946
+ const converted = Buffer.from(source2);
109947
+ convertTransfer(converted, sourceTransfer, targetTransfer);
109948
+ if (converted.byteLength > maxBytes) {
109949
+ return converted;
109950
+ }
109951
+ evictUntilRoom(converted.byteLength);
109952
+ entries2.set(key2, converted);
109953
+ totalBytes += converted.byteLength;
109954
+ return converted;
109955
+ },
109956
+ size() {
109957
+ return entries2.size;
109958
+ },
109959
+ bytesUsed() {
109960
+ return totalBytes;
109961
+ }
109962
+ };
109963
+ }
109964
+
109965
+ // src/services/renderOrchestrator.ts
109966
+ async function safeCleanup(label, fn, log = defaultLogger) {
109967
+ try {
109968
+ await fn();
109969
+ } catch (err) {
109970
+ log.debug(`Cleanup failed (${label})`, {
109971
+ error: err instanceof Error ? err.message : String(err)
109972
+ });
109973
+ }
109974
+ }
109975
+ function sampleDirectoryBytes(dir) {
109976
+ let total = 0;
109977
+ const stack = [dir];
109978
+ while (stack.length > 0) {
109979
+ const current = stack.pop();
109980
+ if (!current) continue;
109981
+ let entries2 = [];
109982
+ try {
109983
+ entries2 = readdirSync8(current);
109984
+ } catch {
109985
+ continue;
109986
+ }
109987
+ for (const name of entries2) {
109988
+ const full = join16(current, name);
109989
+ try {
109990
+ const st = statSync7(full);
109991
+ if (st.isDirectory()) {
109992
+ stack.push(full);
109993
+ } else if (st.isFile()) {
109994
+ total += st.size;
109995
+ }
109996
+ } catch {
109997
+ }
109998
+ }
109999
+ }
110000
+ return total;
110001
+ }
109540
110002
  function countNonZeroAlpha(rgba) {
109541
110003
  let n = 0;
109542
110004
  for (let p = 3; p < rgba.length; p += 4) {
@@ -109560,6 +110022,10 @@ var RenderCancelledError = class extends Error {
109560
110022
  this.reason = reason;
109561
110023
  }
109562
110024
  };
110025
+ var BROWSER_MEDIA_EPSILON = 1e-4;
110026
+ function projectBrowserEndToCompositionTimeline(existingStart, browserStart, browserEnd) {
110027
+ return browserEnd + (existingStart - browserStart);
110028
+ }
109563
110029
  function updateJobStatus(job, status, stage, progress, onProgress) {
109564
110030
  job.status = status;
109565
110031
  job.currentStage = stage;
@@ -109603,21 +110069,21 @@ function installDebugLogger(logPath, log = defaultLogger) {
109603
110069
  };
109604
110070
  }
109605
110071
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
109606
- const compileDir = join15(workDir, "compiled");
109607
- mkdirSync10(compileDir, { recursive: true });
109608
- writeFileSync4(join15(compileDir, "index.html"), compiled.html, "utf-8");
110072
+ const compileDir = join16(workDir, "compiled");
110073
+ mkdirSync11(compileDir, { recursive: true });
110074
+ writeFileSync5(join16(compileDir, "index.html"), compiled.html, "utf-8");
109609
110075
  for (const [srcPath, html] of compiled.subCompositions) {
109610
- const outPath = join15(compileDir, srcPath);
109611
- mkdirSync10(dirname10(outPath), { recursive: true });
109612
- writeFileSync4(outPath, html, "utf-8");
110076
+ const outPath = join16(compileDir, srcPath);
110077
+ mkdirSync11(dirname10(outPath), { recursive: true });
110078
+ writeFileSync5(outPath, html, "utf-8");
109613
110079
  }
109614
110080
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
109615
- const outPath = resolve11(join15(compileDir, relativePath));
110081
+ const outPath = resolve11(join16(compileDir, relativePath));
109616
110082
  if (!isPathInside2(outPath, compileDir)) {
109617
110083
  console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
109618
110084
  continue;
109619
110085
  }
109620
- mkdirSync10(dirname10(outPath), { recursive: true });
110086
+ mkdirSync11(dirname10(outPath), { recursive: true });
109621
110087
  copyFileSync2(absolutePath, outPath);
109622
110088
  }
109623
110089
  if (includeSummary) {
@@ -109642,7 +110108,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
109642
110108
  subCompositions: Array.from(compiled.subCompositions.keys()),
109643
110109
  renderModeHints: compiled.renderModeHints
109644
110110
  };
109645
- writeFileSync4(join15(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
110111
+ writeFileSync5(join16(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
109646
110112
  }
109647
110113
  }
109648
110114
  function applyRenderModeHints(cfg, compiled, log = defaultLogger) {
@@ -109663,8 +110129,8 @@ function blitHdrVideoLayer(canvas, el, time, fps, hdrFrameDirs, hdrStartTimes, w
109663
110129
  if (videoFrameIndex < 1) return;
109664
110130
  const maxIndex = getMaxFrameIndex(frameDir);
109665
110131
  const effectiveIndex = maxIndex > 0 ? Math.min(videoFrameIndex, maxIndex) : videoFrameIndex;
109666
- const framePath = join15(frameDir, `frame_${String(effectiveIndex).padStart(4, "0")}.png`);
109667
- if (!existsSync15(framePath)) {
110132
+ const framePath = join16(frameDir, `frame_${String(effectiveIndex).padStart(4, "0")}.png`);
110133
+ if (!existsSync16(framePath)) {
109668
110134
  return;
109669
110135
  }
109670
110136
  try {
@@ -109710,17 +110176,13 @@ function blitHdrVideoLayer(canvas, el, time, fps, hdrFrameDirs, hdrStartTimes, w
109710
110176
  }
109711
110177
  }
109712
110178
  }
109713
- function blitHdrImageLayer(canvas, el, hdrImageBuffers, width, height, log, sourceTransfer, targetTransfer) {
110179
+ function blitHdrImageLayer(canvas, el, hdrImageBuffers, hdrImageTransferCache, width, height, log, sourceTransfer, targetTransfer) {
109714
110180
  const buf = hdrImageBuffers.get(el.id);
109715
110181
  if (!buf) {
109716
110182
  return;
109717
110183
  }
109718
110184
  try {
109719
- let hdrRgb = buf.data;
109720
- if (sourceTransfer && targetTransfer && sourceTransfer !== targetTransfer) {
109721
- hdrRgb = Buffer.from(buf.data);
109722
- convertTransfer(hdrRgb, sourceTransfer, targetTransfer);
109723
- }
110185
+ const hdrRgb = sourceTransfer && targetTransfer ? hdrImageTransferCache.getConverted(el.id, sourceTransfer, targetTransfer, buf.data) : buf.data;
109724
110186
  const viewportMatrix = parseTransformMatrix(el.transform);
109725
110187
  const br = el.borderRadius;
109726
110188
  const hasBorderRadius = br[0] > 0 || br[1] > 0 || br[2] > 0 || br[3] > 0;
@@ -109770,6 +110232,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
109770
110232
  effectiveHdr,
109771
110233
  nativeHdrImageIds,
109772
110234
  hdrImageBuffers,
110235
+ hdrImageTransferCache,
109773
110236
  hdrFrameDirs,
109774
110237
  hdrVideoStartTimes,
109775
110238
  imageTransfers,
@@ -109809,6 +110272,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
109809
110272
  canvas,
109810
110273
  layer.element,
109811
110274
  hdrImageBuffers,
110275
+ hdrImageTransferCache,
109812
110276
  width,
109813
110277
  height,
109814
110278
  log,
@@ -109849,7 +110313,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
109849
110313
  const startTime = hdrVideoStartTimes.get(layer.element.id) ?? 0;
109850
110314
  const localTime = time - startTime;
109851
110315
  const frameNum = Math.floor(localTime * fps) + 1;
109852
- const expectedFrame = frameDir ? join15(frameDir, `frame_${String(frameNum).padStart(4, "0")}.png`) : null;
110316
+ const expectedFrame = frameDir ? join16(frameDir, `frame_${String(frameNum).padStart(4, "0")}.png`) : null;
109853
110317
  log.info("[diag] hdr layer blit", {
109854
110318
  frame: debugFrameIndex,
109855
110319
  layerIdx,
@@ -109861,7 +110325,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
109861
110325
  localTime: localTime.toFixed(3),
109862
110326
  hdrFrameNum: frameNum,
109863
110327
  expectedFrame,
109864
- expectedFrameExists: expectedFrame ? existsSync15(expectedFrame) : false
110328
+ expectedFrameExists: expectedFrame ? existsSync16(expectedFrame) : false
109865
110329
  });
109866
110330
  }
109867
110331
  }
@@ -109886,8 +110350,8 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
109886
110350
  if (shouldLog && debugDumpDir) {
109887
110351
  const after2 = countNonZeroRgb48(canvas);
109888
110352
  const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
109889
- const dumpPath = join15(debugDumpDir, dumpName);
109890
- writeFileSync4(dumpPath, domPng);
110353
+ const dumpPath = join16(debugDumpDir, dumpName);
110354
+ writeFileSync5(dumpPath, domPng);
109891
110355
  log.info("[diag] dom layer blit", {
109892
110356
  frame: debugFrameIndex,
109893
110357
  layerIdx,
@@ -109960,8 +110424,8 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
109960
110424
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
109961
110425
  const moduleDir = dirname10(fileURLToPath3(import.meta.url));
109962
110426
  const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve11(process.env.PRODUCER_RENDERS_DIR, "..") : resolve11(moduleDir, "../..");
109963
- const debugDir = join15(producerRoot, ".debug");
109964
- const workDir = job.config.debug ? join15(debugDir, job.id) : join15(dirname10(outputPath), `work-${job.id}`);
110427
+ const debugDir = join16(producerRoot, ".debug");
110428
+ const workDir = job.config.debug ? join16(debugDir, job.id) : join16(dirname10(outputPath), `work-${job.id}`);
109965
110429
  const pipelineStart = Date.now();
109966
110430
  const log = job.config.logger ?? defaultLogger;
109967
110431
  let fileServer = null;
@@ -109973,7 +110437,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
109973
110437
  videoExtractionFailures: 0,
109974
110438
  imageDecodeFailures: 0
109975
110439
  };
109976
- const perfOutputPath = join15(workDir, "perf-summary.json");
110440
+ const perfOutputPath = join16(workDir, "perf-summary.json");
109977
110441
  const cfg = { ...job.config.producerConfig ?? resolveConfig() };
109978
110442
  const outputFormat = job.config.format ?? "mp4";
109979
110443
  const isWebm = outputFormat === "webm";
@@ -110006,22 +110470,22 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110006
110470
  };
110007
110471
  job.startedAt = /* @__PURE__ */ new Date();
110008
110472
  assertNotAborted();
110009
- if (!existsSync15(workDir)) mkdirSync10(workDir, { recursive: true });
110473
+ if (!existsSync16(workDir)) mkdirSync11(workDir, { recursive: true });
110010
110474
  if (job.config.debug) {
110011
- const logPath = join15(workDir, "render.log");
110475
+ const logPath = join16(workDir, "render.log");
110012
110476
  restoreLogger = installDebugLogger(logPath, log);
110013
110477
  }
110014
110478
  const entryFile = job.config.entryFile || "index.html";
110015
- let htmlPath = join15(projectDir, entryFile);
110016
- if (!existsSync15(htmlPath)) {
110479
+ let htmlPath = join16(projectDir, entryFile);
110480
+ if (!existsSync16(htmlPath)) {
110017
110481
  throw new Error(`Entry file not found: ${htmlPath}`);
110018
110482
  }
110019
110483
  assertNotAborted();
110020
110484
  const rawEntry = readFileSync10(htmlPath, "utf-8");
110021
110485
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
110022
- const wrapperPath = join15(workDir, "standalone-entry.html");
110023
- const projectIndexPath = join15(projectDir, "index.html");
110024
- if (!existsSync15(projectIndexPath)) {
110486
+ const wrapperPath = join16(workDir, "standalone-entry.html");
110487
+ const projectIndexPath = join16(projectDir, "index.html");
110488
+ if (!existsSync16(projectIndexPath)) {
110025
110489
  throw new Error(
110026
110490
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
110027
110491
  );
@@ -110035,7 +110499,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110035
110499
  `Entry file "${entryFile}" is not mounted from index.html via data-composition-src, so it cannot be rendered independently.`
110036
110500
  );
110037
110501
  }
110038
- writeFileSync4(wrapperPath, standaloneHtml, "utf-8");
110502
+ writeFileSync5(wrapperPath, standaloneHtml, "utf-8");
110039
110503
  htmlPath = wrapperPath;
110040
110504
  log.info("Extracted standalone entry from index.html host context", {
110041
110505
  entryFile
@@ -110044,7 +110508,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110044
110508
  const stage1Start = Date.now();
110045
110509
  updateJobStatus(job, "preprocessing", "Compiling composition", 5, onProgress);
110046
110510
  const compileStart = Date.now();
110047
- let compiled = await compileForRender(projectDir, htmlPath, join15(workDir, "downloads"));
110511
+ let compiled = await compileForRender(projectDir, htmlPath, join16(workDir, "downloads"));
110048
110512
  assertNotAborted();
110049
110513
  perfStages.compileOnlyMs = Date.now() - compileStart;
110050
110514
  applyRenderModeHints(cfg, compiled, log);
@@ -110076,7 +110540,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110076
110540
  reasons.push(`${compiled.unresolvedCompositions.length} unresolved composition(s)`);
110077
110541
  fileServer = await createFileServer2({
110078
110542
  projectDir,
110079
- compiledDir: join15(workDir, "compiled"),
110543
+ compiledDir: join16(workDir, "compiled"),
110080
110544
  port: 0,
110081
110545
  preHeadScripts: [VIRTUAL_TIME_SHIM]
110082
110546
  });
@@ -110090,7 +110554,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110090
110554
  };
110091
110555
  probeSession = await createCaptureSession(
110092
110556
  fileServer.url,
110093
- join15(workDir, "probe"),
110557
+ join16(workDir, "probe"),
110094
110558
  captureOpts,
110095
110559
  null,
110096
110560
  cfg
@@ -110122,7 +110586,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110122
110586
  compiled,
110123
110587
  resolutions,
110124
110588
  projectDir,
110125
- join15(workDir, "downloads")
110589
+ join16(workDir, "downloads")
110126
110590
  );
110127
110591
  assertNotAborted();
110128
110592
  composition.videos = compiled.videos;
@@ -110149,10 +110613,15 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110149
110613
  if (existing.src !== src) {
110150
110614
  existing.src = src;
110151
110615
  }
110152
- if (el.end > 0 && (existing.end <= 0 || Math.abs(existing.end - el.end) > 1e-4)) {
110153
- existing.end = el.end;
110616
+ const projectedEnd = projectBrowserEndToCompositionTimeline(
110617
+ existing.start,
110618
+ el.start,
110619
+ el.end
110620
+ );
110621
+ if (projectedEnd > 0 && (existing.end <= 0 || Math.abs(existing.end - projectedEnd) > BROWSER_MEDIA_EPSILON)) {
110622
+ existing.end = projectedEnd;
110154
110623
  }
110155
- if (el.mediaStart > 0 && (existing.mediaStart <= 0 || Math.abs(existing.mediaStart - el.mediaStart) > 1e-4)) {
110624
+ if (el.mediaStart > 0 && (existing.mediaStart <= 0 || Math.abs(existing.mediaStart - el.mediaStart) > BROWSER_MEDIA_EPSILON)) {
110156
110625
  existing.mediaStart = el.mediaStart;
110157
110626
  }
110158
110627
  if (el.hasAudio && !existing.hasAudio) {
@@ -110177,13 +110646,18 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110177
110646
  if (existing.src !== src) {
110178
110647
  existing.src = src;
110179
110648
  }
110180
- if (el.end > 0 && (existing.end <= 0 || Math.abs(existing.end - el.end) > 1e-4)) {
110181
- existing.end = el.end;
110649
+ const projectedEnd = projectBrowserEndToCompositionTimeline(
110650
+ existing.start,
110651
+ el.start,
110652
+ el.end
110653
+ );
110654
+ if (projectedEnd > 0 && (existing.end <= 0 || Math.abs(existing.end - projectedEnd) > BROWSER_MEDIA_EPSILON)) {
110655
+ existing.end = projectedEnd;
110182
110656
  }
110183
- if (el.mediaStart > 0 && (existing.mediaStart <= 0 || Math.abs(existing.mediaStart - el.mediaStart) > 1e-4)) {
110657
+ if (el.mediaStart > 0 && (existing.mediaStart <= 0 || Math.abs(existing.mediaStart - el.mediaStart) > BROWSER_MEDIA_EPSILON)) {
110184
110658
  existing.mediaStart = el.mediaStart;
110185
110659
  }
110186
- if (el.volume > 0 && Math.abs((existing.volume ?? 1) - el.volume) > 1e-4) {
110660
+ if (el.volume > 0 && Math.abs((existing.volume ?? 1) - el.volume) > BROWSER_MEDIA_EPSILON) {
110187
110661
  existing.volume = el.volume;
110188
110662
  }
110189
110663
  }
@@ -110262,7 +110736,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110262
110736
  const stage2Start = Date.now();
110263
110737
  updateJobStatus(job, "preprocessing", "Extracting video frames", 10, onProgress);
110264
110738
  let frameLookup = null;
110265
- const compiledDir = join15(workDir, "compiled");
110739
+ const compiledDir = join16(workDir, "compiled");
110266
110740
  let extractionResult = null;
110267
110741
  const nativeHdrVideoIds = /* @__PURE__ */ new Set();
110268
110742
  const videoTransfers = /* @__PURE__ */ new Map();
@@ -110271,10 +110745,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110271
110745
  composition.videos.map(async (v) => {
110272
110746
  let videoPath = v.src;
110273
110747
  if (!videoPath.startsWith("/")) {
110274
- const fromCompiled = existsSync15(join15(compiledDir, videoPath)) ? join15(compiledDir, videoPath) : join15(projectDir, videoPath);
110748
+ const fromCompiled = existsSync16(join16(compiledDir, videoPath)) ? join16(compiledDir, videoPath) : join16(projectDir, videoPath);
110275
110749
  videoPath = fromCompiled;
110276
110750
  }
110277
- if (!existsSync15(videoPath)) return;
110751
+ if (!existsSync16(videoPath)) return;
110278
110752
  const meta = await extractMediaMetadata(videoPath);
110279
110753
  if (isHdrColorSpace(meta.colorSpace)) {
110280
110754
  nativeHdrVideoIds.add(v.id);
@@ -110292,10 +110766,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110292
110766
  composition.images.map(async (img) => {
110293
110767
  let imgPath = img.src;
110294
110768
  if (!imgPath.startsWith("/")) {
110295
- const fromCompiled = existsSync15(join15(compiledDir, imgPath)) ? join15(compiledDir, imgPath) : join15(projectDir, imgPath);
110769
+ const fromCompiled = existsSync16(join16(compiledDir, imgPath)) ? join16(compiledDir, imgPath) : join16(projectDir, imgPath);
110296
110770
  imgPath = fromCompiled;
110297
110771
  }
110298
- if (!existsSync15(imgPath)) return null;
110772
+ if (!existsSync16(imgPath)) return null;
110299
110773
  const meta = await extractMediaMetadata(imgPath);
110300
110774
  if (isHdrColorSpace(meta.colorSpace)) {
110301
110775
  nativeHdrImageIds.add(img.id);
@@ -110311,9 +110785,9 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110311
110785
  extractionResult = await extractAllVideoFrames(
110312
110786
  composition.videos,
110313
110787
  projectDir,
110314
- { fps: job.config.fps, outputDir: join15(workDir, "video-frames") },
110788
+ { fps: job.config.fps, outputDir: join16(workDir, "video-frames") },
110315
110789
  abortSignal,
110316
- void 0,
110790
+ { extractCacheDir: cfg.extractCacheDir },
110317
110791
  compiledDir
110318
110792
  );
110319
110793
  assertNotAborted();
@@ -110369,13 +110843,13 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110369
110843
  }
110370
110844
  const stage3Start = Date.now();
110371
110845
  updateJobStatus(job, "preprocessing", "Processing audio tracks", 20, onProgress);
110372
- const audioOutputPath = join15(workDir, "audio.aac");
110846
+ const audioOutputPath = join16(workDir, "audio.aac");
110373
110847
  let hasAudio = false;
110374
110848
  if (composition.audios.length > 0) {
110375
110849
  const audioResult = await processCompositionAudio(
110376
110850
  composition.audios,
110377
110851
  projectDir,
110378
- join15(workDir, "audio-work"),
110852
+ join16(workDir, "audio-work"),
110379
110853
  audioOutputPath,
110380
110854
  job.duration,
110381
110855
  abortSignal,
@@ -110393,14 +110867,14 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110393
110867
  if (!fileServer) {
110394
110868
  fileServer = await createFileServer2({
110395
110869
  projectDir,
110396
- compiledDir: join15(workDir, "compiled"),
110870
+ compiledDir: join16(workDir, "compiled"),
110397
110871
  port: 0,
110398
110872
  preHeadScripts: [VIRTUAL_TIME_SHIM]
110399
110873
  });
110400
110874
  assertNotAborted();
110401
110875
  }
110402
- const framesDir = join15(workDir, "captured-frames");
110403
- if (!existsSync15(framesDir)) mkdirSync10(framesDir, { recursive: true });
110876
+ const framesDir = join16(workDir, "captured-frames");
110877
+ if (!existsSync16(framesDir)) mkdirSync11(framesDir, { recursive: true });
110404
110878
  const captureOptions = {
110405
110879
  width,
110406
110880
  height,
@@ -110415,7 +110889,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110415
110889
  const workerCount = calculateOptimalWorkers(totalFrames, job.config.workers, cfg);
110416
110890
  const FORMAT_EXT = { mp4: ".mp4", webm: ".webm", mov: ".mov" };
110417
110891
  const videoExt = FORMAT_EXT[outputFormat] ?? ".mp4";
110418
- const videoOnlyPath = join15(workDir, `video-only${videoExt}`);
110892
+ const videoOnlyPath = join16(workDir, `video-only${videoExt}`);
110419
110893
  const nativeHdrIds = /* @__PURE__ */ new Set([...nativeHdrVideoIds, ...nativeHdrImageIds]);
110420
110894
  const hasHdrContent = effectiveHdr && nativeHdrIds.size > 0;
110421
110895
  const encoderHdr = hasHdrContent ? effectiveHdr : void 0;
@@ -110437,8 +110911,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110437
110911
  if (!hdrVideoIds.includes(v.id)) continue;
110438
110912
  let srcPath = v.src;
110439
110913
  if (!srcPath.startsWith("/")) {
110440
- const fromCompiled = join15(compiledDir, srcPath);
110441
- srcPath = existsSync15(fromCompiled) ? fromCompiled : join15(projectDir, srcPath);
110914
+ const fromCompiled = join16(compiledDir, srcPath);
110915
+ srcPath = existsSync16(fromCompiled) ? fromCompiled : join16(projectDir, srcPath);
110442
110916
  }
110443
110917
  hdrVideoSrcPaths.set(v.id, srcPath);
110444
110918
  }
@@ -110568,8 +111042,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110568
111042
  for (const [videoId, srcPath] of hdrVideoSrcPaths) {
110569
111043
  const video = composition.videos.find((v) => v.id === videoId);
110570
111044
  if (!video) continue;
110571
- const frameDir = join15(framesDir, `hdr_${videoId}`);
110572
- mkdirSync10(frameDir, { recursive: true });
111045
+ const frameDir = join16(framesDir, `hdr_${videoId}`);
111046
+ mkdirSync11(frameDir, { recursive: true });
110573
111047
  const duration = video.end - video.start;
110574
111048
  const dims = hdrExtractionDims.get(videoId) ?? { width, height };
110575
111049
  const ffmpegArgs = [
@@ -110588,7 +111062,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110588
111062
  "-c:v",
110589
111063
  "png",
110590
111064
  "-y",
110591
- join15(frameDir, "frame_%04d.png")
111065
+ join16(frameDir, "frame_%04d.png")
110592
111066
  ];
110593
111067
  const result = await runFfmpeg(ffmpegArgs, { signal: abortSignal });
110594
111068
  if (!result.success) {
@@ -110656,15 +111130,19 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110656
111130
  }
110657
111131
  }
110658
111132
  const debugDumpEnabled = process.env.KEEP_TEMP === "1";
110659
- const debugDumpDir = debugDumpEnabled ? join15(framesDir, "debug-composite") : null;
110660
- if (debugDumpDir && !existsSync15(debugDumpDir)) {
110661
- mkdirSync10(debugDumpDir, { recursive: true });
111133
+ const debugDumpDir = debugDumpEnabled ? join16(framesDir, "debug-composite") : null;
111134
+ if (debugDumpDir && !existsSync16(debugDumpDir)) {
111135
+ mkdirSync11(debugDumpDir, { recursive: true });
110662
111136
  }
110663
111137
  if (!effectiveHdr) {
110664
111138
  throw new Error(
110665
111139
  "Internal: HDR render path entered without effectiveHdr \u2014 this is a bug."
110666
111140
  );
110667
111141
  }
111142
+ const hdrCacheMaxBytes = process.env.HDR_TRANSFER_CACHE_MAX_BYTES ? Number(process.env.HDR_TRANSFER_CACHE_MAX_BYTES) : void 0;
111143
+ const hdrImageTransferCache = createHdrImageTransferCache(
111144
+ hdrCacheMaxBytes !== void 0 ? { maxBytes: hdrCacheMaxBytes } : {}
111145
+ );
110668
111146
  const hdrCompositeCtx = {
110669
111147
  log,
110670
111148
  domSession,
@@ -110675,6 +111153,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110675
111153
  effectiveHdr,
110676
111154
  nativeHdrImageIds,
110677
111155
  hdrImageBuffers,
111156
+ hdrImageTransferCache,
110678
111157
  hdrFrameDirs,
110679
111158
  hdrVideoStartTimes,
110680
111159
  imageTransfers,
@@ -110735,6 +111214,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110735
111214
  sceneBuf,
110736
111215
  el,
110737
111216
  hdrImageBuffers,
111217
+ hdrImageTransferCache,
110738
111218
  width,
110739
111219
  height,
110740
111220
  log,
@@ -110798,11 +111278,11 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110798
111278
  i
110799
111279
  );
110800
111280
  if (debugDumpEnabled && debugDumpDir && i % 30 === 0) {
110801
- const previewPath = join15(
111281
+ const previewPath = join16(
110802
111282
  debugDumpDir,
110803
111283
  `frame_${String(i).padStart(4, "0")}_final_rgb48le.bin`
110804
111284
  );
110805
- writeFileSync4(previewPath, normalCanvas);
111285
+ writeFileSync5(previewPath, normalCanvas);
110806
111286
  }
110807
111287
  hdrEncoder.writeFrame(normalCanvas);
110808
111288
  }
@@ -110822,7 +111302,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110822
111302
  error: err instanceof Error ? err.message : String(err)
110823
111303
  });
110824
111304
  }
110825
- frameDirMaxIndexCache.delete(frameDir);
111305
+ clearMaxFrameIndex(frameDir);
110826
111306
  hdrFrameDirs.delete(videoId);
110827
111307
  }
110828
111308
  cleanedUpVideos.add(videoId);
@@ -110873,7 +111353,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110873
111353
  });
110874
111354
  }
110875
111355
  for (const frameDir of hdrFrameDirs.values()) {
110876
- frameDirMaxIndexCache.delete(frameDir);
111356
+ clearMaxFrameIndex(frameDir);
110877
111357
  }
110878
111358
  hdrFrameDirs.clear();
110879
111359
  }
@@ -111145,6 +111625,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111145
111625
  updateJobStatus(job, "complete", "Render complete", 100, onProgress);
111146
111626
  const totalElapsed = Date.now() - pipelineStart;
111147
111627
  sampleMemory();
111628
+ const tmpPeakBytes = existsSync16(workDir) ? sampleDirectoryBytes(workDir) : 0;
111148
111629
  const perfSummary = {
111149
111630
  renderId: job.id,
111150
111631
  totalElapsedMs: totalElapsed,
@@ -111159,6 +111640,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111159
111640
  videoCount: composition.videos.length,
111160
111641
  audioCount: composition.audios.length,
111161
111642
  stages: perfStages,
111643
+ videoExtractBreakdown: extractionResult?.phaseBreakdown,
111644
+ tmpPeakBytes,
111162
111645
  hdrDiagnostics: hdrDiagnostics.videoExtractionFailures > 0 || hdrDiagnostics.imageDecodeFailures > 0 ? { ...hdrDiagnostics } : void 0,
111163
111646
  captureAvgMs: totalFrames > 0 ? Math.round((perfStages.captureMs ?? 0) / totalFrames) : void 0,
111164
111647
  peakRssMb: Math.round(peakRssBytes / (1024 * 1024)),
@@ -111167,7 +111650,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111167
111650
  job.perfSummary = perfSummary;
111168
111651
  if (job.config.debug) {
111169
111652
  try {
111170
- writeFileSync4(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
111653
+ writeFileSync5(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
111171
111654
  } catch (err) {
111172
111655
  log.debug("Failed to write perf summary", {
111173
111656
  perfOutputPath,
@@ -111176,8 +111659,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111176
111659
  }
111177
111660
  }
111178
111661
  if (job.config.debug) {
111179
- if (existsSync15(outputPath)) {
111180
- const debugOutput = join15(workDir, `output${videoExt}`);
111662
+ if (existsSync16(outputPath)) {
111663
+ const debugOutput = join16(workDir, `output${videoExt}`);
111181
111664
  copyFileSync2(outputPath, debugOutput);
111182
111665
  }
111183
111666
  } else if (process.env.KEEP_TEMP === "1") {
@@ -111263,7 +111746,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111263
111746
  await safeCleanup(
111264
111747
  "remove workDir (error)",
111265
111748
  () => {
111266
- if (existsSync15(workDir)) rmSync3(workDir, { recursive: true, force: true });
111749
+ if (existsSync16(workDir)) rmSync3(workDir, { recursive: true, force: true });
111267
111750
  },
111268
111751
  log
111269
111752
  );
@@ -111277,15 +111760,15 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111277
111760
 
111278
111761
  // src/server.ts
111279
111762
  import {
111280
- existsSync as existsSync17,
111281
- mkdirSync as mkdirSync11,
111282
- statSync as statSync7,
111763
+ existsSync as existsSync18,
111764
+ mkdirSync as mkdirSync12,
111765
+ statSync as statSync9,
111283
111766
  mkdtempSync,
111284
- writeFileSync as writeFileSync5,
111767
+ writeFileSync as writeFileSync6,
111285
111768
  rmSync as rmSync4,
111286
111769
  createReadStream as createReadStream2
111287
111770
  } from "node:fs";
111288
- import { resolve as resolve13, dirname as dirname11, join as join17 } from "node:path";
111771
+ import { resolve as resolve13, dirname as dirname11, join as join18 } from "node:path";
111289
111772
  import { tmpdir as tmpdir2 } from "node:os";
111290
111773
  import { parseArgs } from "node:util";
111291
111774
  import crypto2 from "node:crypto";
@@ -111440,8 +111923,8 @@ var streamSSE = (c, cb, onError) => {
111440
111923
  };
111441
111924
 
111442
111925
  // src/services/hyperframeLint.ts
111443
- import { existsSync as existsSync16, readFileSync as readFileSync11, statSync as statSync6 } from "node:fs";
111444
- import { resolve as resolve12, join as join16 } from "node:path";
111926
+ import { existsSync as existsSync17, readFileSync as readFileSync11, statSync as statSync8 } from "node:fs";
111927
+ import { resolve as resolve12, join as join17 } from "node:path";
111445
111928
  function isStringRecord(value) {
111446
111929
  if (!value || typeof value !== "object" || Array.isArray(value)) {
111447
111930
  return false;
@@ -111469,7 +111952,7 @@ function pickEntryFile(files, preferredEntryFile) {
111469
111952
  }
111470
111953
  function readProjectEntryFile(projectDir, preferredEntryFile) {
111471
111954
  const absProjectDir = resolve12(projectDir);
111472
- if (!existsSync16(absProjectDir) || !statSync6(absProjectDir).isDirectory()) {
111955
+ if (!existsSync17(absProjectDir) || !statSync8(absProjectDir).isDirectory()) {
111473
111956
  return { error: `Project directory not found: ${absProjectDir}` };
111474
111957
  }
111475
111958
  const entryCandidates = [preferredEntryFile, "index.html", "src/index.html"].filter(
@@ -111480,7 +111963,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
111480
111963
  if (!absoluteEntryPath.startsWith(absProjectDir)) {
111481
111964
  return { error: `Entry file must stay inside project directory: ${entryFile}` };
111482
111965
  }
111483
- if (existsSync16(absoluteEntryPath) && statSync6(absoluteEntryPath).isFile()) {
111966
+ if (existsSync17(absoluteEntryPath) && statSync8(absoluteEntryPath).isFile()) {
111484
111967
  return {
111485
111968
  entryFile,
111486
111969
  html: readFileSync11(absoluteEntryPath, "utf-8"),
@@ -111489,7 +111972,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
111489
111972
  }
111490
111973
  }
111491
111974
  return {
111492
- error: `No HTML entry file found in project directory: ${join16(absProjectDir, preferredEntryFile || "index.html")}`
111975
+ error: `No HTML entry file found in project directory: ${join17(absProjectDir, preferredEntryFile || "index.html")}`
111493
111976
  };
111494
111977
  }
111495
111978
  function prepareHyperframeLintBody(body) {
@@ -111580,11 +112063,11 @@ async function prepareRenderBody(body) {
111580
112063
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
111581
112064
  if (projectDir) {
111582
112065
  const absProjectDir = resolve13(projectDir);
111583
- if (!existsSync17(absProjectDir) || !statSync7(absProjectDir).isDirectory()) {
112066
+ if (!existsSync18(absProjectDir) || !statSync9(absProjectDir).isDirectory()) {
111584
112067
  return { error: `Project directory not found: ${absProjectDir}` };
111585
112068
  }
111586
112069
  const entry = options.entryFile || "index.html";
111587
- if (!existsSync17(resolve13(absProjectDir, entry))) {
112070
+ if (!existsSync18(resolve13(absProjectDir, entry))) {
111588
112071
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
111589
112072
  }
111590
112073
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -111609,8 +112092,8 @@ async function prepareRenderBody(body) {
111609
112092
  }
111610
112093
  }
111611
112094
  const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir2();
111612
- const tempProjectDir = mkdtempSync(join17(tempRoot, "producer-project-"));
111613
- writeFileSync5(join17(tempProjectDir, "index.html"), htmlContent, "utf-8");
112095
+ const tempProjectDir = mkdtempSync(join18(tempRoot, "producer-project-"));
112096
+ writeFileSync6(join18(tempProjectDir, "index.html"), htmlContent, "utf-8");
111614
112097
  return {
111615
112098
  prepared: {
111616
112099
  input: {
@@ -111733,7 +112216,7 @@ function createRenderHandlers(options = {}) {
111733
112216
  log
111734
112217
  );
111735
112218
  const outputDir = dirname11(absoluteOutputPath);
111736
- if (!existsSync17(outputDir)) mkdirSync11(outputDir, { recursive: true });
112219
+ if (!existsSync18(outputDir)) mkdirSync12(outputDir, { recursive: true });
111737
112220
  const release = await renderSemaphore.acquire();
111738
112221
  log.info("render started", {
111739
112222
  requestId,
@@ -111760,7 +112243,7 @@ function createRenderHandlers(options = {}) {
111760
112243
  log.info(`render progress ${pct}%`, { requestId, stage: j.currentStage, message });
111761
112244
  }
111762
112245
  });
111763
- const fileSize = existsSync17(absoluteOutputPath) ? statSync7(absoluteOutputPath).size : 0;
112246
+ const fileSize = existsSync18(absoluteOutputPath) ? statSync9(absoluteOutputPath).size : 0;
111764
112247
  const durationMs = Date.now() - t0;
111765
112248
  const outputToken = store.register(absoluteOutputPath);
111766
112249
  const outputUrl = `${outputUrlPrefix}/${outputToken}`;
@@ -111844,7 +112327,7 @@ function createRenderHandlers(options = {}) {
111844
112327
  log
111845
112328
  );
111846
112329
  const outputDir = dirname11(absoluteOutputPath);
111847
- if (!existsSync17(outputDir)) mkdirSync11(outputDir, { recursive: true });
112330
+ if (!existsSync18(outputDir)) mkdirSync12(outputDir, { recursive: true });
111848
112331
  log.info("render-stream started", { requestId, projectDir: input2.projectDir });
111849
112332
  const job = createRenderJob({
111850
112333
  fps: input2.fps,
@@ -111889,7 +112372,7 @@ function createRenderHandlers(options = {}) {
111889
112372
  },
111890
112373
  abortController.signal
111891
112374
  );
111892
- const fileSize = existsSync17(absoluteOutputPath) ? statSync7(absoluteOutputPath).size : 0;
112375
+ const fileSize = existsSync18(absoluteOutputPath) ? statSync9(absoluteOutputPath).size : 0;
111893
112376
  const outputToken = store.register(absoluteOutputPath);
111894
112377
  const outputUrl = `${outputUrlPrefix}/${outputToken}`;
111895
112378
  log.info("render-stream completed", { requestId, fileSize, perf: job.perfSummary ?? null });
@@ -111948,11 +112431,11 @@ function createRenderHandlers(options = {}) {
111948
112431
  if (!artifact) {
111949
112432
  return c.json({ success: false, error: "Output artifact not found or expired" }, 404);
111950
112433
  }
111951
- if (!existsSync17(artifact.path)) {
112434
+ if (!existsSync18(artifact.path)) {
111952
112435
  store.delete(token);
111953
112436
  return c.json({ success: false, error: "Output artifact file missing" }, 404);
111954
112437
  }
111955
- const stats = statSync7(artifact.path);
112438
+ const stats = statSync9(artifact.path);
111956
112439
  return new Response(createReadStream2(artifact.path), {
111957
112440
  headers: {
111958
112441
  "content-type": "video/mp4",