@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.
@@ -7907,7 +7907,7 @@ function inertIfDisposed(target, _) {
7907
7907
  };
7908
7908
  }
7909
7909
  function invokeAtMostOnceForArguments(target, _) {
7910
- const cache = /* @__PURE__ */ new WeakMap();
7910
+ const cache2 = /* @__PURE__ */ new WeakMap();
7911
7911
  let cacheDepth = -1;
7912
7912
  return function(...args) {
7913
7913
  if (cacheDepth === -1) {
@@ -7917,7 +7917,7 @@ function invokeAtMostOnceForArguments(target, _) {
7917
7917
  throw new Error("Memoized method was called with the wrong number of arguments");
7918
7918
  }
7919
7919
  let freshArguments = false;
7920
- let cacheIterator = cache;
7920
+ let cacheIterator = cache2;
7921
7921
  for (const arg of args) {
7922
7922
  if (cacheIterator.has(arg)) {
7923
7923
  cacheIterator = cacheIterator.get(arg);
@@ -45140,7 +45140,7 @@ var require_websocket = __commonJS({
45140
45140
  var http2 = __require("http");
45141
45141
  var net = __require("net");
45142
45142
  var tls = __require("tls");
45143
- var { randomBytes, createHash: createHash3 } = __require("crypto");
45143
+ var { randomBytes, createHash: createHash4 } = __require("crypto");
45144
45144
  var { Duplex, Readable: Readable3 } = __require("stream");
45145
45145
  var { URL: URL3 } = __require("url");
45146
45146
  var PerMessageDeflate = require_permessage_deflate();
@@ -45800,7 +45800,7 @@ var require_websocket = __commonJS({
45800
45800
  abortHandshake(websocket, socket, "Invalid Upgrade header");
45801
45801
  return;
45802
45802
  }
45803
- const digest = createHash3("sha1").update(key2 + GUID).digest("base64");
45803
+ const digest = createHash4("sha1").update(key2 + GUID).digest("base64");
45804
45804
  if (res.headers["sec-websocket-accept"] !== digest) {
45805
45805
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
45806
45806
  return;
@@ -46167,7 +46167,7 @@ var require_websocket_server = __commonJS({
46167
46167
  var EventEmitter4 = __require("events");
46168
46168
  var http2 = __require("http");
46169
46169
  var { Duplex } = __require("stream");
46170
- var { createHash: createHash3 } = __require("crypto");
46170
+ var { createHash: createHash4 } = __require("crypto");
46171
46171
  var extension = require_extension();
46172
46172
  var PerMessageDeflate = require_permessage_deflate();
46173
46173
  var subprotocol = require_subprotocol();
@@ -46468,7 +46468,7 @@ var require_websocket_server = __commonJS({
46468
46468
  );
46469
46469
  }
46470
46470
  if (this._state > RUNNING) return abortHandshake(socket, 503);
46471
- const digest = createHash3("sha1").update(key2 + GUID).digest("base64");
46471
+ const digest = createHash4("sha1").update(key2 + GUID).digest("base64");
46472
46472
  const headers = [
46473
46473
  "HTTP/1.1 101 Switching Protocols",
46474
46474
  "Upgrade: websocket",
@@ -47604,7 +47604,7 @@ var require_range = __commonJS({
47604
47604
  parseRange(range) {
47605
47605
  const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE);
47606
47606
  const memoKey = memoOpts + ":" + range;
47607
- const cached = cache.get(memoKey);
47607
+ const cached = cache2.get(memoKey);
47608
47608
  if (cached) {
47609
47609
  return cached;
47610
47610
  }
@@ -47638,7 +47638,7 @@ var require_range = __commonJS({
47638
47638
  rangeMap.delete("");
47639
47639
  }
47640
47640
  const result = [...rangeMap.values()];
47641
- cache.set(memoKey, result);
47641
+ cache2.set(memoKey, result);
47642
47642
  return result;
47643
47643
  }
47644
47644
  intersects(range, options) {
@@ -47677,7 +47677,7 @@ var require_range = __commonJS({
47677
47677
  };
47678
47678
  module.exports = Range2;
47679
47679
  var LRU = require_lrucache();
47680
- var cache = new LRU();
47680
+ var cache2 = new LRU();
47681
47681
  var parseOptions = require_parse_options();
47682
47682
  var Comparator = require_comparator();
47683
47683
  var debug6 = require_debug();
@@ -54357,12 +54357,12 @@ var require_data = __commonJS({
54357
54357
  this.hash = hash2;
54358
54358
  }
54359
54359
  };
54360
- var data = async ({ href: uri }, { cache } = {}) => {
54360
+ var data = async ({ href: uri }, { cache: cache2 } = {}) => {
54361
54361
  const shasum = (0, crypto_1.createHash)("sha1");
54362
54362
  shasum.update(uri);
54363
54363
  const hash2 = shasum.digest("hex");
54364
54364
  debug6('generated SHA1 hash for "data:" URI: %o', hash2);
54365
- if (cache?.hash === hash2) {
54365
+ if (cache2?.hash === hash2) {
54366
54366
  debug6("got matching cache SHA1 hash: %o", hash2);
54367
54367
  throw new notmodified_1.default();
54368
54368
  } else {
@@ -54407,7 +54407,7 @@ var require_file = __commonJS({
54407
54407
  var debug6 = (0, debug_1.default)("get-uri:file");
54408
54408
  var file = async ({ href: uri }, opts = {}) => {
54409
54409
  const {
54410
- cache,
54410
+ cache: cache2,
54411
54411
  flags = "r",
54412
54412
  mode = 438
54413
54413
  // =0666
@@ -54418,7 +54418,7 @@ var require_file = __commonJS({
54418
54418
  const fdHandle = await fs_1.promises.open(filepath, flags, mode);
54419
54419
  const fd = fdHandle.fd;
54420
54420
  const stat = await fdHandle.stat();
54421
- if (cache && cache.stat && stat && isNotModified(cache.stat, stat)) {
54421
+ if (cache2 && cache2.stat && stat && isNotModified(cache2.stat, stat)) {
54422
54422
  await fdHandle.close();
54423
54423
  throw new notmodified_1.default();
54424
54424
  }
@@ -56438,7 +56438,7 @@ var require_ftp = __commonJS({
56438
56438
  var notmodified_1 = __importDefault2(require_notmodified());
56439
56439
  var debug6 = (0, debug_1.default)("get-uri:ftp");
56440
56440
  var ftp = async (url, opts = {}) => {
56441
- const { cache } = opts;
56441
+ const { cache: cache2 } = opts;
56442
56442
  const filepath = decodeURIComponent(url.pathname);
56443
56443
  let lastModified;
56444
56444
  if (!filepath) {
@@ -56492,8 +56492,8 @@ var require_ftp = __commonJS({
56492
56492
  throw err;
56493
56493
  }
56494
56494
  function isNotModified() {
56495
- if (cache?.lastModified && lastModified) {
56496
- return +cache.lastModified === +lastModified;
56495
+ if (cache2?.lastModified && lastModified) {
56496
+ return +cache2.lastModified === +lastModified;
56497
56497
  }
56498
56498
  return false;
56499
56499
  }
@@ -56538,10 +56538,10 @@ var require_http = __commonJS({
56538
56538
  var debug6 = (0, debug_1.default)("get-uri:http");
56539
56539
  var http2 = async (url, opts = {}) => {
56540
56540
  debug6("GET %o", url.href);
56541
- const cache = getCache(url, opts.cache);
56542
- if (cache && isFresh(cache) && typeof cache.statusCode === "number") {
56543
- const type2 = cache.statusCode / 100 | 0;
56544
- if (type2 === 3 && cache.headers.location) {
56541
+ const cache2 = getCache(url, opts.cache);
56542
+ if (cache2 && isFresh(cache2) && typeof cache2.statusCode === "number") {
56543
+ const type2 = cache2.statusCode / 100 | 0;
56544
+ if (type2 === 3 && cache2.headers.location) {
56545
56545
  debug6("cached redirect");
56546
56546
  throw new Error("TODO: implement cached redirects!");
56547
56547
  }
@@ -56558,16 +56558,16 @@ var require_http = __commonJS({
56558
56558
  debug6("using `http` core module");
56559
56559
  }
56560
56560
  const options = { ...opts };
56561
- if (cache) {
56561
+ if (cache2) {
56562
56562
  if (!options.headers) {
56563
56563
  options.headers = {};
56564
56564
  }
56565
- const lastModified = cache.headers["last-modified"];
56565
+ const lastModified = cache2.headers["last-modified"];
56566
56566
  if (lastModified) {
56567
56567
  options.headers["If-Modified-Since"] = lastModified;
56568
56568
  debug6('added "If-Modified-Since" request header: %o', lastModified);
56569
56569
  }
56570
- const etag = cache.headers.etag;
56570
+ const etag = cache2.headers.etag;
56571
56571
  if (etag) {
56572
56572
  options.headers["If-None-Match"] = etag;
56573
56573
  debug6('added "If-None-Match" request header: %o', etag);
@@ -56614,10 +56614,10 @@ var require_http = __commonJS({
56614
56614
  return res;
56615
56615
  };
56616
56616
  exports.http = http2;
56617
- function isFresh(cache) {
56617
+ function isFresh(cache2) {
56618
56618
  let fresh = false;
56619
- let expires = parseInt(cache.headers.expires || "", 10);
56620
- const cacheControl = cache.headers["cache-control"];
56619
+ let expires = parseInt(cache2.headers.expires || "", 10);
56620
+ const cacheControl = cache2.headers["cache-control"];
56621
56621
  if (cacheControl) {
56622
56622
  debug6("Cache-Control: %o", cacheControl);
56623
56623
  const parts = cacheControl.split(/,\s*?\b/);
@@ -56627,7 +56627,7 @@ var require_http = __commonJS({
56627
56627
  const name = subparts[0];
56628
56628
  switch (name) {
56629
56629
  case "max-age":
56630
- expires = (cache.date || 0) + parseInt(subparts[1], 10) * 1e3;
56630
+ expires = (cache2.date || 0) + parseInt(subparts[1], 10) * 1e3;
56631
56631
  fresh = Date.now() < expires;
56632
56632
  if (fresh) {
56633
56633
  debug6('cache is "fresh" due to previous %o Cache-Control param', part);
@@ -56653,14 +56653,14 @@ var require_http = __commonJS({
56653
56653
  }
56654
56654
  return false;
56655
56655
  }
56656
- function getCache(url, cache) {
56657
- if (cache) {
56658
- if (cache.parsed && cache.parsed.href === url.href) {
56659
- return cache;
56656
+ function getCache(url, cache2) {
56657
+ if (cache2) {
56658
+ if (cache2.parsed && cache2.parsed.href === url.href) {
56659
+ return cache2;
56660
56660
  }
56661
- if (cache.redirects) {
56662
- for (let i = 0; i < cache.redirects.length; i++) {
56663
- const c = getCache(url, cache.redirects[i]);
56661
+ if (cache2.redirects) {
56662
+ for (let i = 0; i < cache2.redirects.length; i++) {
56663
+ const c = getCache(url, cache2.redirects[i]);
56664
56664
  if (c) {
56665
56665
  return c;
56666
56666
  }
@@ -57895,7 +57895,7 @@ var require_util2 = __commonJS({
57895
57895
  return path12;
57896
57896
  }
57897
57897
  exports.normalize = normalize2;
57898
- function join18(aRoot, aPath) {
57898
+ function join19(aRoot, aPath) {
57899
57899
  if (aRoot === "") {
57900
57900
  aRoot = ".";
57901
57901
  }
@@ -57927,7 +57927,7 @@ var require_util2 = __commonJS({
57927
57927
  }
57928
57928
  return joined;
57929
57929
  }
57930
- exports.join = join18;
57930
+ exports.join = join19;
57931
57931
  exports.isAbsolute = function(aPath) {
57932
57932
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
57933
57933
  };
@@ -58100,7 +58100,7 @@ var require_util2 = __commonJS({
58100
58100
  parsed.path = parsed.path.substring(0, index + 1);
58101
58101
  }
58102
58102
  }
58103
- sourceURL = join18(urlGenerate(parsed), sourceURL);
58103
+ sourceURL = join19(urlGenerate(parsed), sourceURL);
58104
58104
  }
58105
58105
  return normalize2(sourceURL);
58106
58106
  }
@@ -59902,7 +59902,7 @@ var require_escodegen = __commonJS({
59902
59902
  function noEmptySpace() {
59903
59903
  return space ? space : " ";
59904
59904
  }
59905
- function join18(left2, right2) {
59905
+ function join19(left2, right2) {
59906
59906
  var leftSource, rightSource, leftCharCode, rightCharCode;
59907
59907
  leftSource = toSourceNodeWhenNeeded(left2).toString();
59908
59908
  if (leftSource.length === 0) {
@@ -60233,8 +60233,8 @@ var require_escodegen = __commonJS({
60233
60233
  } else {
60234
60234
  result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));
60235
60235
  }
60236
- result = join18(result, operator);
60237
- result = [join18(
60236
+ result = join19(result, operator);
60237
+ result = [join19(
60238
60238
  result,
60239
60239
  that.generateExpression(stmt.right, Precedence.Assignment, E_TTT)
60240
60240
  ), ")"];
@@ -60377,11 +60377,11 @@ var require_escodegen = __commonJS({
60377
60377
  var result, fragment;
60378
60378
  result = ["class"];
60379
60379
  if (stmt.id) {
60380
- result = join18(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
60380
+ result = join19(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
60381
60381
  }
60382
60382
  if (stmt.superClass) {
60383
- fragment = join18("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
60384
- result = join18(result, fragment);
60383
+ fragment = join19("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
60384
+ result = join19(result, fragment);
60385
60385
  }
60386
60386
  result.push(space);
60387
60387
  result.push(this.generateStatement(stmt.body, S_TFFT));
@@ -60394,9 +60394,9 @@ var require_escodegen = __commonJS({
60394
60394
  return escapeDirective(stmt.directive) + this.semicolon(flags);
60395
60395
  },
60396
60396
  DoWhileStatement: function(stmt, flags) {
60397
- var result = join18("do", this.maybeBlock(stmt.body, S_TFFF));
60397
+ var result = join19("do", this.maybeBlock(stmt.body, S_TFFF));
60398
60398
  result = this.maybeBlockSuffix(stmt.body, result);
60399
- return join18(result, [
60399
+ return join19(result, [
60400
60400
  "while" + space + "(",
60401
60401
  this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
60402
60402
  ")" + this.semicolon(flags)
@@ -60432,11 +60432,11 @@ var require_escodegen = __commonJS({
60432
60432
  ExportDefaultDeclaration: function(stmt, flags) {
60433
60433
  var result = ["export"], bodyFlags;
60434
60434
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
60435
- result = join18(result, "default");
60435
+ result = join19(result, "default");
60436
60436
  if (isStatement(stmt.declaration)) {
60437
- result = join18(result, this.generateStatement(stmt.declaration, bodyFlags));
60437
+ result = join19(result, this.generateStatement(stmt.declaration, bodyFlags));
60438
60438
  } else {
60439
- result = join18(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
60439
+ result = join19(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
60440
60440
  }
60441
60441
  return result;
60442
60442
  },
@@ -60444,15 +60444,15 @@ var require_escodegen = __commonJS({
60444
60444
  var result = ["export"], bodyFlags, that = this;
60445
60445
  bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
60446
60446
  if (stmt.declaration) {
60447
- return join18(result, this.generateStatement(stmt.declaration, bodyFlags));
60447
+ return join19(result, this.generateStatement(stmt.declaration, bodyFlags));
60448
60448
  }
60449
60449
  if (stmt.specifiers) {
60450
60450
  if (stmt.specifiers.length === 0) {
60451
- result = join18(result, "{" + space + "}");
60451
+ result = join19(result, "{" + space + "}");
60452
60452
  } else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {
60453
- result = join18(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
60453
+ result = join19(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
60454
60454
  } else {
60455
- result = join18(result, "{");
60455
+ result = join19(result, "{");
60456
60456
  withIndent(function(indent2) {
60457
60457
  var i, iz;
60458
60458
  result.push(newline);
@@ -60470,7 +60470,7 @@ var require_escodegen = __commonJS({
60470
60470
  result.push(base + "}");
60471
60471
  }
60472
60472
  if (stmt.source) {
60473
- result = join18(result, [
60473
+ result = join19(result, [
60474
60474
  "from" + space,
60475
60475
  // ModuleSpecifier
60476
60476
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -60558,7 +60558,7 @@ var require_escodegen = __commonJS({
60558
60558
  ];
60559
60559
  cursor = 0;
60560
60560
  if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {
60561
- result = join18(result, [
60561
+ result = join19(result, [
60562
60562
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
60563
60563
  ]);
60564
60564
  ++cursor;
@@ -60568,7 +60568,7 @@ var require_escodegen = __commonJS({
60568
60568
  result.push(",");
60569
60569
  }
60570
60570
  if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {
60571
- result = join18(result, [
60571
+ result = join19(result, [
60572
60572
  space,
60573
60573
  this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
60574
60574
  ]);
@@ -60597,7 +60597,7 @@ var require_escodegen = __commonJS({
60597
60597
  }
60598
60598
  }
60599
60599
  }
60600
- result = join18(result, [
60600
+ result = join19(result, [
60601
60601
  "from" + space,
60602
60602
  // ModuleSpecifier
60603
60603
  this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
@@ -60651,7 +60651,7 @@ var require_escodegen = __commonJS({
60651
60651
  return result;
60652
60652
  },
60653
60653
  ThrowStatement: function(stmt, flags) {
60654
- return [join18(
60654
+ return [join19(
60655
60655
  "throw",
60656
60656
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
60657
60657
  ), this.semicolon(flags)];
@@ -60662,7 +60662,7 @@ var require_escodegen = __commonJS({
60662
60662
  result = this.maybeBlockSuffix(stmt.block, result);
60663
60663
  if (stmt.handlers) {
60664
60664
  for (i = 0, iz = stmt.handlers.length; i < iz; ++i) {
60665
- result = join18(result, this.generateStatement(stmt.handlers[i], S_TFFF));
60665
+ result = join19(result, this.generateStatement(stmt.handlers[i], S_TFFF));
60666
60666
  if (stmt.finalizer || i + 1 !== iz) {
60667
60667
  result = this.maybeBlockSuffix(stmt.handlers[i].body, result);
60668
60668
  }
@@ -60670,7 +60670,7 @@ var require_escodegen = __commonJS({
60670
60670
  } else {
60671
60671
  guardedHandlers = stmt.guardedHandlers || [];
60672
60672
  for (i = 0, iz = guardedHandlers.length; i < iz; ++i) {
60673
- result = join18(result, this.generateStatement(guardedHandlers[i], S_TFFF));
60673
+ result = join19(result, this.generateStatement(guardedHandlers[i], S_TFFF));
60674
60674
  if (stmt.finalizer || i + 1 !== iz) {
60675
60675
  result = this.maybeBlockSuffix(guardedHandlers[i].body, result);
60676
60676
  }
@@ -60678,13 +60678,13 @@ var require_escodegen = __commonJS({
60678
60678
  if (stmt.handler) {
60679
60679
  if (Array.isArray(stmt.handler)) {
60680
60680
  for (i = 0, iz = stmt.handler.length; i < iz; ++i) {
60681
- result = join18(result, this.generateStatement(stmt.handler[i], S_TFFF));
60681
+ result = join19(result, this.generateStatement(stmt.handler[i], S_TFFF));
60682
60682
  if (stmt.finalizer || i + 1 !== iz) {
60683
60683
  result = this.maybeBlockSuffix(stmt.handler[i].body, result);
60684
60684
  }
60685
60685
  }
60686
60686
  } else {
60687
- result = join18(result, this.generateStatement(stmt.handler, S_TFFF));
60687
+ result = join19(result, this.generateStatement(stmt.handler, S_TFFF));
60688
60688
  if (stmt.finalizer) {
60689
60689
  result = this.maybeBlockSuffix(stmt.handler.body, result);
60690
60690
  }
@@ -60692,7 +60692,7 @@ var require_escodegen = __commonJS({
60692
60692
  }
60693
60693
  }
60694
60694
  if (stmt.finalizer) {
60695
- result = join18(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
60695
+ result = join19(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
60696
60696
  }
60697
60697
  return result;
60698
60698
  },
@@ -60726,7 +60726,7 @@ var require_escodegen = __commonJS({
60726
60726
  withIndent(function() {
60727
60727
  if (stmt.test) {
60728
60728
  result = [
60729
- join18("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
60729
+ join19("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
60730
60730
  ":"
60731
60731
  ];
60732
60732
  } else {
@@ -60774,9 +60774,9 @@ var require_escodegen = __commonJS({
60774
60774
  result.push(this.maybeBlock(stmt.consequent, S_TFFF));
60775
60775
  result = this.maybeBlockSuffix(stmt.consequent, result);
60776
60776
  if (stmt.alternate.type === Syntax.IfStatement) {
60777
- result = join18(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
60777
+ result = join19(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
60778
60778
  } else {
60779
- result = join18(result, join18("else", this.maybeBlock(stmt.alternate, bodyFlags)));
60779
+ result = join19(result, join19("else", this.maybeBlock(stmt.alternate, bodyFlags)));
60780
60780
  }
60781
60781
  } else {
60782
60782
  result.push(this.maybeBlock(stmt.consequent, bodyFlags));
@@ -60877,7 +60877,7 @@ var require_escodegen = __commonJS({
60877
60877
  },
60878
60878
  ReturnStatement: function(stmt, flags) {
60879
60879
  if (stmt.argument) {
60880
- return [join18(
60880
+ return [join19(
60881
60881
  "return",
60882
60882
  this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
60883
60883
  ), this.semicolon(flags)];
@@ -60966,14 +60966,14 @@ var require_escodegen = __commonJS({
60966
60966
  if (leftSource.charCodeAt(leftSource.length - 1) === 47 && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {
60967
60967
  result = [fragment, noEmptySpace(), expr.operator];
60968
60968
  } else {
60969
- result = join18(fragment, expr.operator);
60969
+ result = join19(fragment, expr.operator);
60970
60970
  }
60971
60971
  fragment = this.generateExpression(expr.right, rightPrecedence, flags);
60972
60972
  if (expr.operator === "/" && fragment.toString().charAt(0) === "/" || expr.operator.slice(-1) === "<" && fragment.toString().slice(0, 3) === "!--") {
60973
60973
  result.push(noEmptySpace());
60974
60974
  result.push(fragment);
60975
60975
  } else {
60976
- result = join18(result, fragment);
60976
+ result = join19(result, fragment);
60977
60977
  }
60978
60978
  if (expr.operator === "in" && !(flags & F_ALLOW_IN)) {
60979
60979
  return ["(", result, ")"];
@@ -61013,7 +61013,7 @@ var require_escodegen = __commonJS({
61013
61013
  var result, length, i, iz, itemFlags;
61014
61014
  length = expr["arguments"].length;
61015
61015
  itemFlags = flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0 ? E_TFT : E_TFF;
61016
- result = join18(
61016
+ result = join19(
61017
61017
  "new",
61018
61018
  this.generateExpression(expr.callee, Precedence.New, itemFlags)
61019
61019
  );
@@ -61063,11 +61063,11 @@ var require_escodegen = __commonJS({
61063
61063
  var result, fragment, rightCharCode, leftSource, leftCharCode;
61064
61064
  fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);
61065
61065
  if (space === "") {
61066
- result = join18(expr.operator, fragment);
61066
+ result = join19(expr.operator, fragment);
61067
61067
  } else {
61068
61068
  result = [expr.operator];
61069
61069
  if (expr.operator.length > 2) {
61070
- result = join18(result, fragment);
61070
+ result = join19(result, fragment);
61071
61071
  } else {
61072
61072
  leftSource = toSourceNodeWhenNeeded(result).toString();
61073
61073
  leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
@@ -61090,7 +61090,7 @@ var require_escodegen = __commonJS({
61090
61090
  result = "yield";
61091
61091
  }
61092
61092
  if (expr.argument) {
61093
- result = join18(
61093
+ result = join19(
61094
61094
  result,
61095
61095
  this.generateExpression(expr.argument, Precedence.Yield, E_TTT)
61096
61096
  );
@@ -61098,7 +61098,7 @@ var require_escodegen = __commonJS({
61098
61098
  return parenthesize(result, Precedence.Yield, precedence);
61099
61099
  },
61100
61100
  AwaitExpression: function(expr, precedence, flags) {
61101
- var result = join18(
61101
+ var result = join19(
61102
61102
  expr.all ? "await*" : "await",
61103
61103
  this.generateExpression(expr.argument, Precedence.Await, E_TTT)
61104
61104
  );
@@ -61181,11 +61181,11 @@ var require_escodegen = __commonJS({
61181
61181
  var result, fragment;
61182
61182
  result = ["class"];
61183
61183
  if (expr.id) {
61184
- result = join18(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
61184
+ result = join19(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
61185
61185
  }
61186
61186
  if (expr.superClass) {
61187
- fragment = join18("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
61188
- result = join18(result, fragment);
61187
+ fragment = join19("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
61188
+ result = join19(result, fragment);
61189
61189
  }
61190
61190
  result.push(space);
61191
61191
  result.push(this.generateStatement(expr.body, S_TFFT));
@@ -61200,7 +61200,7 @@ var require_escodegen = __commonJS({
61200
61200
  }
61201
61201
  if (expr.kind === "get" || expr.kind === "set") {
61202
61202
  fragment = [
61203
- join18(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
61203
+ join19(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
61204
61204
  this.generateFunctionBody(expr.value)
61205
61205
  ];
61206
61206
  } else {
@@ -61210,7 +61210,7 @@ var require_escodegen = __commonJS({
61210
61210
  this.generateFunctionBody(expr.value)
61211
61211
  ];
61212
61212
  }
61213
- return join18(result, fragment);
61213
+ return join19(result, fragment);
61214
61214
  },
61215
61215
  Property: function(expr, precedence, flags) {
61216
61216
  if (expr.kind === "get" || expr.kind === "set") {
@@ -61405,7 +61405,7 @@ var require_escodegen = __commonJS({
61405
61405
  for (i = 0, iz = expr.blocks.length; i < iz; ++i) {
61406
61406
  fragment = that.generateExpression(expr.blocks[i], Precedence.Sequence, E_TTT);
61407
61407
  if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
61408
- result = join18(result, fragment);
61408
+ result = join19(result, fragment);
61409
61409
  } else {
61410
61410
  result.push(fragment);
61411
61411
  }
@@ -61413,13 +61413,13 @@ var require_escodegen = __commonJS({
61413
61413
  });
61414
61414
  }
61415
61415
  if (expr.filter) {
61416
- result = join18(result, "if" + space);
61416
+ result = join19(result, "if" + space);
61417
61417
  fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);
61418
- result = join18(result, ["(", fragment, ")"]);
61418
+ result = join19(result, ["(", fragment, ")"]);
61419
61419
  }
61420
61420
  if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
61421
61421
  fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
61422
- result = join18(result, fragment);
61422
+ result = join19(result, fragment);
61423
61423
  }
61424
61424
  result.push(expr.type === Syntax.GeneratorExpression ? ")" : "]");
61425
61425
  return result;
@@ -61435,8 +61435,8 @@ var require_escodegen = __commonJS({
61435
61435
  } else {
61436
61436
  fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);
61437
61437
  }
61438
- fragment = join18(fragment, expr.of ? "of" : "in");
61439
- fragment = join18(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
61438
+ fragment = join19(fragment, expr.of ? "of" : "in");
61439
+ fragment = join19(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
61440
61440
  return ["for" + space + "(", fragment, ")"];
61441
61441
  },
61442
61442
  SpreadElement: function(expr, precedence, flags) {
@@ -69093,12 +69093,12 @@ var require_path = __commonJS({
69093
69093
  return path12.__childCache || (path12.__childCache = /* @__PURE__ */ Object.create(null));
69094
69094
  }
69095
69095
  function getChildPath(path12, name) {
69096
- var cache = getChildCache(path12);
69096
+ var cache2 = getChildCache(path12);
69097
69097
  var actualChildValue = path12.getValueProperty(name);
69098
- var childPath = cache[name];
69099
- if (!hasOwn.call(cache, name) || // Ensure consistency between cache and reality.
69098
+ var childPath = cache2[name];
69099
+ if (!hasOwn.call(cache2, name) || // Ensure consistency between cache and reality.
69100
69100
  childPath.value !== actualChildValue) {
69101
- childPath = cache[name] = new path12.constructor(actualChildValue, path12, name);
69101
+ childPath = cache2[name] = new path12.constructor(actualChildValue, path12, name);
69102
69102
  }
69103
69103
  return childPath;
69104
69104
  }
@@ -69174,7 +69174,7 @@ var require_path = __commonJS({
69174
69174
  isNumber4.assert(start);
69175
69175
  isNumber4.assert(end);
69176
69176
  var moves = /* @__PURE__ */ Object.create(null);
69177
- var cache = getChildCache(path12);
69177
+ var cache2 = getChildCache(path12);
69178
69178
  for (var i = start; i < end; ++i) {
69179
69179
  if (hasOwn.call(path12.value, i)) {
69180
69180
  var childPath = path12.get(i);
@@ -69184,17 +69184,17 @@ var require_path = __commonJS({
69184
69184
  var newIndex = i + offset;
69185
69185
  childPath.name = newIndex;
69186
69186
  moves[newIndex] = childPath;
69187
- delete cache[i];
69187
+ delete cache2[i];
69188
69188
  }
69189
69189
  }
69190
- delete cache.length;
69190
+ delete cache2.length;
69191
69191
  return function() {
69192
69192
  for (var newIndex2 in moves) {
69193
69193
  var childPath2 = moves[newIndex2];
69194
69194
  if (childPath2.name !== +newIndex2) {
69195
69195
  throw new Error("");
69196
69196
  }
69197
- cache[newIndex2] = childPath2;
69197
+ cache2[newIndex2] = childPath2;
69198
69198
  path12.value[newIndex2] = childPath2.value;
69199
69199
  }
69200
69200
  };
@@ -69226,9 +69226,9 @@ var require_path = __commonJS({
69226
69226
  };
69227
69227
  Pp.pop = function pop() {
69228
69228
  isArray4.assert(this.value);
69229
- var cache = getChildCache(this);
69230
- delete cache[this.value.length - 1];
69231
- delete cache.length;
69229
+ var cache2 = getChildCache(this);
69230
+ delete cache2[this.value.length - 1];
69231
+ delete cache2.length;
69232
69232
  return this.value.pop();
69233
69233
  };
69234
69234
  Pp.insertAt = function insertAt(index) {
@@ -76740,12 +76740,12 @@ var init_Cache = __esm({
76740
76740
  /**
76741
76741
  * @internal
76742
76742
  */
76743
- constructor(cache, browser, buildId, platform) {
76744
- this.#cache = cache;
76743
+ constructor(cache2, browser, buildId, platform) {
76744
+ this.#cache = cache2;
76745
76745
  this.browser = browser;
76746
76746
  this.buildId = buildId;
76747
76747
  this.platform = platform;
76748
- this.executablePath = cache.computeExecutablePath({
76748
+ this.executablePath = cache2.computeExecutablePath({
76749
76749
  browser,
76750
76750
  buildId,
76751
76751
  platform
@@ -81915,8 +81915,8 @@ async function installWithProviders(options) {
81915
81915
  if (!options.platform) {
81916
81916
  throw new Error("Platform must be defined");
81917
81917
  }
81918
- const cache = new Cache(options.cacheDir);
81919
- const browserRoot = cache.browserRoot(options.browser);
81918
+ const cache2 = new Cache(options.cacheDir);
81919
+ const browserRoot = cache2.browserRoot(options.browser);
81920
81920
  const providers = [...options.providers || []];
81921
81921
  if (options.baseUrl) {
81922
81922
  providers.push(new DefaultProvider(options.baseUrl));
@@ -82018,8 +82018,8 @@ async function installUrl(url, options, provider) {
82018
82018
  }
82019
82019
  const fileName = decodeURIComponent(url.toString()).split("/").pop();
82020
82020
  assert2(fileName, `A malformed download URL was found: ${url}.`);
82021
- const cache = new Cache(options.cacheDir);
82022
- const browserRoot = cache.browserRoot(options.browser);
82021
+ const cache2 = new Cache(options.cacheDir);
82022
+ const browserRoot = cache2.browserRoot(options.browser);
82023
82023
  const archivePath = path8.join(browserRoot, `${options.buildId}-${fileName}`);
82024
82024
  if (!existsSync(browserRoot)) {
82025
82025
  await mkdir2(browserRoot, { recursive: true });
@@ -82034,16 +82034,16 @@ async function installUrl(url, options, provider) {
82034
82034
  debugTimeEnd("download");
82035
82035
  return archivePath;
82036
82036
  }
82037
- const outputPath = cache.installationDir(options.browser, options.platform, options.buildId);
82037
+ const outputPath = cache2.installationDir(options.browser, options.platform, options.buildId);
82038
82038
  const relativeExecutablePath6 = await provider.getExecutablePath({
82039
82039
  browser: options.browser,
82040
82040
  buildId: options.buildId,
82041
82041
  platform: options.platform
82042
82042
  });
82043
82043
  debugInstall(`Using executable path from provider: ${relativeExecutablePath6}`);
82044
- const installedBrowser = new InstalledBrowser(cache, options.browser, options.buildId, options.platform);
82044
+ const installedBrowser = new InstalledBrowser(cache2, options.browser, options.buildId, options.platform);
82045
82045
  if (!(provider instanceof DefaultProvider)) {
82046
- cache.writeExecutablePath(options.browser, options.platform, options.buildId, relativeExecutablePath6);
82046
+ cache2.writeExecutablePath(options.browser, options.platform, options.buildId, relativeExecutablePath6);
82047
82047
  }
82048
82048
  try {
82049
82049
  if (existsSync(outputPath)) {
@@ -87415,8 +87415,8 @@ var init_CLI = __esm({
87415
87415
  console.log("Cancelled.");
87416
87416
  return;
87417
87417
  }
87418
- const cache = new Cache(cacheDir);
87419
- cache.clear();
87418
+ const cache2 = new Cache(cacheDir);
87419
+ cache2.clear();
87420
87420
  console.log(`${cacheDir} cleared.`);
87421
87421
  });
87422
87422
  }).command("list", "List all installed browsers in the cache directory", (yargs2) => {
@@ -87427,8 +87427,8 @@ var init_CLI = __esm({
87427
87427
  return this.#definePathParameter(yargs2);
87428
87428
  }, async (args) => {
87429
87429
  const cacheDir = args.path ?? this.#cachePath;
87430
- const cache = new Cache(cacheDir);
87431
- const browsers = cache.getInstalledBrowsers();
87430
+ const cache2 = new Cache(cacheDir);
87431
+ const browsers = cache2.getInstalledBrowsers();
87432
87432
  for (const browser of browsers) {
87433
87433
  console.log(`${browser.browser}@${browser.buildId} (${browser.platform}) ${browser.executablePath}`);
87434
87434
  }
@@ -87598,9 +87598,9 @@ async function getConnectionTransport(options) {
87598
87598
  throw new Error("Could not detect required browser platform");
87599
87599
  }
87600
87600
  const { convertPuppeteerChannelToBrowsersChannel: convertPuppeteerChannelToBrowsersChannel2 } = await Promise.resolve().then(() => (init_LaunchOptions(), LaunchOptions_exports));
87601
- const { join: join18 } = await import("node:path");
87601
+ const { join: join19 } = await import("node:path");
87602
87602
  const userDataDir = resolveDefaultUserDataDir3(Browser4.CHROME, platform, convertPuppeteerChannelToBrowsersChannel2(options.channel));
87603
- const portPath = join18(userDataDir, "DevToolsActivePort");
87603
+ const portPath = join19(userDataDir, "DevToolsActivePort");
87604
87604
  try {
87605
87605
  const fileContent = await environment.value.fs.promises.readFile(portPath, "ascii");
87606
87606
  const [rawPort, rawPath] = fileContent.split("\n").map((line) => {
@@ -89418,15 +89418,15 @@ var init_puppeteer_core = __esm({
89418
89418
 
89419
89419
  // src/server.ts
89420
89420
  import {
89421
- existsSync as existsSync17,
89422
- mkdirSync as mkdirSync11,
89423
- statSync as statSync7,
89421
+ existsSync as existsSync18,
89422
+ mkdirSync as mkdirSync12,
89423
+ statSync as statSync9,
89424
89424
  mkdtempSync,
89425
- writeFileSync as writeFileSync5,
89425
+ writeFileSync as writeFileSync6,
89426
89426
  rmSync as rmSync4,
89427
89427
  createReadStream as createReadStream2
89428
89428
  } from "node:fs";
89429
- import { resolve as resolve13, dirname as dirname11, join as join17 } from "node:path";
89429
+ import { resolve as resolve13, dirname as dirname11, join as join18 } from "node:path";
89430
89430
  import { tmpdir as tmpdir2 } from "node:os";
89431
89431
  import { parseArgs } from "node:util";
89432
89432
  import crypto2 from "node:crypto";
@@ -91854,14 +91854,14 @@ var Response2 = class _Response {
91854
91854
  }
91855
91855
  }
91856
91856
  get headers() {
91857
- const cache = this[cacheKey];
91858
- if (cache) {
91859
- if (!(cache[2] instanceof Headers)) {
91860
- cache[2] = new Headers(
91861
- cache[2] || { "content-type": "text/plain; charset=UTF-8" }
91857
+ const cache2 = this[cacheKey];
91858
+ if (cache2) {
91859
+ if (!(cache2[2] instanceof Headers)) {
91860
+ cache2[2] = new Headers(
91861
+ cache2[2] || { "content-type": "text/plain; charset=UTF-8" }
91862
91862
  );
91863
91863
  }
91864
- return cache[2];
91864
+ return cache2[2];
91865
91865
  }
91866
91866
  return this[getResponseCache]().headers;
91867
91867
  }
@@ -92206,12 +92206,13 @@ var serve = (options, listeningListener) => {
92206
92206
 
92207
92207
  // src/services/renderOrchestrator.ts
92208
92208
  import {
92209
- existsSync as existsSync15,
92210
- mkdirSync as mkdirSync10,
92209
+ existsSync as existsSync16,
92210
+ mkdirSync as mkdirSync11,
92211
92211
  rmSync as rmSync3,
92212
92212
  readFileSync as readFileSync10,
92213
- readdirSync as readdirSync6,
92214
- writeFileSync as writeFileSync4,
92213
+ readdirSync as readdirSync8,
92214
+ statSync as statSync7,
92215
+ writeFileSync as writeFileSync5,
92215
92216
  copyFileSync as copyFileSync2,
92216
92217
  appendFileSync
92217
92218
  } from "fs";
@@ -101536,7 +101537,8 @@ function resolveConfig(overrides) {
101536
101537
  DEFAULT_CONFIG.renderReadyTimeout
101537
101538
  ),
101538
101539
  verifyRuntime: env2("PRODUCER_VERIFY_HYPERFRAME_RUNTIME") !== "false",
101539
- runtimeManifestPath: env2("PRODUCER_HYPERFRAME_MANIFEST_PATH")
101540
+ runtimeManifestPath: env2("PRODUCER_HYPERFRAME_MANIFEST_PATH"),
101541
+ extractCacheDir: env2("HYPERFRAMES_EXTRACT_CACHE_DIR")
101540
101542
  };
101541
101543
  const cleanEnv = Object.fromEntries(Object.entries(fromEnv).filter(([, v]) => v !== void 0));
101542
101544
  return {
@@ -102692,6 +102694,7 @@ var mediaRules = [
102692
102694
 
102693
102695
  // ../core/src/lint/rules/gsap.ts
102694
102696
  var META_GSAP_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "repeat", "yoyo", "overwrite", "delay"]);
102697
+ var SCENE_BOUNDARY_EPSILON_SECONDS = 0.05;
102695
102698
  function countClassUsage(tags) {
102696
102699
  const counts = /* @__PURE__ */ new Map();
102697
102700
  for (const tag of tags) {
@@ -102732,6 +102735,7 @@ function extractGsapWindows(script) {
102732
102735
  position: animation.position,
102733
102736
  end: animation.position + meta.effectiveDuration,
102734
102737
  properties: meta.properties.length > 0 ? meta.properties : Object.keys(animation.properties),
102738
+ propertyValues: meta.propertyValues,
102735
102739
  overwriteAuto: meta.overwriteAuto,
102736
102740
  method: match2[1] ?? "to",
102737
102741
  raw: raw2
@@ -102740,8 +102744,14 @@ function extractGsapWindows(script) {
102740
102744
  return windows;
102741
102745
  }
102742
102746
  function parseGsapWindowMeta(method, argsStr) {
102747
+ const emptyMeta = {
102748
+ effectiveDuration: 0,
102749
+ properties: [],
102750
+ propertyValues: {},
102751
+ overwriteAuto: false
102752
+ };
102743
102753
  const selectorMatch = argsStr.match(/^\s*["']([^"']+)["']\s*,/);
102744
- if (!selectorMatch) return { effectiveDuration: 0, properties: [], overwriteAuto: false };
102754
+ if (!selectorMatch) return emptyMeta;
102745
102755
  const afterSelector = argsStr.slice(selectorMatch[0].length);
102746
102756
  let properties = {};
102747
102757
  let fromProperties = {};
@@ -102779,6 +102789,7 @@ function parseGsapWindowMeta(method, argsStr) {
102779
102789
  return {
102780
102790
  effectiveDuration: method === "set" ? 0 : effectiveDuration,
102781
102791
  properties: [...propertyNames],
102792
+ propertyValues: properties,
102782
102793
  overwriteAuto
102783
102794
  };
102784
102795
  }
@@ -102826,6 +102837,94 @@ function stringValue(value) {
102826
102837
  if (typeof value === "number") return String(value);
102827
102838
  return null;
102828
102839
  }
102840
+ function zeroValue(value) {
102841
+ if (typeof value === "number") return value === 0;
102842
+ if (typeof value !== "string") return false;
102843
+ return Number(value.trim()) === 0;
102844
+ }
102845
+ function isHiddenGsapState(values) {
102846
+ const visibility = stringValue(values.visibility)?.toLowerCase();
102847
+ const display = stringValue(values.display)?.toLowerCase();
102848
+ return zeroValue(values.opacity) || zeroValue(values.autoAlpha) || visibility === "hidden" || display === "none";
102849
+ }
102850
+ function isSceneBoundaryExit(win) {
102851
+ if (win.end <= win.position) return false;
102852
+ if (win.method !== "to" && win.method !== "fromTo") return false;
102853
+ return isHiddenGsapState(win.propertyValues);
102854
+ }
102855
+ function isHardKillSet(win, selector, boundary) {
102856
+ return win.method === "set" && win.targetSelector === selector && Math.abs(win.position - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS && isHiddenGsapState(win.propertyValues);
102857
+ }
102858
+ function hiddenStateLiteral(values) {
102859
+ if (zeroValue(values.autoAlpha)) return "{ autoAlpha: 0 }";
102860
+ if (zeroValue(values.opacity)) return "{ opacity: 0 }";
102861
+ if (stringValue(values.visibility)?.toLowerCase() === "hidden") return '{ visibility: "hidden" }';
102862
+ if (stringValue(values.display)?.toLowerCase() === "none") return '{ display: "none" }';
102863
+ return "{ opacity: 0 }";
102864
+ }
102865
+ function findTagEnd(source2, tag) {
102866
+ const escapedTagName = tag.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
102867
+ const pattern = new RegExp(`<\\/?${escapedTagName}\\b[^>]*>`, "gi");
102868
+ pattern.lastIndex = tag.index;
102869
+ let depth = 0;
102870
+ let match2;
102871
+ while ((match2 = pattern.exec(source2)) !== null) {
102872
+ const raw2 = match2[0];
102873
+ const isClosing = /^<\s*\//.test(raw2);
102874
+ const isSelfClosing = /\/\s*>$/.test(raw2);
102875
+ if (!isClosing && !isSelfClosing) depth += 1;
102876
+ if (isClosing) depth -= 1;
102877
+ if (depth === 0) return pattern.lastIndex;
102878
+ }
102879
+ return source2.length;
102880
+ }
102881
+ function collectCompositionRanges(source2, tags) {
102882
+ return tags.map((tag) => {
102883
+ const id = readAttr(tag.raw, "data-composition-id");
102884
+ if (!id) return null;
102885
+ return {
102886
+ id,
102887
+ start: tag.index,
102888
+ end: findTagEnd(source2, tag)
102889
+ };
102890
+ }).filter((range) => range !== null);
102891
+ }
102892
+ function findContainingCompositionId(tag, ranges) {
102893
+ let match2 = null;
102894
+ for (const range of ranges) {
102895
+ if (tag.index < range.start || tag.index >= range.end) continue;
102896
+ if (!match2 || range.start >= match2.start) match2 = range;
102897
+ }
102898
+ return match2?.id || null;
102899
+ }
102900
+ function collectClipStartBoundariesByComposition(source2, tags) {
102901
+ const ranges = collectCompositionRanges(source2, tags);
102902
+ const boundaries = /* @__PURE__ */ new Map();
102903
+ for (const tag of tags) {
102904
+ const classAttr = readAttr(tag.raw, "class") || "";
102905
+ const classes = classAttr.split(/\s+/).filter(Boolean);
102906
+ if (!classes.includes("clip")) continue;
102907
+ const compositionId = findContainingCompositionId(tag, ranges);
102908
+ if (!compositionId) continue;
102909
+ const start = numberValue(readAttr(tag.raw, "data-start") ?? void 0);
102910
+ if (start == null || start <= 0) continue;
102911
+ const compositionBoundaries = boundaries.get(compositionId) ?? /* @__PURE__ */ new Set();
102912
+ compositionBoundaries.add(start);
102913
+ boundaries.set(compositionId, compositionBoundaries);
102914
+ }
102915
+ return new Map(
102916
+ [...boundaries.entries()].map(([compositionId, values]) => [
102917
+ compositionId,
102918
+ [...values].sort((a, b) => a - b)
102919
+ ])
102920
+ );
102921
+ }
102922
+ function findMatchingSceneBoundary(time, boundaries) {
102923
+ for (const boundary of boundaries) {
102924
+ if (Math.abs(time - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS) return boundary;
102925
+ }
102926
+ return null;
102927
+ }
102829
102928
  function isSuspiciousGlobalSelector(selector) {
102830
102929
  if (!selector) return false;
102831
102930
  if (selector.includes("[data-composition-id=")) return false;
@@ -102866,7 +102965,7 @@ function cssTransformToGsapProps(cssTransform) {
102866
102965
  }
102867
102966
  var gsapRules = [
102868
102967
  // overlapping_gsap_tweens + gsap_animates_clip_element + unscoped_gsap_selector
102869
- ({ tags, scripts, rootCompositionId }) => {
102968
+ ({ source: source2, tags, scripts, rootCompositionId }) => {
102870
102969
  const findings = [];
102871
102970
  const clipIds = /* @__PURE__ */ new Map();
102872
102971
  const clipClasses = /* @__PURE__ */ new Map();
@@ -102886,9 +102985,11 @@ var gsapRules = [
102886
102985
  }
102887
102986
  }
102888
102987
  const classUsage = countClassUsage(tags);
102988
+ const clipStartBoundariesByComposition = collectClipStartBoundariesByComposition(source2, tags);
102889
102989
  for (const script of scripts) {
102890
102990
  const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);
102891
102991
  const gsapWindows = extractGsapWindows(script.content);
102992
+ const clipStartBoundaries = clipStartBoundariesByComposition.get(localTimelineCompId || rootCompositionId || "") ?? [];
102892
102993
  for (let i = 0; i < gsapWindows.length; i++) {
102893
102994
  const left2 = gsapWindows[i];
102894
102995
  if (!left2) continue;
@@ -102917,6 +103018,25 @@ ${right2.raw}`)
102917
103018
  });
102918
103019
  }
102919
103020
  }
103021
+ if (clipStartBoundaries.length > 0) {
103022
+ for (const win of gsapWindows) {
103023
+ if (!isSceneBoundaryExit(win)) continue;
103024
+ const boundary = findMatchingSceneBoundary(win.end, clipStartBoundaries);
103025
+ if (boundary == null) continue;
103026
+ const hasHardKill = gsapWindows.some(
103027
+ (candidate) => isHardKillSet(candidate, win.targetSelector, boundary)
103028
+ );
103029
+ if (hasHardKill) continue;
103030
+ findings.push({
103031
+ code: "gsap_exit_missing_hard_kill",
103032
+ severity: "warning",
103033
+ 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.`,
103034
+ selector: win.targetSelector,
103035
+ fixHint: `Add \`tl.set("${win.targetSelector}", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\` after the exit tween.`,
103036
+ snippet: truncateSnippet(win.raw)
103037
+ });
103038
+ }
103039
+ }
102920
103040
  for (const win of gsapWindows) {
102921
103041
  const sel = win.targetSelector;
102922
103042
  const clipInfo = clipIds.get(sel) || clipClasses.get(sel);
@@ -105231,8 +105351,8 @@ Process error: ${err.message}`;
105231
105351
 
105232
105352
  // ../engine/src/services/videoFrameExtractor.ts
105233
105353
  import { spawn as spawn8 } from "child_process";
105234
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync4, rmSync } from "fs";
105235
- import { isAbsolute as isAbsolute2, join as join8 } from "path";
105354
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync5, rmSync } from "fs";
105355
+ import { isAbsolute as isAbsolute2, join as join9 } from "path";
105236
105356
 
105237
105357
  // ../engine/src/utils/ffprobe.ts
105238
105358
  import { spawn as spawn7 } from "child_process";
@@ -105562,10 +105682,115 @@ function isHttpUrl(path12) {
105562
105682
  return path12.startsWith("http://") || path12.startsWith("https://");
105563
105683
  }
105564
105684
 
105685
+ // ../engine/src/utils/htmlTemplate.ts
105686
+ function parseHTMLContent(html) {
105687
+ const trimmed = html.trimStart().toLowerCase();
105688
+ if (trimmed.startsWith("<!doctype") || trimmed.startsWith("<html")) {
105689
+ return parseHTML(html).document;
105690
+ }
105691
+ return parseHTML(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`).document;
105692
+ }
105693
+ function getSingleMeaningfulChild(container) {
105694
+ let child = null;
105695
+ for (const node of Array.from(container.childNodes)) {
105696
+ if (node.nodeType === 3 && !(node.textContent || "").trim()) continue;
105697
+ if (node.nodeType === 8) continue;
105698
+ if (node.nodeType !== 1) return null;
105699
+ if (child) return null;
105700
+ child = node;
105701
+ }
105702
+ return child;
105703
+ }
105704
+ function unwrapTemplate(html) {
105705
+ const lowered = html.toLowerCase();
105706
+ if (!lowered.includes("<template") || !lowered.includes("</template>")) {
105707
+ return html;
105708
+ }
105709
+ const { body } = parseHTMLContent(html);
105710
+ if (!body) return html;
105711
+ let container = body;
105712
+ const bodyWrapper = getSingleMeaningfulChild(container);
105713
+ if (bodyWrapper?.tagName === "BODY") {
105714
+ container = bodyWrapper;
105715
+ }
105716
+ const template = getSingleMeaningfulChild(container);
105717
+ if (template?.tagName !== "TEMPLATE") {
105718
+ return html;
105719
+ }
105720
+ return template.innerHTML ?? html;
105721
+ }
105722
+
105723
+ // ../engine/src/services/extractionCache.ts
105724
+ import { createHash as createHash2 } from "node:crypto";
105725
+ import { mkdirSync as mkdirSync5, readdirSync as readdirSync4, statSync as statSync5, writeFileSync as writeFileSync3 } from "node:fs";
105726
+ import { existsSync as existsSync8 } from "node:fs";
105727
+ import { join as join8 } from "node:path";
105728
+ var FRAME_FILENAME_PREFIX = "frame_";
105729
+ var COMPLETE_SENTINEL = ".hf-complete";
105730
+ var SCHEMA_PREFIX = "hfcache-v2-";
105731
+ var KEY_HEX_CHARS = 16;
105732
+ function readKeyStat(videoPath) {
105733
+ try {
105734
+ const stat = statSync5(videoPath);
105735
+ return { mtimeMs: Math.floor(stat.mtimeMs), size: stat.size };
105736
+ } catch {
105737
+ return null;
105738
+ }
105739
+ }
105740
+ function canonicalKeyBlob(input2) {
105741
+ const durationForKey = Number.isFinite(input2.duration) ? input2.duration : -1;
105742
+ return JSON.stringify({
105743
+ p: input2.videoPath,
105744
+ m: input2.mtimeMs,
105745
+ s: input2.size,
105746
+ ms: input2.mediaStart,
105747
+ d: durationForKey,
105748
+ f: input2.fps,
105749
+ fmt: input2.format
105750
+ });
105751
+ }
105752
+ function computeCacheKey(input2) {
105753
+ return createHash2("sha256").update(canonicalKeyBlob(input2)).digest("hex");
105754
+ }
105755
+ function cacheEntryDirName(keyHash) {
105756
+ return SCHEMA_PREFIX + keyHash.slice(0, KEY_HEX_CHARS);
105757
+ }
105758
+ function lookupCacheEntry(rootDir, input2) {
105759
+ const keyHash = computeCacheKey(input2);
105760
+ const dir = join8(rootDir, cacheEntryDirName(keyHash));
105761
+ const complete = existsSync8(join8(dir, COMPLETE_SENTINEL));
105762
+ return { entry: { dir, keyHash }, hit: complete };
105763
+ }
105764
+ function ensureCacheEntryDir(entry) {
105765
+ mkdirSync5(entry.dir, { recursive: true });
105766
+ }
105767
+ function markCacheEntryComplete(entry) {
105768
+ writeFileSync3(join8(entry.dir, COMPLETE_SENTINEL), "", "utf-8");
105769
+ }
105770
+ function rehydrateCacheEntry(entry, options) {
105771
+ const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${options.format}`;
105772
+ const framePaths = /* @__PURE__ */ new Map();
105773
+ const suffix = `.${options.format}`;
105774
+ const files = readdirSync4(entry.dir).filter((f) => f.startsWith(FRAME_FILENAME_PREFIX) && f.endsWith(suffix)).sort();
105775
+ files.forEach((file, idx) => {
105776
+ framePaths.set(idx, join8(entry.dir, file));
105777
+ });
105778
+ return {
105779
+ videoId: options.videoId,
105780
+ srcPath: options.srcPath,
105781
+ outputDir: entry.dir,
105782
+ framePattern,
105783
+ fps: options.fps,
105784
+ totalFrames: framePaths.size,
105785
+ metadata: options.metadata,
105786
+ framePaths
105787
+ };
105788
+ }
105789
+
105565
105790
  // ../engine/src/services/videoFrameExtractor.ts
105566
105791
  function parseVideoElements(html) {
105567
105792
  const videos = [];
105568
- const { document: document2 } = parseHTML(html);
105793
+ const { document: document2 } = parseHTML(unwrapTemplate(html));
105569
105794
  const videoEls = document2.querySelectorAll("video[src]");
105570
105795
  let autoIdCounter = 0;
105571
105796
  for (const el of videoEls) {
@@ -105602,7 +105827,7 @@ function parseVideoElements(html) {
105602
105827
  }
105603
105828
  function parseImageElements(html) {
105604
105829
  const images = [];
105605
- const { document: document2 } = parseHTML(html);
105830
+ const { document: document2 } = parseHTML(unwrapTemplate(html));
105606
105831
  const imgEls = document2.querySelectorAll("img[src]");
105607
105832
  let autoIdCounter = 0;
105608
105833
  for (const el of imgEls) {
@@ -105628,14 +105853,14 @@ function parseImageElements(html) {
105628
105853
  }
105629
105854
  return images;
105630
105855
  }
105631
- async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config2) {
105856
+ async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config2, outputDirOverride) {
105632
105857
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
105633
105858
  const { fps, outputDir, quality = 95, format: format3 = "jpg" } = options;
105634
- const videoOutputDir = join8(outputDir, videoId);
105635
- if (!existsSync8(videoOutputDir)) mkdirSync5(videoOutputDir, { recursive: true });
105859
+ const videoOutputDir = outputDirOverride ?? join9(outputDir, videoId);
105860
+ if (!existsSync9(videoOutputDir)) mkdirSync6(videoOutputDir, { recursive: true });
105636
105861
  const metadata = await extractMediaMetadata(videoPath);
105637
- const framePattern = `frame_%05d.${format3}`;
105638
- const outputPattern = join8(videoOutputDir, framePattern);
105862
+ const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format3}`;
105863
+ const outputPattern = join9(videoOutputDir, framePattern);
105639
105864
  const isHdr = isHdrColorSpace(metadata.colorSpace);
105640
105865
  const isMacOS = process.platform === "darwin";
105641
105866
  const args = [];
@@ -105683,9 +105908,9 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
105683
105908
  return;
105684
105909
  }
105685
105910
  const framePaths = /* @__PURE__ */ new Map();
105686
- const files = readdirSync4(videoOutputDir).filter((f) => f.startsWith("frame_") && f.endsWith(`.${format3}`)).sort();
105911
+ const files = readdirSync5(videoOutputDir).filter((f) => f.startsWith(FRAME_FILENAME_PREFIX) && f.endsWith(`.${format3}`)).sort();
105687
105912
  files.forEach((file, index) => {
105688
- framePaths.set(index, join8(videoOutputDir, file));
105913
+ framePaths.set(index, join9(videoOutputDir, file));
105689
105914
  });
105690
105915
  resolve14({
105691
105916
  videoId,
@@ -105709,12 +105934,19 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
105709
105934
  });
105710
105935
  });
105711
105936
  }
105712
- async function convertSdrToHdr(inputPath, outputPath, targetTransfer, signal, config2) {
105937
+ async function convertSdrToHdr(inputPath, outputPath, startTime, duration, targetTransfer, signal, config2) {
105938
+ if (duration <= 0) {
105939
+ throw new Error(`convertSdrToHdr: duration must be positive (got ${duration})`);
105940
+ }
105713
105941
  const timeout2 = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
105714
105942
  const colorTrc = targetTransfer === "pq" ? "smpte2084" : "arib-std-b67";
105715
105943
  const args = [
105944
+ "-ss",
105945
+ String(startTime),
105716
105946
  "-i",
105717
105947
  inputPath,
105948
+ "-t",
105949
+ String(duration),
105718
105950
  "-vf",
105719
105951
  "colorspace=all=bt2020:iall=bt709:range=tv",
105720
105952
  "-color_primaries",
@@ -105741,6 +105973,11 @@ async function convertSdrToHdr(inputPath, outputPath, targetTransfer, signal, co
105741
105973
  );
105742
105974
  }
105743
105975
  }
105976
+ function resolveSegmentDuration(requested, mediaStart, metadata) {
105977
+ if (Number.isFinite(requested) && requested > 0) return requested;
105978
+ const sourceRemaining = metadata.durationSeconds - mediaStart;
105979
+ return sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
105980
+ }
105744
105981
  async function convertVfrToCfr(inputPath, outputPath, targetFps, startTime, duration, signal, config2) {
105745
105982
  const timeout2 = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
105746
105983
  const args = [
@@ -105777,21 +106014,34 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
105777
106014
  const extracted = [];
105778
106015
  const errors = [];
105779
106016
  let totalFramesExtracted = 0;
106017
+ const breakdown = {
106018
+ resolveMs: 0,
106019
+ hdrProbeMs: 0,
106020
+ hdrPreflightMs: 0,
106021
+ hdrPreflightCount: 0,
106022
+ vfrProbeMs: 0,
106023
+ vfrPreflightMs: 0,
106024
+ vfrPreflightCount: 0,
106025
+ extractMs: 0,
106026
+ cacheHits: 0,
106027
+ cacheMisses: 0
106028
+ };
106029
+ const phase1Start = Date.now();
105780
106030
  const resolvedVideos = [];
105781
106031
  for (const video of videos) {
105782
106032
  if (signal?.aborted) break;
105783
106033
  try {
105784
106034
  let videoPath = video.src;
105785
106035
  if (!isAbsolute2(videoPath) && !isHttpUrl(videoPath)) {
105786
- const fromCompiled = compiledDir ? join8(compiledDir, videoPath) : null;
105787
- videoPath = fromCompiled && existsSync8(fromCompiled) ? fromCompiled : join8(baseDir, videoPath);
106036
+ const fromCompiled = compiledDir ? join9(compiledDir, videoPath) : null;
106037
+ videoPath = fromCompiled && existsSync9(fromCompiled) ? fromCompiled : join9(baseDir, videoPath);
105788
106038
  }
105789
106039
  if (isHttpUrl(videoPath)) {
105790
- const downloadDir = join8(options.outputDir, "_downloads");
105791
- mkdirSync5(downloadDir, { recursive: true });
106040
+ const downloadDir = join9(options.outputDir, "_downloads");
106041
+ mkdirSync6(downloadDir, { recursive: true });
105792
106042
  videoPath = await downloadToTemp(videoPath, downloadDir);
105793
106043
  }
105794
- if (!existsSync8(videoPath)) {
106044
+ if (!existsSync9(videoPath)) {
105795
106045
  errors.push({ videoId: video.id, error: `Video file not found: ${videoPath}` });
105796
106046
  continue;
105797
106047
  }
@@ -105800,27 +106050,66 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
105800
106050
  errors.push({ videoId: video.id, error: err instanceof Error ? err.message : String(err) });
105801
106051
  }
105802
106052
  }
105803
- const videoColorSpaces = await Promise.all(
105804
- resolvedVideos.map(async ({ videoPath }) => {
105805
- const metadata = await extractMediaMetadata(videoPath);
105806
- return metadata.colorSpace;
105807
- })
106053
+ breakdown.resolveMs = Date.now() - phase1Start;
106054
+ const cacheKeyInputs = resolvedVideos.map(({ video, videoPath }) => {
106055
+ const stat = readKeyStat(videoPath);
106056
+ if (!stat) return null;
106057
+ return {
106058
+ videoPath,
106059
+ mtimeMs: stat.mtimeMs,
106060
+ size: stat.size,
106061
+ mediaStart: video.mediaStart,
106062
+ start: video.start,
106063
+ end: video.end
106064
+ };
106065
+ });
106066
+ const phase2ProbeStart = Date.now();
106067
+ const videoMetadata = await Promise.all(
106068
+ resolvedVideos.map(({ videoPath }) => extractMediaMetadata(videoPath))
105808
106069
  );
106070
+ const videoColorSpaces = videoMetadata.map((m) => m.colorSpace);
106071
+ breakdown.hdrProbeMs = Date.now() - phase2ProbeStart;
106072
+ const hdrPreflightStart = Date.now();
105809
106073
  const hdrInfo = analyzeCompositionHdr(videoColorSpaces);
106074
+ const hdrSkippedIndices = /* @__PURE__ */ new Set();
105810
106075
  if (hdrInfo.hasHdr && hdrInfo.dominantTransfer) {
105811
106076
  const targetTransfer = hdrInfo.dominantTransfer;
105812
- const convertDir = join8(options.outputDir, "_hdr_normalized");
105813
- mkdirSync5(convertDir, { recursive: true });
106077
+ const convertDir = join9(options.outputDir, "_hdr_normalized");
106078
+ mkdirSync6(convertDir, { recursive: true });
105814
106079
  for (let i = 0; i < resolvedVideos.length; i++) {
105815
106080
  if (signal?.aborted) break;
105816
106081
  const cs = videoColorSpaces[i] ?? null;
105817
106082
  if (!isHdrColorSpace(cs)) {
105818
106083
  const entry = resolvedVideos[i];
105819
- if (!entry) continue;
105820
- const convertedPath = join8(convertDir, `${entry.video.id}_hdr.mp4`);
106084
+ const metadata = videoMetadata[i];
106085
+ if (!entry || !metadata) continue;
106086
+ if (entry.video.mediaStart >= metadata.durationSeconds) {
106087
+ errors.push({
106088
+ videoId: entry.video.id,
106089
+ error: `SDR\u2192HDR conversion skipped: mediaStart (${entry.video.mediaStart}s) \u2265 source duration (${metadata.durationSeconds}s)`
106090
+ });
106091
+ hdrSkippedIndices.add(i);
106092
+ continue;
106093
+ }
106094
+ let segDuration = entry.video.end - entry.video.start;
106095
+ if (!Number.isFinite(segDuration) || segDuration <= 0) {
106096
+ const sourceRemaining = metadata.durationSeconds - entry.video.mediaStart;
106097
+ segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
106098
+ }
106099
+ const convertedPath = join9(convertDir, `${entry.video.id}_hdr.mp4`);
105821
106100
  try {
105822
- await convertSdrToHdr(entry.videoPath, convertedPath, targetTransfer, signal, config2);
106101
+ await convertSdrToHdr(
106102
+ entry.videoPath,
106103
+ convertedPath,
106104
+ entry.video.mediaStart,
106105
+ segDuration,
106106
+ targetTransfer,
106107
+ signal,
106108
+ config2
106109
+ );
105823
106110
  entry.videoPath = convertedPath;
106111
+ entry.video = { ...entry.video, mediaStart: 0 };
106112
+ breakdown.hdrPreflightCount += 1;
105824
106113
  } catch (err) {
105825
106114
  errors.push({
105826
106115
  videoId: entry.video.id,
@@ -105830,20 +106119,34 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
105830
106119
  }
105831
106120
  }
105832
106121
  }
105833
- const vfrNormDir = join8(options.outputDir, "_vfr_normalized");
106122
+ breakdown.hdrPreflightMs = Date.now() - hdrPreflightStart;
106123
+ if (hdrSkippedIndices.size > 0) {
106124
+ for (let i = resolvedVideos.length - 1; i >= 0; i--) {
106125
+ if (hdrSkippedIndices.has(i)) {
106126
+ resolvedVideos.splice(i, 1);
106127
+ videoMetadata.splice(i, 1);
106128
+ videoColorSpaces.splice(i, 1);
106129
+ cacheKeyInputs.splice(i, 1);
106130
+ }
106131
+ }
106132
+ }
106133
+ const vfrPreflightStart = Date.now();
106134
+ const vfrNormDir = join9(options.outputDir, "_vfr_normalized");
105834
106135
  for (let i = 0; i < resolvedVideos.length; i++) {
105835
106136
  if (signal?.aborted) break;
105836
106137
  const entry = resolvedVideos[i];
105837
106138
  if (!entry) continue;
106139
+ const vfrProbeStart = Date.now();
105838
106140
  const metadata = await extractMediaMetadata(entry.videoPath);
106141
+ breakdown.vfrProbeMs += Date.now() - vfrProbeStart;
105839
106142
  if (!metadata.isVFR) continue;
105840
106143
  let segDuration = entry.video.end - entry.video.start;
105841
106144
  if (!Number.isFinite(segDuration) || segDuration <= 0) {
105842
106145
  const sourceRemaining = metadata.durationSeconds - entry.video.mediaStart;
105843
106146
  segDuration = sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
105844
106147
  }
105845
- mkdirSync5(vfrNormDir, { recursive: true });
105846
- const normalizedPath = join8(vfrNormDir, `${entry.video.id}_cfr.mp4`);
106148
+ mkdirSync6(vfrNormDir, { recursive: true });
106149
+ const normalizedPath = join9(vfrNormDir, `${entry.video.id}_cfr.mp4`);
105847
106150
  try {
105848
106151
  await convertVfrToCfr(
105849
106152
  entry.videoPath,
@@ -105856,6 +106159,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
105856
106159
  );
105857
106160
  entry.videoPath = normalizedPath;
105858
106161
  entry.video = { ...entry.video, mediaStart: 0 };
106162
+ breakdown.vfrPreflightCount += 1;
105859
106163
  } catch (err) {
105860
106164
  errors.push({
105861
106165
  videoId: entry.video.id,
@@ -105863,19 +106167,72 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
105863
106167
  });
105864
106168
  }
105865
106169
  }
106170
+ breakdown.vfrPreflightMs = Date.now() - vfrPreflightStart;
106171
+ const phase3Start = Date.now();
106172
+ const cacheRootDir = config2?.extractCacheDir;
106173
+ const cacheFormat = options.format ?? "jpg";
106174
+ async function tryCachedExtract(video, videoPath, videoDuration, i) {
106175
+ if (!cacheRootDir) return null;
106176
+ const keyInput = cacheKeyInputs[i];
106177
+ const probedMeta = videoMetadata[i];
106178
+ if (!keyInput || !probedMeta) return null;
106179
+ const keyDuration = resolveSegmentDuration(
106180
+ keyInput.end - keyInput.start,
106181
+ keyInput.mediaStart,
106182
+ probedMeta
106183
+ );
106184
+ const lookup = lookupCacheEntry(cacheRootDir, {
106185
+ videoPath: keyInput.videoPath,
106186
+ mtimeMs: keyInput.mtimeMs,
106187
+ size: keyInput.size,
106188
+ mediaStart: keyInput.mediaStart,
106189
+ duration: keyDuration,
106190
+ fps: options.fps,
106191
+ format: cacheFormat
106192
+ });
106193
+ if (lookup.hit) {
106194
+ breakdown.cacheHits += 1;
106195
+ const rehydrated = rehydrateCacheEntry(lookup.entry, {
106196
+ videoId: video.id,
106197
+ srcPath: keyInput.videoPath,
106198
+ fps: options.fps,
106199
+ format: cacheFormat,
106200
+ metadata: probedMeta
106201
+ });
106202
+ return { ...rehydrated, ownedByLookup: true };
106203
+ }
106204
+ breakdown.cacheMisses += 1;
106205
+ ensureCacheEntryDir(lookup.entry);
106206
+ const result = await extractVideoFramesRange(
106207
+ videoPath,
106208
+ video.id,
106209
+ video.mediaStart,
106210
+ videoDuration,
106211
+ options,
106212
+ signal,
106213
+ config2,
106214
+ lookup.entry.dir
106215
+ );
106216
+ markCacheEntryComplete(lookup.entry);
106217
+ return { ...result, ownedByLookup: true };
106218
+ }
105866
106219
  const results = await Promise.all(
105867
- resolvedVideos.map(async ({ video, videoPath }) => {
106220
+ resolvedVideos.map(async ({ video, videoPath }, i) => {
105868
106221
  if (signal?.aborted) {
105869
106222
  throw new Error("Video frame extraction cancelled");
105870
106223
  }
105871
106224
  try {
105872
- let videoDuration = video.end - video.start;
105873
- if (!Number.isFinite(videoDuration) || videoDuration <= 0) {
105874
- const metadata = await extractMediaMetadata(videoPath);
105875
- const sourceDuration = metadata.durationSeconds - video.mediaStart;
105876
- videoDuration = sourceDuration > 0 ? sourceDuration : metadata.durationSeconds;
106225
+ const probedMeta = videoMetadata[i] ?? await extractMediaMetadata(videoPath);
106226
+ const videoDuration = resolveSegmentDuration(
106227
+ video.end - video.start,
106228
+ video.mediaStart,
106229
+ probedMeta
106230
+ );
106231
+ if (video.end - video.start !== videoDuration) {
105877
106232
  video.end = video.start + videoDuration;
105878
106233
  }
106234
+ const cached = await tryCachedExtract(video, videoPath, videoDuration, i);
106235
+ if (cached) return { result: cached };
105879
106236
  const result = await extractVideoFramesRange(
105880
106237
  videoPath,
105881
106238
  video.id,
@@ -105896,6 +106253,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
105896
106253
  }
105897
106254
  })
105898
106255
  );
106256
+ breakdown.extractMs = Date.now() - phase3Start;
105899
106257
  for (const item of results) {
105900
106258
  if ("error" in item && item.error) {
105901
106259
  errors.push(item.error);
@@ -105909,7 +106267,8 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
105909
106267
  extracted,
105910
106268
  errors,
105911
106269
  totalFramesExtracted,
105912
- durationMs: Date.now() - startTime
106270
+ durationMs: Date.now() - startTime,
106271
+ phaseBreakdown: breakdown
105913
106272
  };
105914
106273
  }
105915
106274
  function getFrameAtTime(extracted, globalTime, videoStart) {
@@ -106002,7 +106361,8 @@ var FrameLookupTable = class {
106002
106361
  }
106003
106362
  cleanup() {
106004
106363
  for (const video of this.videos.values()) {
106005
- if (existsSync8(video.extracted.outputDir)) {
106364
+ if (video.extracted.ownedByLookup) continue;
106365
+ if (existsSync9(video.extracted.outputDir)) {
106006
106366
  rmSync(video.extracted.outputDir, { recursive: true, force: true });
106007
106367
  }
106008
106368
  }
@@ -106025,23 +106385,23 @@ function createFrameLookupTable(videos, extracted) {
106025
106385
  // ../engine/src/services/videoFrameInjector.ts
106026
106386
  import { promises as fs7 } from "fs";
106027
106387
  function createFrameDataUriCache(cacheLimit) {
106028
- const cache = /* @__PURE__ */ new Map();
106388
+ const cache2 = /* @__PURE__ */ new Map();
106029
106389
  const inFlight = /* @__PURE__ */ new Map();
106030
106390
  function remember(framePath, dataUri) {
106031
- if (cache.has(framePath)) {
106032
- cache.delete(framePath);
106391
+ if (cache2.has(framePath)) {
106392
+ cache2.delete(framePath);
106033
106393
  }
106034
- cache.set(framePath, dataUri);
106035
- if (cache.size > cacheLimit) {
106036
- const oldestKey = cache.keys().next().value;
106394
+ cache2.set(framePath, dataUri);
106395
+ if (cache2.size > cacheLimit) {
106396
+ const oldestKey = cache2.keys().next().value;
106037
106397
  if (oldestKey) {
106038
- cache.delete(oldestKey);
106398
+ cache2.delete(oldestKey);
106039
106399
  }
106040
106400
  }
106041
106401
  return dataUri;
106042
106402
  }
106043
106403
  async function get(framePath) {
106044
- const cached = cache.get(framePath);
106404
+ const cached = cache2.get(framePath);
106045
106405
  if (cached) {
106046
106406
  remember(framePath, cached);
106047
106407
  return cached;
@@ -106245,11 +106605,11 @@ async function queryElementStacking(page, nativeHdrIds) {
106245
106605
  }
106246
106606
 
106247
106607
  // ../engine/src/services/audioMixer.ts
106248
- import { existsSync as existsSync9, mkdirSync as mkdirSync6, rmSync as rmSync2 } from "fs";
106249
- import { isAbsolute as isAbsolute3, join as join9, dirname as dirname7 } from "path";
106608
+ import { existsSync as existsSync10, mkdirSync as mkdirSync7, rmSync as rmSync2 } from "fs";
106609
+ import { isAbsolute as isAbsolute3, join as join10, dirname as dirname7 } from "path";
106250
106610
  function parseAudioElements(html) {
106251
106611
  const elements = [];
106252
- const { document: document2 } = parseHTML(html);
106612
+ const { document: document2 } = parseHTML(unwrapTemplate(html));
106253
106613
  const audioEls = document2.querySelectorAll("audio[id][src]");
106254
106614
  for (const el of audioEls) {
106255
106615
  const id = el.getAttribute("id");
@@ -106297,7 +106657,7 @@ function parseAudioElements(html) {
106297
106657
  async function extractAudioFromVideo(videoPath, outputPath, options, signal, config2) {
106298
106658
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
106299
106659
  const outputDir = dirname7(outputPath);
106300
- if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
106660
+ if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
106301
106661
  const args = ["-i", videoPath];
106302
106662
  if (options?.startTime !== void 0) args.push("-ss", String(options.startTime));
106303
106663
  if (options?.duration !== void 0) args.push("-t", String(options.duration));
@@ -106324,7 +106684,7 @@ async function extractAudioFromVideo(videoPath, outputPath, options, signal, con
106324
106684
  async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, signal, config2) {
106325
106685
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
106326
106686
  const outputDir = dirname7(outputPath);
106327
- if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
106687
+ if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
106328
106688
  const args = [
106329
106689
  "-ss",
106330
106690
  String(mediaStart),
@@ -106360,7 +106720,7 @@ async function prepareAudioTrack(srcPath, outputPath, mediaStart, duration, sign
106360
106720
  async function generateSilence(outputPath, duration, signal, config2) {
106361
106721
  const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
106362
106722
  const outputDir = dirname7(outputPath);
106363
- if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
106723
+ if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
106364
106724
  const args = [
106365
106725
  "-f",
106366
106726
  "lavfi",
@@ -106403,7 +106763,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config2
106403
106763
  };
106404
106764
  }
106405
106765
  const outputDir = dirname7(outputPath);
106406
- if (!existsSync9(outputDir)) mkdirSync6(outputDir, { recursive: true });
106766
+ if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
106407
106767
  const inputs = [];
106408
106768
  const filterParts = [];
106409
106769
  tracks.forEach((track, i) => {
@@ -106464,7 +106824,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
106464
106824
  const startMs = Date.now();
106465
106825
  const tracks = [];
106466
106826
  const errors = [];
106467
- if (!existsSync9(workDir)) mkdirSync6(workDir, { recursive: true });
106827
+ if (!existsSync10(workDir)) mkdirSync7(workDir, { recursive: true });
106468
106828
  await Promise.all(
106469
106829
  elements.map(async (element) => {
106470
106830
  if (signal?.aborted) {
@@ -106474,8 +106834,8 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
106474
106834
  try {
106475
106835
  let srcPath = element.src;
106476
106836
  if (!isAbsolute3(srcPath) && !isHttpUrl(srcPath)) {
106477
- const fromCompiled = compiledDir ? join9(compiledDir, srcPath) : null;
106478
- srcPath = fromCompiled && existsSync9(fromCompiled) ? fromCompiled : join9(baseDir, srcPath);
106837
+ const fromCompiled = compiledDir ? join10(compiledDir, srcPath) : null;
106838
+ srcPath = fromCompiled && existsSync10(fromCompiled) ? fromCompiled : join10(baseDir, srcPath);
106479
106839
  }
106480
106840
  if (isHttpUrl(srcPath)) {
106481
106841
  try {
@@ -106487,7 +106847,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
106487
106847
  return;
106488
106848
  }
106489
106849
  }
106490
- if (!existsSync9(srcPath)) {
106850
+ if (!existsSync10(srcPath)) {
106491
106851
  errors.push(`Source not found: ${element.id} (${element.src})`);
106492
106852
  return;
106493
106853
  }
@@ -106498,7 +106858,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
106498
106858
  }
106499
106859
  let audioSrcPath = srcPath;
106500
106860
  if (element.type === "video") {
106501
- const extractedPath = join9(workDir, `${element.id}-extracted.wav`);
106861
+ const extractedPath = join10(workDir, `${element.id}-extracted.wav`);
106502
106862
  const extractResult = await extractAudioFromVideo(
106503
106863
  srcPath,
106504
106864
  extractedPath,
@@ -106515,7 +106875,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
106515
106875
  }
106516
106876
  audioSrcPath = extractedPath;
106517
106877
  } else {
106518
- const trimmedPath = join9(workDir, `${element.id}-trimmed.wav`);
106878
+ const trimmedPath = join10(workDir, `${element.id}-trimmed.wav`);
106519
106879
  const prepResult = await prepareAudioTrack(
106520
106880
  srcPath,
106521
106881
  trimmedPath,
@@ -106558,9 +106918,9 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
106558
106918
 
106559
106919
  // ../engine/src/services/parallelCoordinator.ts
106560
106920
  import { cpus, freemem, totalmem } from "os";
106561
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, readdirSync as readdirSync5 } from "fs";
106921
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, readdirSync as readdirSync6 } from "fs";
106562
106922
  import { copyFile, rename as rename2 } from "fs/promises";
106563
- import { join as join10 } from "path";
106923
+ import { join as join11 } from "path";
106564
106924
  var MEMORY_PER_WORKER_MB = 256;
106565
106925
  var MIN_WORKERS = 1;
106566
106926
  var ABSOLUTE_MAX_WORKERS = 10;
@@ -106608,7 +106968,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
106608
106968
  workerId: i,
106609
106969
  startFrame,
106610
106970
  endFrame,
106611
- outputDir: join10(workDir, `worker-${i}`)
106971
+ outputDir: join11(workDir, `worker-${i}`)
106612
106972
  });
106613
106973
  }
106614
106974
  return tasks;
@@ -106616,7 +106976,7 @@ function distributeFrames(totalFrames, workerCount, workDir) {
106616
106976
  async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCaptureHook, signal, onFrameCaptured, onFrameBuffer, config2) {
106617
106977
  const startTime = Date.now();
106618
106978
  let framesCaptured = 0;
106619
- if (!existsSync10(task.outputDir)) mkdirSync7(task.outputDir, { recursive: true });
106979
+ if (!existsSync11(task.outputDir)) mkdirSync8(task.outputDir, { recursive: true });
106620
106980
  let session = null;
106621
106981
  let perf;
106622
106982
  try {
@@ -106706,17 +107066,17 @@ async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions,
106706
107066
  return results;
106707
107067
  }
106708
107068
  async function mergeWorkerFrames(workDir, tasks, outputDir) {
106709
- if (!existsSync10(outputDir)) mkdirSync7(outputDir, { recursive: true });
107069
+ if (!existsSync11(outputDir)) mkdirSync8(outputDir, { recursive: true });
106710
107070
  let totalFrames = 0;
106711
107071
  const sortedTasks = [...tasks].sort((a, b) => a.startFrame - b.startFrame);
106712
107072
  for (const task of sortedTasks) {
106713
- if (!existsSync10(task.outputDir)) {
107073
+ if (!existsSync11(task.outputDir)) {
106714
107074
  continue;
106715
107075
  }
106716
- const files = readdirSync5(task.outputDir).filter((f) => f.startsWith("frame_") && (f.endsWith(".jpg") || f.endsWith(".png"))).sort();
107076
+ const files = readdirSync6(task.outputDir).filter((f) => f.startsWith("frame_") && (f.endsWith(".jpg") || f.endsWith(".png"))).sort();
106717
107077
  const copyTasks = files.map(async (file) => {
106718
- const sourcePath = join10(task.outputDir, file);
106719
- const targetPath = join10(outputDir, file);
107078
+ const sourcePath = join11(task.outputDir, file);
107079
+ const targetPath = join11(outputDir, file);
106720
107080
  try {
106721
107081
  await rename2(sourcePath, targetPath);
106722
107082
  } catch {
@@ -107897,18 +108257,18 @@ var ridgedBurn = (from2, to, out, w, h, p) => {
107897
108257
  TRANSITIONS["ridged-burn"] = ridgedBurn;
107898
108258
 
107899
108259
  // src/services/renderOrchestrator.ts
107900
- import { join as join15, dirname as dirname10, resolve as resolve11 } from "path";
108260
+ import { join as join16, dirname as dirname10, resolve as resolve11 } from "path";
107901
108261
  import { randomUUID } from "crypto";
107902
108262
  import { freemem as freemem2 } from "os";
107903
108263
  import { fileURLToPath as fileURLToPath3 } from "url";
107904
108264
 
107905
108265
  // src/services/fileServer.ts
107906
- import { readFileSync as readFileSync7, existsSync as existsSync12, realpathSync, statSync as statSync5 } from "node:fs";
107907
- import { join as join11, extname as extname4, resolve as resolve8, sep } from "node:path";
108266
+ import { readFileSync as readFileSync7, existsSync as existsSync13, realpathSync, statSync as statSync6 } from "node:fs";
108267
+ import { join as join12, extname as extname4, resolve as resolve8, sep } from "node:path";
107908
108268
 
107909
108269
  // src/services/hyperframeRuntimeLoader.ts
107910
- import { createHash as createHash2 } from "node:crypto";
107911
- import { existsSync as existsSync11, readFileSync as readFileSync6 } from "node:fs";
108270
+ import { createHash as createHash3 } from "node:crypto";
108271
+ import { existsSync as existsSync12, readFileSync as readFileSync6 } from "node:fs";
107912
108272
  import { dirname as dirname8, resolve as resolve7 } from "node:path";
107913
108273
  import { fileURLToPath as fileURLToPath2 } from "node:url";
107914
108274
  var PRODUCER_DIR = dirname8(fileURLToPath2(import.meta.url));
@@ -107935,7 +108295,7 @@ function resolveHyperframeManifestPath() {
107935
108295
  MODULE_RELATIVE_MANIFEST_PATH
107936
108296
  ];
107937
108297
  for (const candidate of candidates) {
107938
- if (existsSync11(candidate)) {
108298
+ if (existsSync12(candidate)) {
107939
108299
  return candidate;
107940
108300
  }
107941
108301
  }
@@ -107946,7 +108306,7 @@ function getVerifiedHyperframeRuntimeSource() {
107946
108306
  }
107947
108307
  function resolveVerifiedHyperframeRuntime() {
107948
108308
  const manifestPath = resolveHyperframeManifestPath();
107949
- if (!existsSync11(manifestPath)) {
108309
+ if (!existsSync12(manifestPath)) {
107950
108310
  throw new Error(
107951
108311
  `[HyperframeRuntimeLoader] Missing manifest at ${manifestPath}. Build core runtime artifacts before rendering.`
107952
108312
  );
@@ -107960,11 +108320,11 @@ function resolveVerifiedHyperframeRuntime() {
107960
108320
  );
107961
108321
  }
107962
108322
  const runtimePath = resolve7(dirname8(manifestPath), runtimeFileName);
107963
- if (!existsSync11(runtimePath)) {
108323
+ if (!existsSync12(runtimePath)) {
107964
108324
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
107965
108325
  }
107966
108326
  const runtimeSource = readFileSync6(runtimePath, "utf8");
107967
- const runtimeSha = createHash2("sha256").update(runtimeSource, "utf8").digest("hex");
108327
+ const runtimeSha = createHash3("sha256").update(runtimeSource, "utf8").digest("hex");
107968
108328
  if (runtimeSha !== manifest.sha256) {
107969
108329
  throw new Error(
107970
108330
  `[HyperframeRuntimeLoader] Runtime checksum mismatch. expected=${manifest.sha256} actual=${runtimeSha}`
@@ -107986,8 +108346,8 @@ function isPathInside(child, parent, options = {}) {
107986
108346
  const separator = pathModule?.sep ?? sep;
107987
108347
  const resolvedChild = resolveFn(child);
107988
108348
  const resolvedParent = resolveFn(parent);
107989
- const normalizedChild = resolveSymlinks && existsSync12(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
107990
- const normalizedParent = resolveSymlinks && existsSync12(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
108349
+ const normalizedChild = resolveSymlinks && existsSync13(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
108350
+ const normalizedParent = resolveSymlinks && existsSync13(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
107991
108351
  if (normalizedChild === normalizedParent) return true;
107992
108352
  const parentWithSep = normalizedParent.endsWith(separator) ? normalizedParent : normalizedParent + separator;
107993
108353
  return normalizedChild.startsWith(parentWithSep);
@@ -108386,14 +108746,14 @@ function createFileServer2(options) {
108386
108746
  const relativePath = requestPath.replace(/^\//, "");
108387
108747
  let filePath = null;
108388
108748
  if (compiledDir) {
108389
- const candidate = join11(compiledDir, relativePath);
108390
- if (existsSync12(candidate) && isPathInside(candidate, compiledDir, { resolveSymlinks: true }) && statSync5(candidate).isFile()) {
108749
+ const candidate = join12(compiledDir, relativePath);
108750
+ if (existsSync13(candidate) && isPathInside(candidate, compiledDir, { resolveSymlinks: true }) && statSync6(candidate).isFile()) {
108391
108751
  filePath = candidate;
108392
108752
  }
108393
108753
  }
108394
108754
  if (!filePath) {
108395
- const candidate = join11(projectDir, relativePath);
108396
- if (existsSync12(candidate) && isPathInside(candidate, projectDir, { resolveSymlinks: true }) && statSync5(candidate).isFile()) {
108755
+ const candidate = join12(projectDir, relativePath);
108756
+ if (existsSync13(candidate) && isPathInside(candidate, projectDir, { resolveSymlinks: true }) && statSync6(candidate).isFile()) {
108397
108757
  filePath = candidate;
108398
108758
  }
108399
108759
  }
@@ -108442,12 +108802,12 @@ function createFileServer2(options) {
108442
108802
  }
108443
108803
 
108444
108804
  // src/services/htmlCompiler.ts
108445
- import { readFileSync as readFileSync9, existsSync as existsSync14, mkdirSync as mkdirSync9 } from "fs";
108446
- import { join as join14, dirname as dirname9, resolve as resolve10 } from "path";
108805
+ import { readFileSync as readFileSync9, existsSync as existsSync15, mkdirSync as mkdirSync10 } from "fs";
108806
+ import { join as join15, dirname as dirname9, resolve as resolve10 } from "path";
108447
108807
  import postcss from "postcss";
108448
108808
 
108449
108809
  // src/utils/paths.ts
108450
- import { resolve as resolve9, basename as basename2, join as join12, relative as relative2, isAbsolute as isAbsolute4 } from "node:path";
108810
+ import { resolve as resolve9, basename as basename2, join as join13, relative as relative2, isAbsolute as isAbsolute4 } from "node:path";
108451
108811
  var DEFAULT_RENDERS_DIR = process.env.PRODUCER_RENDERS_DIR ?? resolve9(new URL(import.meta.url).pathname, "../../..", "renders");
108452
108812
  function isPathInside2(childPath, parentPath) {
108453
108813
  const absChild = resolve9(childPath);
@@ -108469,15 +108829,15 @@ function toExternalAssetKey(absPath) {
108469
108829
  function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
108470
108830
  const absoluteProjectDir = resolve9(projectDir);
108471
108831
  const projectName = basename2(absoluteProjectDir);
108472
- const resolvedOutputPath = outputPath ?? join12(rendersDir, `${projectName}.mp4`);
108832
+ const resolvedOutputPath = outputPath ?? join13(rendersDir, `${projectName}.mp4`);
108473
108833
  const absoluteOutputPath = resolve9(resolvedOutputPath);
108474
108834
  return { absoluteProjectDir, absoluteOutputPath };
108475
108835
  }
108476
108836
 
108477
108837
  // src/services/deterministicFonts.ts
108478
- import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "node:fs";
108838
+ import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "node:fs";
108479
108839
  import { homedir as homedir2 } from "node:os";
108480
- import { join as join13 } from "node:path";
108840
+ import { join as join14 } from "node:path";
108481
108841
 
108482
108842
  // src/services/fontData.generated.ts
108483
108843
  var EMBEDDED_FONT_DATA = /* @__PURE__ */ new Map([
@@ -108755,20 +109115,20 @@ function warnUnresolvedFonts(unresolved) {
108755
109115
  Docs: https://hyperframes.heygen.com/docs/fonts`
108756
109116
  );
108757
109117
  }
108758
- var GOOGLE_FONTS_CACHE_DIR = join13(homedir2(), ".cache", "hyperframes", "fonts");
109118
+ var GOOGLE_FONTS_CACHE_DIR = join14(homedir2(), ".cache", "hyperframes", "fonts");
108759
109119
  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";
108760
109120
  function fontSlug(familyName) {
108761
109121
  return familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
108762
109122
  }
108763
109123
  function fontCacheDir(slug) {
108764
- const dir = join13(GOOGLE_FONTS_CACHE_DIR, slug);
108765
- if (!existsSync13(dir)) {
108766
- mkdirSync8(dir, { recursive: true });
109124
+ const dir = join14(GOOGLE_FONTS_CACHE_DIR, slug);
109125
+ if (!existsSync14(dir)) {
109126
+ mkdirSync9(dir, { recursive: true });
108767
109127
  }
108768
109128
  return dir;
108769
109129
  }
108770
109130
  function cachedWoff2Path(slug, weight, style) {
108771
- return join13(fontCacheDir(slug), `${weight}-${style}.woff2`);
109131
+ return join14(fontCacheDir(slug), `${weight}-${style}.woff2`);
108772
109132
  }
108773
109133
  async function fetchGoogleFont(familyName) {
108774
109134
  const slug = fontSlug(familyName);
@@ -108794,12 +109154,12 @@ async function fetchGoogleFont(familyName) {
108794
109154
  const woff2Url = match2[3] || "";
108795
109155
  if (!woff2Url) continue;
108796
109156
  const cachePath = cachedWoff2Path(slug, weight, style);
108797
- if (!existsSync13(cachePath)) {
109157
+ if (!existsSync14(cachePath)) {
108798
109158
  try {
108799
109159
  const fontRes = await fetch(woff2Url);
108800
109160
  if (!fontRes.ok) continue;
108801
109161
  const buffer = Buffer.from(await fontRes.arrayBuffer());
108802
- writeFileSync3(cachePath, buffer);
109162
+ writeFileSync4(cachePath, buffer);
108803
109163
  } catch {
108804
109164
  continue;
108805
109165
  }
@@ -108905,16 +109265,16 @@ function detectRenderModeHints(html) {
108905
109265
  async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagName19) {
108906
109266
  let filePath = src;
108907
109267
  if (isHttpUrl(src)) {
108908
- if (!existsSync14(downloadDir)) mkdirSync9(downloadDir, { recursive: true });
109268
+ if (!existsSync15(downloadDir)) mkdirSync10(downloadDir, { recursive: true });
108909
109269
  try {
108910
109270
  filePath = await downloadToTemp(src, downloadDir);
108911
109271
  } catch {
108912
109272
  return { duration: 0, resolvedPath: src };
108913
109273
  }
108914
109274
  } else if (!filePath.startsWith("/")) {
108915
- filePath = join14(baseDir, filePath);
109275
+ filePath = join15(baseDir, filePath);
108916
109276
  }
108917
- if (!existsSync14(filePath)) {
109277
+ if (!existsSync15(filePath)) {
108918
109278
  return { duration: 0, resolvedPath: filePath };
108919
109279
  }
108920
109280
  const metadata = tagName19 === "video" ? await extractMediaMetadata(filePath) : await extractAudioMetadata(filePath);
@@ -108983,7 +109343,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
108983
109343
  if (visited.has(filePath)) {
108984
109344
  continue;
108985
109345
  }
108986
- if (!existsSync14(filePath)) {
109346
+ if (!existsSync15(filePath)) {
108987
109347
  continue;
108988
109348
  }
108989
109349
  const rawSubHtml = readFileSync9(filePath, "utf-8");
@@ -109193,7 +109553,7 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
109193
109553
  let compHtml = subCompositions.get(srcPath) || null;
109194
109554
  if (!compHtml) {
109195
109555
  const filePath = resolve10(projectDir, srcPath);
109196
- if (existsSync14(filePath)) {
109556
+ if (existsSync15(filePath)) {
109197
109557
  compHtml = readFileSync9(filePath, "utf-8");
109198
109558
  }
109199
109559
  }
@@ -109421,7 +109781,7 @@ function collectExternalAssets(html, projectDir) {
109421
109781
  if (isPathInside2(absPath, absProjectDir)) {
109422
109782
  return null;
109423
109783
  }
109424
- if (!existsSync14(absPath)) return null;
109784
+ if (!existsSync15(absPath)) return null;
109425
109785
  const safeKey = toExternalAssetKey(absPath);
109426
109786
  externalAssets.set(safeKey, absPath);
109427
109787
  return safeKey;
@@ -109617,9 +109977,10 @@ async function recompileWithResolutions(compiled, resolutions, projectDir, downl
109617
109977
  const mainVideos = parseVideoElements(html);
109618
109978
  const mainAudios = parseAudioElements(html);
109619
109979
  const mainImages = parseImageElements(html);
109620
- const videos = dedupeElementsById([...mainVideos, ...subVideos]);
109621
- const audios = dedupeElementsById([...mainAudios, ...subAudios]);
109622
- const images = dedupeElementsById([...mainImages, ...subImages]);
109980
+ const hasSubMedia = subVideos.length > 0 || subAudios.length > 0 || subImages.length > 0;
109981
+ const videos = hasSubMedia ? dedupeElementsById([...mainVideos, ...subVideos]) : compiled.videos;
109982
+ const audios = hasSubMedia ? dedupeElementsById([...mainAudios, ...subAudios]) : compiled.audios;
109983
+ const images = hasSubMedia ? dedupeElementsById([...mainImages, ...subImages]) : compiled.images;
109623
109984
  const remaining = compiled.unresolvedCompositions.filter(
109624
109985
  (c) => !resolutions.some((r) => r.id === c.id)
109625
109986
  );
@@ -109674,24 +110035,21 @@ function createConsoleLogger(level = "info") {
109674
110035
  }
109675
110036
  var defaultLogger = createConsoleLogger("info");
109676
110037
 
109677
- // src/services/renderOrchestrator.ts
109678
- async function safeCleanup(label, fn, log = defaultLogger) {
109679
- try {
109680
- await fn();
109681
- } catch (err) {
109682
- log.debug(`Cleanup failed (${label})`, {
109683
- error: err instanceof Error ? err.message : String(err)
109684
- });
109685
- }
109686
- }
109687
- var frameDirMaxIndexCache = /* @__PURE__ */ new Map();
110038
+ // src/services/frameDirCache.ts
110039
+ import { readdirSync as readdirSync7 } from "fs";
110040
+ var cache = /* @__PURE__ */ new Map();
109688
110041
  var FRAME_FILENAME_RE = /^frame_(\d+)\.png$/;
110042
+ var MAX_ENTRIES = 1e3;
109689
110043
  function getMaxFrameIndex(frameDir) {
109690
- const cached = frameDirMaxIndexCache.get(frameDir);
109691
- if (cached !== void 0) return cached;
110044
+ const cached = cache.get(frameDir);
110045
+ if (cached !== void 0) {
110046
+ cache.delete(frameDir);
110047
+ cache.set(frameDir, cached);
110048
+ return cached;
110049
+ }
109692
110050
  let max = 0;
109693
110051
  try {
109694
- for (const name of readdirSync6(frameDir)) {
110052
+ for (const name of readdirSync7(frameDir)) {
109695
110053
  const m = FRAME_FILENAME_RE.exec(name);
109696
110054
  if (!m) continue;
109697
110055
  const n = Number(m[1]);
@@ -109699,9 +110057,113 @@ function getMaxFrameIndex(frameDir) {
109699
110057
  }
109700
110058
  } catch {
109701
110059
  }
109702
- frameDirMaxIndexCache.set(frameDir, max);
110060
+ if (cache.size >= MAX_ENTRIES) {
110061
+ const oldest = cache.keys().next().value;
110062
+ if (oldest !== void 0) cache.delete(oldest);
110063
+ }
110064
+ cache.set(frameDir, max);
109703
110065
  return max;
109704
110066
  }
110067
+ function clearMaxFrameIndex(frameDir) {
110068
+ return cache.delete(frameDir);
110069
+ }
110070
+
110071
+ // src/services/hdrImageTransferCache.ts
110072
+ var DEFAULT_MAX_BYTES = 200 * 1024 * 1024;
110073
+ function createHdrImageTransferCache(options = {}) {
110074
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
110075
+ if (!Number.isInteger(maxBytes) || maxBytes < 0) {
110076
+ throw new Error(
110077
+ `createHdrImageTransferCache: maxBytes must be a non-negative integer, got ${String(maxBytes)}`
110078
+ );
110079
+ }
110080
+ const entries2 = /* @__PURE__ */ new Map();
110081
+ let totalBytes = 0;
110082
+ function makeKey(imageId, targetTransfer) {
110083
+ return `${imageId}|${targetTransfer}`;
110084
+ }
110085
+ function evictUntilRoom(needed) {
110086
+ while (totalBytes + needed > maxBytes && entries2.size > 0) {
110087
+ const lruKey = entries2.keys().next().value;
110088
+ if (lruKey === void 0) break;
110089
+ const evicted = entries2.get(lruKey);
110090
+ if (evicted) totalBytes -= evicted.byteLength;
110091
+ entries2.delete(lruKey);
110092
+ }
110093
+ }
110094
+ return {
110095
+ getConverted(imageId, sourceTransfer, targetTransfer, source2) {
110096
+ if (sourceTransfer === targetTransfer) {
110097
+ return source2;
110098
+ }
110099
+ if (maxBytes === 0) {
110100
+ const fresh = Buffer.from(source2);
110101
+ convertTransfer(fresh, sourceTransfer, targetTransfer);
110102
+ return fresh;
110103
+ }
110104
+ const key2 = makeKey(imageId, targetTransfer);
110105
+ const existing = entries2.get(key2);
110106
+ if (existing) {
110107
+ entries2.delete(key2);
110108
+ entries2.set(key2, existing);
110109
+ return existing;
110110
+ }
110111
+ const converted = Buffer.from(source2);
110112
+ convertTransfer(converted, sourceTransfer, targetTransfer);
110113
+ if (converted.byteLength > maxBytes) {
110114
+ return converted;
110115
+ }
110116
+ evictUntilRoom(converted.byteLength);
110117
+ entries2.set(key2, converted);
110118
+ totalBytes += converted.byteLength;
110119
+ return converted;
110120
+ },
110121
+ size() {
110122
+ return entries2.size;
110123
+ },
110124
+ bytesUsed() {
110125
+ return totalBytes;
110126
+ }
110127
+ };
110128
+ }
110129
+
110130
+ // src/services/renderOrchestrator.ts
110131
+ async function safeCleanup(label, fn, log = defaultLogger) {
110132
+ try {
110133
+ await fn();
110134
+ } catch (err) {
110135
+ log.debug(`Cleanup failed (${label})`, {
110136
+ error: err instanceof Error ? err.message : String(err)
110137
+ });
110138
+ }
110139
+ }
110140
+ function sampleDirectoryBytes(dir) {
110141
+ let total = 0;
110142
+ const stack = [dir];
110143
+ while (stack.length > 0) {
110144
+ const current = stack.pop();
110145
+ if (!current) continue;
110146
+ let entries2 = [];
110147
+ try {
110148
+ entries2 = readdirSync8(current);
110149
+ } catch {
110150
+ continue;
110151
+ }
110152
+ for (const name of entries2) {
110153
+ const full = join16(current, name);
110154
+ try {
110155
+ const st = statSync7(full);
110156
+ if (st.isDirectory()) {
110157
+ stack.push(full);
110158
+ } else if (st.isFile()) {
110159
+ total += st.size;
110160
+ }
110161
+ } catch {
110162
+ }
110163
+ }
110164
+ }
110165
+ return total;
110166
+ }
109705
110167
  function countNonZeroAlpha(rgba) {
109706
110168
  let n = 0;
109707
110169
  for (let p = 3; p < rgba.length; p += 4) {
@@ -109725,6 +110187,10 @@ var RenderCancelledError = class extends Error {
109725
110187
  this.reason = reason;
109726
110188
  }
109727
110189
  };
110190
+ var BROWSER_MEDIA_EPSILON = 1e-4;
110191
+ function projectBrowserEndToCompositionTimeline(existingStart, browserStart, browserEnd) {
110192
+ return browserEnd + (existingStart - browserStart);
110193
+ }
109728
110194
  function updateJobStatus(job, status, stage, progress, onProgress) {
109729
110195
  job.status = status;
109730
110196
  job.currentStage = stage;
@@ -109768,21 +110234,21 @@ function installDebugLogger(logPath, log = defaultLogger) {
109768
110234
  };
109769
110235
  }
109770
110236
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
109771
- const compileDir = join15(workDir, "compiled");
109772
- mkdirSync10(compileDir, { recursive: true });
109773
- writeFileSync4(join15(compileDir, "index.html"), compiled.html, "utf-8");
110237
+ const compileDir = join16(workDir, "compiled");
110238
+ mkdirSync11(compileDir, { recursive: true });
110239
+ writeFileSync5(join16(compileDir, "index.html"), compiled.html, "utf-8");
109774
110240
  for (const [srcPath, html] of compiled.subCompositions) {
109775
- const outPath = join15(compileDir, srcPath);
109776
- mkdirSync10(dirname10(outPath), { recursive: true });
109777
- writeFileSync4(outPath, html, "utf-8");
110241
+ const outPath = join16(compileDir, srcPath);
110242
+ mkdirSync11(dirname10(outPath), { recursive: true });
110243
+ writeFileSync5(outPath, html, "utf-8");
109778
110244
  }
109779
110245
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
109780
- const outPath = resolve11(join15(compileDir, relativePath));
110246
+ const outPath = resolve11(join16(compileDir, relativePath));
109781
110247
  if (!isPathInside2(outPath, compileDir)) {
109782
110248
  console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
109783
110249
  continue;
109784
110250
  }
109785
- mkdirSync10(dirname10(outPath), { recursive: true });
110251
+ mkdirSync11(dirname10(outPath), { recursive: true });
109786
110252
  copyFileSync2(absolutePath, outPath);
109787
110253
  }
109788
110254
  if (includeSummary) {
@@ -109807,7 +110273,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
109807
110273
  subCompositions: Array.from(compiled.subCompositions.keys()),
109808
110274
  renderModeHints: compiled.renderModeHints
109809
110275
  };
109810
- writeFileSync4(join15(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
110276
+ writeFileSync5(join16(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
109811
110277
  }
109812
110278
  }
109813
110279
  function applyRenderModeHints(cfg, compiled, log = defaultLogger) {
@@ -109828,8 +110294,8 @@ function blitHdrVideoLayer(canvas, el, time, fps, hdrFrameDirs, hdrStartTimes, w
109828
110294
  if (videoFrameIndex < 1) return;
109829
110295
  const maxIndex = getMaxFrameIndex(frameDir);
109830
110296
  const effectiveIndex = maxIndex > 0 ? Math.min(videoFrameIndex, maxIndex) : videoFrameIndex;
109831
- const framePath = join15(frameDir, `frame_${String(effectiveIndex).padStart(4, "0")}.png`);
109832
- if (!existsSync15(framePath)) {
110297
+ const framePath = join16(frameDir, `frame_${String(effectiveIndex).padStart(4, "0")}.png`);
110298
+ if (!existsSync16(framePath)) {
109833
110299
  return;
109834
110300
  }
109835
110301
  try {
@@ -109875,17 +110341,13 @@ function blitHdrVideoLayer(canvas, el, time, fps, hdrFrameDirs, hdrStartTimes, w
109875
110341
  }
109876
110342
  }
109877
110343
  }
109878
- function blitHdrImageLayer(canvas, el, hdrImageBuffers, width, height, log, sourceTransfer, targetTransfer) {
110344
+ function blitHdrImageLayer(canvas, el, hdrImageBuffers, hdrImageTransferCache, width, height, log, sourceTransfer, targetTransfer) {
109879
110345
  const buf = hdrImageBuffers.get(el.id);
109880
110346
  if (!buf) {
109881
110347
  return;
109882
110348
  }
109883
110349
  try {
109884
- let hdrRgb = buf.data;
109885
- if (sourceTransfer && targetTransfer && sourceTransfer !== targetTransfer) {
109886
- hdrRgb = Buffer.from(buf.data);
109887
- convertTransfer(hdrRgb, sourceTransfer, targetTransfer);
109888
- }
110350
+ const hdrRgb = sourceTransfer && targetTransfer ? hdrImageTransferCache.getConverted(el.id, sourceTransfer, targetTransfer, buf.data) : buf.data;
109889
110351
  const viewportMatrix = parseTransformMatrix(el.transform);
109890
110352
  const br = el.borderRadius;
109891
110353
  const hasBorderRadius = br[0] > 0 || br[1] > 0 || br[2] > 0 || br[3] > 0;
@@ -109935,6 +110397,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
109935
110397
  effectiveHdr,
109936
110398
  nativeHdrImageIds,
109937
110399
  hdrImageBuffers,
110400
+ hdrImageTransferCache,
109938
110401
  hdrFrameDirs,
109939
110402
  hdrVideoStartTimes,
109940
110403
  imageTransfers,
@@ -109974,6 +110437,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
109974
110437
  canvas,
109975
110438
  layer.element,
109976
110439
  hdrImageBuffers,
110440
+ hdrImageTransferCache,
109977
110441
  width,
109978
110442
  height,
109979
110443
  log,
@@ -110014,7 +110478,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
110014
110478
  const startTime = hdrVideoStartTimes.get(layer.element.id) ?? 0;
110015
110479
  const localTime = time - startTime;
110016
110480
  const frameNum = Math.floor(localTime * fps) + 1;
110017
- const expectedFrame = frameDir ? join15(frameDir, `frame_${String(frameNum).padStart(4, "0")}.png`) : null;
110481
+ const expectedFrame = frameDir ? join16(frameDir, `frame_${String(frameNum).padStart(4, "0")}.png`) : null;
110018
110482
  log.info("[diag] hdr layer blit", {
110019
110483
  frame: debugFrameIndex,
110020
110484
  layerIdx,
@@ -110026,7 +110490,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
110026
110490
  localTime: localTime.toFixed(3),
110027
110491
  hdrFrameNum: frameNum,
110028
110492
  expectedFrame,
110029
- expectedFrameExists: expectedFrame ? existsSync15(expectedFrame) : false
110493
+ expectedFrameExists: expectedFrame ? existsSync16(expectedFrame) : false
110030
110494
  });
110031
110495
  }
110032
110496
  }
@@ -110051,8 +110515,8 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
110051
110515
  if (shouldLog && debugDumpDir) {
110052
110516
  const after2 = countNonZeroRgb48(canvas);
110053
110517
  const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
110054
- const dumpPath = join15(debugDumpDir, dumpName);
110055
- writeFileSync4(dumpPath, domPng);
110518
+ const dumpPath = join16(debugDumpDir, dumpName);
110519
+ writeFileSync5(dumpPath, domPng);
110056
110520
  log.info("[diag] dom layer blit", {
110057
110521
  frame: debugFrameIndex,
110058
110522
  layerIdx,
@@ -110125,8 +110589,8 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
110125
110589
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
110126
110590
  const moduleDir = dirname10(fileURLToPath3(import.meta.url));
110127
110591
  const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve11(process.env.PRODUCER_RENDERS_DIR, "..") : resolve11(moduleDir, "../..");
110128
- const debugDir = join15(producerRoot, ".debug");
110129
- const workDir = job.config.debug ? join15(debugDir, job.id) : join15(dirname10(outputPath), `work-${job.id}`);
110592
+ const debugDir = join16(producerRoot, ".debug");
110593
+ const workDir = job.config.debug ? join16(debugDir, job.id) : join16(dirname10(outputPath), `work-${job.id}`);
110130
110594
  const pipelineStart = Date.now();
110131
110595
  const log = job.config.logger ?? defaultLogger;
110132
110596
  let fileServer = null;
@@ -110138,7 +110602,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110138
110602
  videoExtractionFailures: 0,
110139
110603
  imageDecodeFailures: 0
110140
110604
  };
110141
- const perfOutputPath = join15(workDir, "perf-summary.json");
110605
+ const perfOutputPath = join16(workDir, "perf-summary.json");
110142
110606
  const cfg = { ...job.config.producerConfig ?? resolveConfig() };
110143
110607
  const outputFormat = job.config.format ?? "mp4";
110144
110608
  const isWebm = outputFormat === "webm";
@@ -110171,22 +110635,22 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110171
110635
  };
110172
110636
  job.startedAt = /* @__PURE__ */ new Date();
110173
110637
  assertNotAborted();
110174
- if (!existsSync15(workDir)) mkdirSync10(workDir, { recursive: true });
110638
+ if (!existsSync16(workDir)) mkdirSync11(workDir, { recursive: true });
110175
110639
  if (job.config.debug) {
110176
- const logPath = join15(workDir, "render.log");
110640
+ const logPath = join16(workDir, "render.log");
110177
110641
  restoreLogger = installDebugLogger(logPath, log);
110178
110642
  }
110179
110643
  const entryFile = job.config.entryFile || "index.html";
110180
- let htmlPath = join15(projectDir, entryFile);
110181
- if (!existsSync15(htmlPath)) {
110644
+ let htmlPath = join16(projectDir, entryFile);
110645
+ if (!existsSync16(htmlPath)) {
110182
110646
  throw new Error(`Entry file not found: ${htmlPath}`);
110183
110647
  }
110184
110648
  assertNotAborted();
110185
110649
  const rawEntry = readFileSync10(htmlPath, "utf-8");
110186
110650
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
110187
- const wrapperPath = join15(workDir, "standalone-entry.html");
110188
- const projectIndexPath = join15(projectDir, "index.html");
110189
- if (!existsSync15(projectIndexPath)) {
110651
+ const wrapperPath = join16(workDir, "standalone-entry.html");
110652
+ const projectIndexPath = join16(projectDir, "index.html");
110653
+ if (!existsSync16(projectIndexPath)) {
110190
110654
  throw new Error(
110191
110655
  `Template entry file "${entryFile}" requires a project index.html to extract its render shell.`
110192
110656
  );
@@ -110200,7 +110664,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110200
110664
  `Entry file "${entryFile}" is not mounted from index.html via data-composition-src, so it cannot be rendered independently.`
110201
110665
  );
110202
110666
  }
110203
- writeFileSync4(wrapperPath, standaloneHtml, "utf-8");
110667
+ writeFileSync5(wrapperPath, standaloneHtml, "utf-8");
110204
110668
  htmlPath = wrapperPath;
110205
110669
  log.info("Extracted standalone entry from index.html host context", {
110206
110670
  entryFile
@@ -110209,7 +110673,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110209
110673
  const stage1Start = Date.now();
110210
110674
  updateJobStatus(job, "preprocessing", "Compiling composition", 5, onProgress);
110211
110675
  const compileStart = Date.now();
110212
- let compiled = await compileForRender(projectDir, htmlPath, join15(workDir, "downloads"));
110676
+ let compiled = await compileForRender(projectDir, htmlPath, join16(workDir, "downloads"));
110213
110677
  assertNotAborted();
110214
110678
  perfStages.compileOnlyMs = Date.now() - compileStart;
110215
110679
  applyRenderModeHints(cfg, compiled, log);
@@ -110241,7 +110705,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110241
110705
  reasons.push(`${compiled.unresolvedCompositions.length} unresolved composition(s)`);
110242
110706
  fileServer = await createFileServer2({
110243
110707
  projectDir,
110244
- compiledDir: join15(workDir, "compiled"),
110708
+ compiledDir: join16(workDir, "compiled"),
110245
110709
  port: 0,
110246
110710
  preHeadScripts: [VIRTUAL_TIME_SHIM]
110247
110711
  });
@@ -110255,7 +110719,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110255
110719
  };
110256
110720
  probeSession = await createCaptureSession(
110257
110721
  fileServer.url,
110258
- join15(workDir, "probe"),
110722
+ join16(workDir, "probe"),
110259
110723
  captureOpts,
110260
110724
  null,
110261
110725
  cfg
@@ -110287,7 +110751,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110287
110751
  compiled,
110288
110752
  resolutions,
110289
110753
  projectDir,
110290
- join15(workDir, "downloads")
110754
+ join16(workDir, "downloads")
110291
110755
  );
110292
110756
  assertNotAborted();
110293
110757
  composition.videos = compiled.videos;
@@ -110314,10 +110778,15 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110314
110778
  if (existing.src !== src) {
110315
110779
  existing.src = src;
110316
110780
  }
110317
- if (el.end > 0 && (existing.end <= 0 || Math.abs(existing.end - el.end) > 1e-4)) {
110318
- existing.end = el.end;
110781
+ const projectedEnd = projectBrowserEndToCompositionTimeline(
110782
+ existing.start,
110783
+ el.start,
110784
+ el.end
110785
+ );
110786
+ if (projectedEnd > 0 && (existing.end <= 0 || Math.abs(existing.end - projectedEnd) > BROWSER_MEDIA_EPSILON)) {
110787
+ existing.end = projectedEnd;
110319
110788
  }
110320
- if (el.mediaStart > 0 && (existing.mediaStart <= 0 || Math.abs(existing.mediaStart - el.mediaStart) > 1e-4)) {
110789
+ if (el.mediaStart > 0 && (existing.mediaStart <= 0 || Math.abs(existing.mediaStart - el.mediaStart) > BROWSER_MEDIA_EPSILON)) {
110321
110790
  existing.mediaStart = el.mediaStart;
110322
110791
  }
110323
110792
  if (el.hasAudio && !existing.hasAudio) {
@@ -110342,13 +110811,18 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110342
110811
  if (existing.src !== src) {
110343
110812
  existing.src = src;
110344
110813
  }
110345
- if (el.end > 0 && (existing.end <= 0 || Math.abs(existing.end - el.end) > 1e-4)) {
110346
- existing.end = el.end;
110814
+ const projectedEnd = projectBrowserEndToCompositionTimeline(
110815
+ existing.start,
110816
+ el.start,
110817
+ el.end
110818
+ );
110819
+ if (projectedEnd > 0 && (existing.end <= 0 || Math.abs(existing.end - projectedEnd) > BROWSER_MEDIA_EPSILON)) {
110820
+ existing.end = projectedEnd;
110347
110821
  }
110348
- if (el.mediaStart > 0 && (existing.mediaStart <= 0 || Math.abs(existing.mediaStart - el.mediaStart) > 1e-4)) {
110822
+ if (el.mediaStart > 0 && (existing.mediaStart <= 0 || Math.abs(existing.mediaStart - el.mediaStart) > BROWSER_MEDIA_EPSILON)) {
110349
110823
  existing.mediaStart = el.mediaStart;
110350
110824
  }
110351
- if (el.volume > 0 && Math.abs((existing.volume ?? 1) - el.volume) > 1e-4) {
110825
+ if (el.volume > 0 && Math.abs((existing.volume ?? 1) - el.volume) > BROWSER_MEDIA_EPSILON) {
110352
110826
  existing.volume = el.volume;
110353
110827
  }
110354
110828
  }
@@ -110427,7 +110901,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110427
110901
  const stage2Start = Date.now();
110428
110902
  updateJobStatus(job, "preprocessing", "Extracting video frames", 10, onProgress);
110429
110903
  let frameLookup = null;
110430
- const compiledDir = join15(workDir, "compiled");
110904
+ const compiledDir = join16(workDir, "compiled");
110431
110905
  let extractionResult = null;
110432
110906
  const nativeHdrVideoIds = /* @__PURE__ */ new Set();
110433
110907
  const videoTransfers = /* @__PURE__ */ new Map();
@@ -110436,10 +110910,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110436
110910
  composition.videos.map(async (v) => {
110437
110911
  let videoPath = v.src;
110438
110912
  if (!videoPath.startsWith("/")) {
110439
- const fromCompiled = existsSync15(join15(compiledDir, videoPath)) ? join15(compiledDir, videoPath) : join15(projectDir, videoPath);
110913
+ const fromCompiled = existsSync16(join16(compiledDir, videoPath)) ? join16(compiledDir, videoPath) : join16(projectDir, videoPath);
110440
110914
  videoPath = fromCompiled;
110441
110915
  }
110442
- if (!existsSync15(videoPath)) return;
110916
+ if (!existsSync16(videoPath)) return;
110443
110917
  const meta = await extractMediaMetadata(videoPath);
110444
110918
  if (isHdrColorSpace(meta.colorSpace)) {
110445
110919
  nativeHdrVideoIds.add(v.id);
@@ -110457,10 +110931,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110457
110931
  composition.images.map(async (img) => {
110458
110932
  let imgPath = img.src;
110459
110933
  if (!imgPath.startsWith("/")) {
110460
- const fromCompiled = existsSync15(join15(compiledDir, imgPath)) ? join15(compiledDir, imgPath) : join15(projectDir, imgPath);
110934
+ const fromCompiled = existsSync16(join16(compiledDir, imgPath)) ? join16(compiledDir, imgPath) : join16(projectDir, imgPath);
110461
110935
  imgPath = fromCompiled;
110462
110936
  }
110463
- if (!existsSync15(imgPath)) return null;
110937
+ if (!existsSync16(imgPath)) return null;
110464
110938
  const meta = await extractMediaMetadata(imgPath);
110465
110939
  if (isHdrColorSpace(meta.colorSpace)) {
110466
110940
  nativeHdrImageIds.add(img.id);
@@ -110476,9 +110950,9 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110476
110950
  extractionResult = await extractAllVideoFrames(
110477
110951
  composition.videos,
110478
110952
  projectDir,
110479
- { fps: job.config.fps, outputDir: join15(workDir, "video-frames") },
110953
+ { fps: job.config.fps, outputDir: join16(workDir, "video-frames") },
110480
110954
  abortSignal,
110481
- void 0,
110955
+ { extractCacheDir: cfg.extractCacheDir },
110482
110956
  compiledDir
110483
110957
  );
110484
110958
  assertNotAborted();
@@ -110534,13 +111008,13 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110534
111008
  }
110535
111009
  const stage3Start = Date.now();
110536
111010
  updateJobStatus(job, "preprocessing", "Processing audio tracks", 20, onProgress);
110537
- const audioOutputPath = join15(workDir, "audio.aac");
111011
+ const audioOutputPath = join16(workDir, "audio.aac");
110538
111012
  let hasAudio = false;
110539
111013
  if (composition.audios.length > 0) {
110540
111014
  const audioResult = await processCompositionAudio(
110541
111015
  composition.audios,
110542
111016
  projectDir,
110543
- join15(workDir, "audio-work"),
111017
+ join16(workDir, "audio-work"),
110544
111018
  audioOutputPath,
110545
111019
  job.duration,
110546
111020
  abortSignal,
@@ -110558,14 +111032,14 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110558
111032
  if (!fileServer) {
110559
111033
  fileServer = await createFileServer2({
110560
111034
  projectDir,
110561
- compiledDir: join15(workDir, "compiled"),
111035
+ compiledDir: join16(workDir, "compiled"),
110562
111036
  port: 0,
110563
111037
  preHeadScripts: [VIRTUAL_TIME_SHIM]
110564
111038
  });
110565
111039
  assertNotAborted();
110566
111040
  }
110567
- const framesDir = join15(workDir, "captured-frames");
110568
- if (!existsSync15(framesDir)) mkdirSync10(framesDir, { recursive: true });
111041
+ const framesDir = join16(workDir, "captured-frames");
111042
+ if (!existsSync16(framesDir)) mkdirSync11(framesDir, { recursive: true });
110569
111043
  const captureOptions = {
110570
111044
  width,
110571
111045
  height,
@@ -110580,7 +111054,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110580
111054
  const workerCount = calculateOptimalWorkers(totalFrames, job.config.workers, cfg);
110581
111055
  const FORMAT_EXT = { mp4: ".mp4", webm: ".webm", mov: ".mov" };
110582
111056
  const videoExt = FORMAT_EXT[outputFormat] ?? ".mp4";
110583
- const videoOnlyPath = join15(workDir, `video-only${videoExt}`);
111057
+ const videoOnlyPath = join16(workDir, `video-only${videoExt}`);
110584
111058
  const nativeHdrIds = /* @__PURE__ */ new Set([...nativeHdrVideoIds, ...nativeHdrImageIds]);
110585
111059
  const hasHdrContent = effectiveHdr && nativeHdrIds.size > 0;
110586
111060
  const encoderHdr = hasHdrContent ? effectiveHdr : void 0;
@@ -110602,8 +111076,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110602
111076
  if (!hdrVideoIds.includes(v.id)) continue;
110603
111077
  let srcPath = v.src;
110604
111078
  if (!srcPath.startsWith("/")) {
110605
- const fromCompiled = join15(compiledDir, srcPath);
110606
- srcPath = existsSync15(fromCompiled) ? fromCompiled : join15(projectDir, srcPath);
111079
+ const fromCompiled = join16(compiledDir, srcPath);
111080
+ srcPath = existsSync16(fromCompiled) ? fromCompiled : join16(projectDir, srcPath);
110607
111081
  }
110608
111082
  hdrVideoSrcPaths.set(v.id, srcPath);
110609
111083
  }
@@ -110733,8 +111207,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110733
111207
  for (const [videoId, srcPath] of hdrVideoSrcPaths) {
110734
111208
  const video = composition.videos.find((v) => v.id === videoId);
110735
111209
  if (!video) continue;
110736
- const frameDir = join15(framesDir, `hdr_${videoId}`);
110737
- mkdirSync10(frameDir, { recursive: true });
111210
+ const frameDir = join16(framesDir, `hdr_${videoId}`);
111211
+ mkdirSync11(frameDir, { recursive: true });
110738
111212
  const duration = video.end - video.start;
110739
111213
  const dims = hdrExtractionDims.get(videoId) ?? { width, height };
110740
111214
  const ffmpegArgs = [
@@ -110753,7 +111227,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110753
111227
  "-c:v",
110754
111228
  "png",
110755
111229
  "-y",
110756
- join15(frameDir, "frame_%04d.png")
111230
+ join16(frameDir, "frame_%04d.png")
110757
111231
  ];
110758
111232
  const result = await runFfmpeg(ffmpegArgs, { signal: abortSignal });
110759
111233
  if (!result.success) {
@@ -110821,15 +111295,19 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110821
111295
  }
110822
111296
  }
110823
111297
  const debugDumpEnabled = process.env.KEEP_TEMP === "1";
110824
- const debugDumpDir = debugDumpEnabled ? join15(framesDir, "debug-composite") : null;
110825
- if (debugDumpDir && !existsSync15(debugDumpDir)) {
110826
- mkdirSync10(debugDumpDir, { recursive: true });
111298
+ const debugDumpDir = debugDumpEnabled ? join16(framesDir, "debug-composite") : null;
111299
+ if (debugDumpDir && !existsSync16(debugDumpDir)) {
111300
+ mkdirSync11(debugDumpDir, { recursive: true });
110827
111301
  }
110828
111302
  if (!effectiveHdr) {
110829
111303
  throw new Error(
110830
111304
  "Internal: HDR render path entered without effectiveHdr \u2014 this is a bug."
110831
111305
  );
110832
111306
  }
111307
+ const hdrCacheMaxBytes = process.env.HDR_TRANSFER_CACHE_MAX_BYTES ? Number(process.env.HDR_TRANSFER_CACHE_MAX_BYTES) : void 0;
111308
+ const hdrImageTransferCache = createHdrImageTransferCache(
111309
+ hdrCacheMaxBytes !== void 0 ? { maxBytes: hdrCacheMaxBytes } : {}
111310
+ );
110833
111311
  const hdrCompositeCtx = {
110834
111312
  log,
110835
111313
  domSession,
@@ -110840,6 +111318,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110840
111318
  effectiveHdr,
110841
111319
  nativeHdrImageIds,
110842
111320
  hdrImageBuffers,
111321
+ hdrImageTransferCache,
110843
111322
  hdrFrameDirs,
110844
111323
  hdrVideoStartTimes,
110845
111324
  imageTransfers,
@@ -110900,6 +111379,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110900
111379
  sceneBuf,
110901
111380
  el,
110902
111381
  hdrImageBuffers,
111382
+ hdrImageTransferCache,
110903
111383
  width,
110904
111384
  height,
110905
111385
  log,
@@ -110963,11 +111443,11 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110963
111443
  i
110964
111444
  );
110965
111445
  if (debugDumpEnabled && debugDumpDir && i % 30 === 0) {
110966
- const previewPath = join15(
111446
+ const previewPath = join16(
110967
111447
  debugDumpDir,
110968
111448
  `frame_${String(i).padStart(4, "0")}_final_rgb48le.bin`
110969
111449
  );
110970
- writeFileSync4(previewPath, normalCanvas);
111450
+ writeFileSync5(previewPath, normalCanvas);
110971
111451
  }
110972
111452
  hdrEncoder.writeFrame(normalCanvas);
110973
111453
  }
@@ -110987,7 +111467,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110987
111467
  error: err instanceof Error ? err.message : String(err)
110988
111468
  });
110989
111469
  }
110990
- frameDirMaxIndexCache.delete(frameDir);
111470
+ clearMaxFrameIndex(frameDir);
110991
111471
  hdrFrameDirs.delete(videoId);
110992
111472
  }
110993
111473
  cleanedUpVideos.add(videoId);
@@ -111038,7 +111518,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111038
111518
  });
111039
111519
  }
111040
111520
  for (const frameDir of hdrFrameDirs.values()) {
111041
- frameDirMaxIndexCache.delete(frameDir);
111521
+ clearMaxFrameIndex(frameDir);
111042
111522
  }
111043
111523
  hdrFrameDirs.clear();
111044
111524
  }
@@ -111310,6 +111790,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111310
111790
  updateJobStatus(job, "complete", "Render complete", 100, onProgress);
111311
111791
  const totalElapsed = Date.now() - pipelineStart;
111312
111792
  sampleMemory();
111793
+ const tmpPeakBytes = existsSync16(workDir) ? sampleDirectoryBytes(workDir) : 0;
111313
111794
  const perfSummary = {
111314
111795
  renderId: job.id,
111315
111796
  totalElapsedMs: totalElapsed,
@@ -111324,6 +111805,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111324
111805
  videoCount: composition.videos.length,
111325
111806
  audioCount: composition.audios.length,
111326
111807
  stages: perfStages,
111808
+ videoExtractBreakdown: extractionResult?.phaseBreakdown,
111809
+ tmpPeakBytes,
111327
111810
  hdrDiagnostics: hdrDiagnostics.videoExtractionFailures > 0 || hdrDiagnostics.imageDecodeFailures > 0 ? { ...hdrDiagnostics } : void 0,
111328
111811
  captureAvgMs: totalFrames > 0 ? Math.round((perfStages.captureMs ?? 0) / totalFrames) : void 0,
111329
111812
  peakRssMb: Math.round(peakRssBytes / (1024 * 1024)),
@@ -111332,7 +111815,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111332
111815
  job.perfSummary = perfSummary;
111333
111816
  if (job.config.debug) {
111334
111817
  try {
111335
- writeFileSync4(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
111818
+ writeFileSync5(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
111336
111819
  } catch (err) {
111337
111820
  log.debug("Failed to write perf summary", {
111338
111821
  perfOutputPath,
@@ -111341,8 +111824,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111341
111824
  }
111342
111825
  }
111343
111826
  if (job.config.debug) {
111344
- if (existsSync15(outputPath)) {
111345
- const debugOutput = join15(workDir, `output${videoExt}`);
111827
+ if (existsSync16(outputPath)) {
111828
+ const debugOutput = join16(workDir, `output${videoExt}`);
111346
111829
  copyFileSync2(outputPath, debugOutput);
111347
111830
  }
111348
111831
  } else if (process.env.KEEP_TEMP === "1") {
@@ -111428,7 +111911,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111428
111911
  await safeCleanup(
111429
111912
  "remove workDir (error)",
111430
111913
  () => {
111431
- if (existsSync15(workDir)) rmSync3(workDir, { recursive: true, force: true });
111914
+ if (existsSync16(workDir)) rmSync3(workDir, { recursive: true, force: true });
111432
111915
  },
111433
111916
  log
111434
111917
  );
@@ -111441,8 +111924,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
111441
111924
  }
111442
111925
 
111443
111926
  // src/services/hyperframeLint.ts
111444
- import { existsSync as existsSync16, readFileSync as readFileSync11, statSync as statSync6 } from "node:fs";
111445
- import { resolve as resolve12, join as join16 } from "node:path";
111927
+ import { existsSync as existsSync17, readFileSync as readFileSync11, statSync as statSync8 } from "node:fs";
111928
+ import { resolve as resolve12, join as join17 } from "node:path";
111446
111929
  function isStringRecord(value) {
111447
111930
  if (!value || typeof value !== "object" || Array.isArray(value)) {
111448
111931
  return false;
@@ -111470,7 +111953,7 @@ function pickEntryFile(files, preferredEntryFile) {
111470
111953
  }
111471
111954
  function readProjectEntryFile(projectDir, preferredEntryFile) {
111472
111955
  const absProjectDir = resolve12(projectDir);
111473
- if (!existsSync16(absProjectDir) || !statSync6(absProjectDir).isDirectory()) {
111956
+ if (!existsSync17(absProjectDir) || !statSync8(absProjectDir).isDirectory()) {
111474
111957
  return { error: `Project directory not found: ${absProjectDir}` };
111475
111958
  }
111476
111959
  const entryCandidates = [preferredEntryFile, "index.html", "src/index.html"].filter(
@@ -111481,7 +111964,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
111481
111964
  if (!absoluteEntryPath.startsWith(absProjectDir)) {
111482
111965
  return { error: `Entry file must stay inside project directory: ${entryFile}` };
111483
111966
  }
111484
- if (existsSync16(absoluteEntryPath) && statSync6(absoluteEntryPath).isFile()) {
111967
+ if (existsSync17(absoluteEntryPath) && statSync8(absoluteEntryPath).isFile()) {
111485
111968
  return {
111486
111969
  entryFile,
111487
111970
  html: readFileSync11(absoluteEntryPath, "utf-8"),
@@ -111490,7 +111973,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
111490
111973
  }
111491
111974
  }
111492
111975
  return {
111493
- error: `No HTML entry file found in project directory: ${join16(absProjectDir, preferredEntryFile || "index.html")}`
111976
+ error: `No HTML entry file found in project directory: ${join17(absProjectDir, preferredEntryFile || "index.html")}`
111494
111977
  };
111495
111978
  }
111496
111979
  function prepareHyperframeLintBody(body) {
@@ -111581,11 +112064,11 @@ async function prepareRenderBody(body) {
111581
112064
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
111582
112065
  if (projectDir) {
111583
112066
  const absProjectDir = resolve13(projectDir);
111584
- if (!existsSync17(absProjectDir) || !statSync7(absProjectDir).isDirectory()) {
112067
+ if (!existsSync18(absProjectDir) || !statSync9(absProjectDir).isDirectory()) {
111585
112068
  return { error: `Project directory not found: ${absProjectDir}` };
111586
112069
  }
111587
112070
  const entry = options.entryFile || "index.html";
111588
- if (!existsSync17(resolve13(absProjectDir, entry))) {
112071
+ if (!existsSync18(resolve13(absProjectDir, entry))) {
111589
112072
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
111590
112073
  }
111591
112074
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -111610,8 +112093,8 @@ async function prepareRenderBody(body) {
111610
112093
  }
111611
112094
  }
111612
112095
  const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir2();
111613
- const tempProjectDir = mkdtempSync(join17(tempRoot, "producer-project-"));
111614
- writeFileSync5(join17(tempProjectDir, "index.html"), htmlContent, "utf-8");
112096
+ const tempProjectDir = mkdtempSync(join18(tempRoot, "producer-project-"));
112097
+ writeFileSync6(join18(tempProjectDir, "index.html"), htmlContent, "utf-8");
111615
112098
  return {
111616
112099
  prepared: {
111617
112100
  input: {
@@ -111734,7 +112217,7 @@ function createRenderHandlers(options = {}) {
111734
112217
  log
111735
112218
  );
111736
112219
  const outputDir = dirname11(absoluteOutputPath);
111737
- if (!existsSync17(outputDir)) mkdirSync11(outputDir, { recursive: true });
112220
+ if (!existsSync18(outputDir)) mkdirSync12(outputDir, { recursive: true });
111738
112221
  const release = await renderSemaphore.acquire();
111739
112222
  log.info("render started", {
111740
112223
  requestId,
@@ -111761,7 +112244,7 @@ function createRenderHandlers(options = {}) {
111761
112244
  log.info(`render progress ${pct}%`, { requestId, stage: j.currentStage, message });
111762
112245
  }
111763
112246
  });
111764
- const fileSize = existsSync17(absoluteOutputPath) ? statSync7(absoluteOutputPath).size : 0;
112247
+ const fileSize = existsSync18(absoluteOutputPath) ? statSync9(absoluteOutputPath).size : 0;
111765
112248
  const durationMs = Date.now() - t0;
111766
112249
  const outputToken = store.register(absoluteOutputPath);
111767
112250
  const outputUrl = `${outputUrlPrefix}/${outputToken}`;
@@ -111845,7 +112328,7 @@ function createRenderHandlers(options = {}) {
111845
112328
  log
111846
112329
  );
111847
112330
  const outputDir = dirname11(absoluteOutputPath);
111848
- if (!existsSync17(outputDir)) mkdirSync11(outputDir, { recursive: true });
112331
+ if (!existsSync18(outputDir)) mkdirSync12(outputDir, { recursive: true });
111849
112332
  log.info("render-stream started", { requestId, projectDir: input2.projectDir });
111850
112333
  const job = createRenderJob({
111851
112334
  fps: input2.fps,
@@ -111890,7 +112373,7 @@ function createRenderHandlers(options = {}) {
111890
112373
  },
111891
112374
  abortController.signal
111892
112375
  );
111893
- const fileSize = existsSync17(absoluteOutputPath) ? statSync7(absoluteOutputPath).size : 0;
112376
+ const fileSize = existsSync18(absoluteOutputPath) ? statSync9(absoluteOutputPath).size : 0;
111894
112377
  const outputToken = store.register(absoluteOutputPath);
111895
112378
  const outputUrl = `${outputUrlPrefix}/${outputToken}`;
111896
112379
  log.info("render-stream completed", { requestId, fileSize, perf: job.perfSummary ?? null });
@@ -111949,11 +112432,11 @@ function createRenderHandlers(options = {}) {
111949
112432
  if (!artifact) {
111950
112433
  return c.json({ success: false, error: "Output artifact not found or expired" }, 404);
111951
112434
  }
111952
- if (!existsSync17(artifact.path)) {
112435
+ if (!existsSync18(artifact.path)) {
111953
112436
  store.delete(token);
111954
112437
  return c.json({ success: false, error: "Output artifact file missing" }, 404);
111955
112438
  }
111956
- const stats = statSync7(artifact.path);
112439
+ const stats = statSync9(artifact.path);
111957
112440
  return new Response(createReadStream2(artifact.path), {
111958
112441
  headers: {
111959
112442
  "content-type": "video/mp4",