@hyperframes/producer 0.4.15-alpha.1 → 0.4.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1356,12 +1356,12 @@ var require_CSSValueExpression = __commonJS({
1356
1356
  return false;
1357
1357
  }
1358
1358
  };
1359
- CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep) {
1360
- var endIdx = this._findMatchedIdx(token, idx, sep), text;
1359
+ CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep2) {
1360
+ var endIdx = this._findMatchedIdx(token, idx, sep2), text;
1361
1361
  if (endIdx === -1) {
1362
1362
  return false;
1363
1363
  } else {
1364
- text = token.substring(idx, endIdx + sep.length);
1364
+ text = token.substring(idx, endIdx + sep2.length);
1365
1365
  return {
1366
1366
  idx: endIdx,
1367
1367
  text
@@ -1401,15 +1401,15 @@ var require_CSSValueExpression = __commonJS({
1401
1401
  if (!isLegal) {
1402
1402
  return false;
1403
1403
  } else {
1404
- var sep = "/";
1405
- return this._parseJSString(token, idx, sep);
1404
+ var sep2 = "/";
1405
+ return this._parseJSString(token, idx, sep2);
1406
1406
  }
1407
1407
  };
1408
- CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep) {
1408
+ CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep2) {
1409
1409
  var startIdx = idx, endIdx;
1410
1410
  var NOT_FOUND = -1;
1411
1411
  while (true) {
1412
- endIdx = token.indexOf(sep, startIdx + 1);
1412
+ endIdx = token.indexOf(sep2, startIdx + 1);
1413
1413
  if (endIdx === -1) {
1414
1414
  endIdx = NOT_FOUND;
1415
1415
  break;
@@ -2148,11 +2148,11 @@ function __extends(d, b) {
2148
2148
  }
2149
2149
  function __awaiter(thisArg, _arguments, P, generator) {
2150
2150
  function adopt(value) {
2151
- return value instanceof P ? value : new P(function(resolve13) {
2152
- resolve13(value);
2151
+ return value instanceof P ? value : new P(function(resolve14) {
2152
+ resolve14(value);
2153
2153
  });
2154
2154
  }
2155
- return new (P || (P = Promise))(function(resolve13, reject) {
2155
+ return new (P || (P = Promise))(function(resolve14, reject) {
2156
2156
  function fulfilled(value) {
2157
2157
  try {
2158
2158
  step(generator.next(value));
@@ -2168,7 +2168,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
2168
2168
  }
2169
2169
  }
2170
2170
  function step(result) {
2171
- result.done ? resolve13(result.value) : adopt(result.value).then(fulfilled, rejected);
2171
+ result.done ? resolve14(result.value) : adopt(result.value).then(fulfilled, rejected);
2172
2172
  }
2173
2173
  step((generator = generator.apply(thisArg, _arguments || [])).next());
2174
2174
  });
@@ -2331,14 +2331,14 @@ function __asyncValues(o) {
2331
2331
  }, i);
2332
2332
  function verb(n) {
2333
2333
  i[n] = o[n] && function(v) {
2334
- return new Promise(function(resolve13, reject) {
2335
- v = o[n](v), settle(resolve13, reject, v.done, v.value);
2334
+ return new Promise(function(resolve14, reject) {
2335
+ v = o[n](v), settle(resolve14, reject, v.done, v.value);
2336
2336
  });
2337
2337
  };
2338
2338
  }
2339
- function settle(resolve13, reject, d, v) {
2339
+ function settle(resolve14, reject, d, v) {
2340
2340
  Promise.resolve(v).then(function(v2) {
2341
- resolve13({ value: v2, done: d });
2341
+ resolve14({ value: v2, done: d });
2342
2342
  }, reject);
2343
2343
  }
2344
2344
  }
@@ -2863,7 +2863,7 @@ function of() {
2863
2863
  }
2864
2864
  function lastValueFrom(source2, config2) {
2865
2865
  var hasConfig = typeof config2 === "object";
2866
- return new Promise(function(resolve13, reject) {
2866
+ return new Promise(function(resolve14, reject) {
2867
2867
  var _hasValue = false;
2868
2868
  var _value;
2869
2869
  source2.subscribe({
@@ -2874,9 +2874,9 @@ function lastValueFrom(source2, config2) {
2874
2874
  error: reject,
2875
2875
  complete: function() {
2876
2876
  if (_hasValue) {
2877
- resolve13(_value);
2877
+ resolve14(_value);
2878
2878
  } else if (hasConfig) {
2879
- resolve13(config2.defaultValue);
2879
+ resolve14(config2.defaultValue);
2880
2880
  } else {
2881
2881
  reject(new EmptyError());
2882
2882
  }
@@ -2886,16 +2886,16 @@ function lastValueFrom(source2, config2) {
2886
2886
  }
2887
2887
  function firstValueFrom(source2, config2) {
2888
2888
  var hasConfig = typeof config2 === "object";
2889
- return new Promise(function(resolve13, reject) {
2889
+ return new Promise(function(resolve14, reject) {
2890
2890
  var subscriber = new SafeSubscriber({
2891
2891
  next: function(value) {
2892
- resolve13(value);
2892
+ resolve14(value);
2893
2893
  subscriber.unsubscribe();
2894
2894
  },
2895
2895
  error: reject,
2896
2896
  complete: function() {
2897
2897
  if (hasConfig) {
2898
- resolve13(config2.defaultValue);
2898
+ resolve14(config2.defaultValue);
2899
2899
  } else {
2900
2900
  reject(new EmptyError());
2901
2901
  }
@@ -3934,7 +3934,7 @@ var init_rxjs = __esm({
3934
3934
  Observable2.prototype.forEach = function(next, promiseCtor) {
3935
3935
  var _this = this;
3936
3936
  promiseCtor = getPromiseCtor(promiseCtor);
3937
- return new promiseCtor(function(resolve13, reject) {
3937
+ return new promiseCtor(function(resolve14, reject) {
3938
3938
  var subscriber = new SafeSubscriber({
3939
3939
  next: function(value) {
3940
3940
  try {
@@ -3945,7 +3945,7 @@ var init_rxjs = __esm({
3945
3945
  }
3946
3946
  },
3947
3947
  error: reject,
3948
- complete: resolve13
3948
+ complete: resolve14
3949
3949
  });
3950
3950
  _this.subscribe(subscriber);
3951
3951
  });
@@ -3967,14 +3967,14 @@ var init_rxjs = __esm({
3967
3967
  Observable2.prototype.toPromise = function(promiseCtor) {
3968
3968
  var _this = this;
3969
3969
  promiseCtor = getPromiseCtor(promiseCtor);
3970
- return new promiseCtor(function(resolve13, reject) {
3970
+ return new promiseCtor(function(resolve14, reject) {
3971
3971
  var value;
3972
3972
  _this.subscribe(function(x) {
3973
3973
  return value = x;
3974
3974
  }, function(err) {
3975
3975
  return reject(err);
3976
3976
  }, function() {
3977
- return resolve13(value);
3977
+ return resolve14(value);
3978
3978
  });
3979
3979
  });
3980
3980
  };
@@ -6404,8 +6404,8 @@ var init_Deferred = __esm({
6404
6404
  // SAFETY: This is ensured by #taskPromise.
6405
6405
  #resolve;
6406
6406
  // TODO: Switch to Promise.withResolvers with Node 22
6407
- #taskPromise = new Promise((resolve13) => {
6408
- this.#resolve = resolve13;
6407
+ #taskPromise = new Promise((resolve14) => {
6408
+ this.#resolve = resolve14;
6409
6409
  });
6410
6410
  #timeoutId;
6411
6411
  #timeoutError;
@@ -6495,12 +6495,12 @@ var init_Mutex = __esm({
6495
6495
  return new _Mutex.Guard(this, onRelease);
6496
6496
  }
6497
6497
  release() {
6498
- const resolve13 = this.#acquirers.shift();
6499
- if (!resolve13) {
6498
+ const resolve14 = this.#acquirers.shift();
6499
+ if (!resolve14) {
6500
6500
  this.#locked = false;
6501
6501
  return;
6502
6502
  }
6503
- resolve13();
6503
+ resolve14();
6504
6504
  }
6505
6505
  };
6506
6506
  }
@@ -8515,12 +8515,12 @@ var init_locators = __esm({
8515
8515
  }
8516
8516
  return defer(() => {
8517
8517
  return from(handle.evaluate((element) => {
8518
- return new Promise((resolve13) => {
8518
+ return new Promise((resolve14) => {
8519
8519
  window.requestAnimationFrame(() => {
8520
8520
  const rect1 = element.getBoundingClientRect();
8521
8521
  window.requestAnimationFrame(() => {
8522
8522
  const rect2 = element.getBoundingClientRect();
8523
- resolve13([
8523
+ resolve14([
8524
8524
  {
8525
8525
  x: rect1.x,
8526
8526
  y: rect1.y,
@@ -10259,9 +10259,9 @@ var init_ElementHandle = __esm({
10259
10259
  const handle = await this.#asSVGElementHandle();
10260
10260
  const target = __addDisposableResource6(env_5, handle && await handle.#getOwnerSVGElement(), false);
10261
10261
  return await (target ?? this).evaluate(async (element, threshold) => {
10262
- const visibleRatio = await new Promise((resolve13) => {
10262
+ const visibleRatio = await new Promise((resolve14) => {
10263
10263
  const observer = new IntersectionObserver((entries2) => {
10264
- resolve13(entries2[0].intersectionRatio);
10264
+ resolve14(entries2[0].intersectionRatio);
10265
10265
  observer.disconnect();
10266
10266
  });
10267
10267
  observer.observe(element);
@@ -10907,7 +10907,7 @@ var init_Frame = __esm({
10907
10907
  }
10908
10908
  type = type ?? "text/javascript";
10909
10909
  return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ url, id, type: type2, content: content2 }) => {
10910
- return await new Promise((resolve13, reject) => {
10910
+ return await new Promise((resolve14, reject) => {
10911
10911
  const script = document.createElement("script");
10912
10912
  script.type = type2;
10913
10913
  script.text = content2;
@@ -10920,12 +10920,12 @@ var init_Frame = __esm({
10920
10920
  if (url) {
10921
10921
  script.src = url;
10922
10922
  script.addEventListener("load", () => {
10923
- resolve13(script);
10923
+ resolve14(script);
10924
10924
  }, { once: true });
10925
10925
  document.head.appendChild(script);
10926
10926
  } else {
10927
10927
  document.head.appendChild(script);
10928
- resolve13(script);
10928
+ resolve14(script);
10929
10929
  }
10930
10930
  });
10931
10931
  }, { ...options, type, content }));
@@ -10945,7 +10945,7 @@ var init_Frame = __esm({
10945
10945
  options.content = content;
10946
10946
  }
10947
10947
  return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ url, content: content2 }) => {
10948
- return await new Promise((resolve13, reject) => {
10948
+ return await new Promise((resolve14, reject) => {
10949
10949
  let element;
10950
10950
  if (!url) {
10951
10951
  element = document.createElement("style");
@@ -10957,7 +10957,7 @@ var init_Frame = __esm({
10957
10957
  element = link;
10958
10958
  }
10959
10959
  element.addEventListener("load", () => {
10960
- resolve13(element);
10960
+ resolve14(element);
10961
10961
  }, { once: true });
10962
10962
  element.addEventListener("error", (event) => {
10963
10963
  reject(new Error(event.message ?? "Could not load style"));
@@ -12696,9 +12696,9 @@ var init_Page = __esm({
12696
12696
  ++this.#screencastSessionCount;
12697
12697
  if (!this.#startScreencastPromise) {
12698
12698
  this.#startScreencastPromise = this.mainFrame().client.send("Page.startScreencast", { format: "png" }).then(() => {
12699
- return new Promise((resolve13) => {
12699
+ return new Promise((resolve14) => {
12700
12700
  return this.mainFrame().client.once("Page.screencastFrame", () => {
12701
- return resolve13();
12701
+ return resolve14();
12702
12702
  });
12703
12703
  });
12704
12704
  });
@@ -16016,11 +16016,11 @@ function addPageBinding(type, name, prefix) {
16016
16016
  return value instanceof Node;
16017
16017
  })
16018
16018
  }));
16019
- return new Promise((resolve13, reject) => {
16019
+ return new Promise((resolve14, reject) => {
16020
16020
  callPuppeteer.callbacks.set(seq, {
16021
16021
  resolve(value) {
16022
16022
  callPuppeteer.args.delete(seq);
16023
- resolve13(value);
16023
+ resolve14(value);
16024
16024
  },
16025
16025
  reject(value) {
16026
16026
  callPuppeteer.args.delete(seq);
@@ -19683,8 +19683,8 @@ var init_Input2 = __esm({
19683
19683
  if (typeof delay === "number") {
19684
19684
  await Promise.all(actions);
19685
19685
  actions.length = 0;
19686
- await new Promise((resolve13) => {
19687
- setTimeout(resolve13, delay);
19686
+ await new Promise((resolve14) => {
19687
+ setTimeout(resolve14, delay);
19688
19688
  });
19689
19689
  }
19690
19690
  actions.push(this.up({ ...options, clickCount }));
@@ -19704,9 +19704,9 @@ var init_Input2 = __esm({
19704
19704
  });
19705
19705
  }
19706
19706
  async drag(start, target) {
19707
- const promise = new Promise((resolve13) => {
19707
+ const promise = new Promise((resolve14) => {
19708
19708
  this.#client.once("Input.dragIntercepted", (event) => {
19709
- return resolve13(event.data);
19709
+ return resolve14(event.data);
19710
19710
  });
19711
19711
  });
19712
19712
  await this.move(start.x, start.y);
@@ -19747,8 +19747,8 @@ var init_Input2 = __esm({
19747
19747
  await this.dragEnter(target, data);
19748
19748
  await this.dragOver(target, data);
19749
19749
  if (delay) {
19750
- await new Promise((resolve13) => {
19751
- return setTimeout(resolve13, delay);
19750
+ await new Promise((resolve14) => {
19751
+ return setTimeout(resolve14, delay);
19752
19752
  });
19753
19753
  }
19754
19754
  await this.drop(target, data);
@@ -20632,9 +20632,9 @@ var init_Page2 = __esm({
20632
20632
  async captureHeapSnapshot(options) {
20633
20633
  const { createWriteStream: createWriteStream3 } = environment.value.fs;
20634
20634
  const stream2 = createWriteStream3(options.path);
20635
- const streamPromise = new Promise((resolve13, reject) => {
20635
+ const streamPromise = new Promise((resolve14, reject) => {
20636
20636
  stream2.on("error", reject);
20637
- stream2.on("finish", resolve13);
20637
+ stream2.on("finish", resolve14);
20638
20638
  });
20639
20639
  const client = this.#primaryTargetClient;
20640
20640
  await client.send("HeapProfiler.enable");
@@ -22276,10 +22276,10 @@ var init_BrowserWebSocketTransport = __esm({
22276
22276
  "../../node_modules/.bun/puppeteer-core@24.40.0/node_modules/puppeteer-core/lib/esm/puppeteer/common/BrowserWebSocketTransport.js"() {
22277
22277
  BrowserWebSocketTransport = class _BrowserWebSocketTransport {
22278
22278
  static create(url) {
22279
- return new Promise((resolve13, reject) => {
22279
+ return new Promise((resolve14, reject) => {
22280
22280
  const ws = new WebSocket(url);
22281
22281
  ws.addEventListener("open", () => {
22282
- return resolve13(new _BrowserWebSocketTransport(ws));
22282
+ return resolve14(new _BrowserWebSocketTransport(ws));
22283
22283
  });
22284
22284
  ws.addEventListener("error", reject);
22285
22285
  });
@@ -25201,11 +25201,11 @@ var require_BrowsingContextProcessor = __commonJS({
25201
25201
  }
25202
25202
  const parentCdpClient = context2.cdpTarget.parentCdpClient;
25203
25203
  try {
25204
- const detachedFromTargetPromise = new Promise((resolve13) => {
25204
+ const detachedFromTargetPromise = new Promise((resolve14) => {
25205
25205
  const onContextDestroyed = (event) => {
25206
25206
  if (event.targetId === params.context) {
25207
25207
  parentCdpClient.off("Target.detachedFromTarget", onContextDestroyed);
25208
- resolve13();
25208
+ resolve14();
25209
25209
  }
25210
25210
  };
25211
25211
  parentCdpClient.on("Target.detachedFromTarget", onContextDestroyed);
@@ -26568,7 +26568,7 @@ var require_ActionDispatcher = __commonJS({
26568
26568
  }
26569
26569
  }
26570
26570
  const promises = [
26571
- new Promise((resolve13) => setTimeout(resolve13, this.#tickDuration))
26571
+ new Promise((resolve14) => setTimeout(resolve14, this.#tickDuration))
26572
26572
  ];
26573
26573
  for (const option of options) {
26574
26574
  promises.push(this.#dispatchAction(option));
@@ -27169,8 +27169,8 @@ var require_Mutex = __commonJS({
27169
27169
  acquire() {
27170
27170
  const state = { resolved: false };
27171
27171
  if (this.#locked) {
27172
- return new Promise((resolve13) => {
27173
- this.#acquirers.push(() => resolve13(this.#release.bind(this, state)));
27172
+ return new Promise((resolve14) => {
27173
+ this.#acquirers.push(() => resolve14(this.#release.bind(this, state)));
27174
27174
  });
27175
27175
  }
27176
27176
  this.#locked = true;
@@ -27181,12 +27181,12 @@ var require_Mutex = __commonJS({
27181
27181
  throw new Error("Cannot release more than once.");
27182
27182
  }
27183
27183
  state.resolved = true;
27184
- const resolve13 = this.#acquirers.shift();
27185
- if (!resolve13) {
27184
+ const resolve14 = this.#acquirers.shift();
27185
+ if (!resolve14) {
27186
27186
  this.#locked = false;
27187
27187
  return;
27188
27188
  }
27189
- resolve13();
27189
+ resolve14();
27190
27190
  }
27191
27191
  async run(action) {
27192
27192
  const release = await this.acquire();
@@ -28368,8 +28368,8 @@ var require_ChannelProxy = __commonJS({
28368
28368
  * in the queue.
28369
28369
  */
28370
28370
  async getMessage() {
28371
- const onMessage = queue.length > 0 ? Promise.resolve() : new Promise((resolve13) => {
28372
- queueNonEmptyResolver = resolve13;
28371
+ const onMessage = queue.length > 0 ? Promise.resolve() : new Promise((resolve14) => {
28372
+ queueNonEmptyResolver = resolve14;
28373
28373
  });
28374
28374
  await onMessage;
28375
28375
  return queue.shift();
@@ -28474,7 +28474,7 @@ var require_ChannelProxy = __commonJS({
28474
28474
  functionDeclaration: String((id) => {
28475
28475
  const w = window;
28476
28476
  if (w[id] === void 0) {
28477
- return new Promise((resolve13) => w[id] = resolve13);
28477
+ return new Promise((resolve14) => w[id] = resolve14);
28478
28478
  }
28479
28479
  const channelProxy = w[id];
28480
28480
  delete w[id];
@@ -29975,8 +29975,8 @@ var require_Deferred = __commonJS({
29975
29975
  return this.#result;
29976
29976
  }
29977
29977
  constructor() {
29978
- this.#promise = new Promise((resolve13, reject) => {
29979
- this.#resolve = resolve13;
29978
+ this.#promise = new Promise((resolve14, reject) => {
29979
+ this.#resolve = resolve14;
29980
29980
  this.#reject = reject;
29981
29981
  });
29982
29982
  this.#promise.catch((_error) => {
@@ -34820,11 +34820,11 @@ var require_BrowsingContextStorage = __commonJS({
34820
34820
  if (this.#contexts.has(browsingContextId)) {
34821
34821
  return Promise.resolve(this.getContext(browsingContextId));
34822
34822
  }
34823
- return new Promise((resolve13) => {
34823
+ return new Promise((resolve14) => {
34824
34824
  const listener = (event) => {
34825
34825
  if (event.browsingContext.id === browsingContextId) {
34826
34826
  this.#eventEmitter.off("added", listener);
34827
- resolve13(event.browsingContext);
34827
+ resolve14(event.browsingContext);
34828
34828
  }
34829
34829
  };
34830
34830
  this.#eventEmitter.on("added", listener);
@@ -38406,8 +38406,8 @@ var init_ExposedFunction = __esm({
38406
38406
  const functionDeclaration = stringifyFunction(interpolateFunction((callback) => {
38407
38407
  Object.assign(globalThis, {
38408
38408
  [PLACEHOLDER("name")]: function(...args) {
38409
- return new Promise((resolve13, reject) => {
38410
- callback([resolve13, reject, args]);
38409
+ return new Promise((resolve14, reject) => {
38410
+ callback([resolve14, reject, args]);
38411
38411
  });
38412
38412
  }
38413
38413
  });
@@ -38495,8 +38495,8 @@ var init_ExposedFunction = __esm({
38495
38495
  return;
38496
38496
  }
38497
38497
  try {
38498
- await dataHandle.evaluate(([resolve13], result2) => {
38499
- resolve13(result2);
38498
+ await dataHandle.evaluate(([resolve14], result2) => {
38499
+ resolve14(result2);
38500
38500
  }, result);
38501
38501
  } catch (error) {
38502
38502
  debugError(error);
@@ -46577,7 +46577,7 @@ var init_NodeWebSocketTransport = __esm({
46577
46577
  init_version();
46578
46578
  NodeWebSocketTransport = class _NodeWebSocketTransport {
46579
46579
  static create(url, headers) {
46580
- return new Promise((resolve13, reject) => {
46580
+ return new Promise((resolve14, reject) => {
46581
46581
  const ws = new wrapper_default(url, [], {
46582
46582
  followRedirects: true,
46583
46583
  perMessageDeflate: false,
@@ -46590,7 +46590,7 @@ var init_NodeWebSocketTransport = __esm({
46590
46590
  }
46591
46591
  });
46592
46592
  ws.addEventListener("open", () => {
46593
- return resolve13(new _NodeWebSocketTransport(ws));
46593
+ return resolve14(new _NodeWebSocketTransport(ws));
46594
46594
  });
46595
46595
  ws.addEventListener("error", reject);
46596
46596
  });
@@ -49651,8 +49651,8 @@ var require_helpers = __commonJS({
49651
49651
  function req(url, opts = {}) {
49652
49652
  const href = typeof url === "string" ? url : url.href;
49653
49653
  const req2 = (href.startsWith("https:") ? https2 : http2).request(url, opts);
49654
- const promise = new Promise((resolve13, reject) => {
49655
- req2.once("response", resolve13).once("error", reject).end();
49654
+ const promise = new Promise((resolve14, reject) => {
49655
+ req2.once("response", resolve14).once("error", reject).end();
49656
49656
  });
49657
49657
  req2.then = promise.then.bind(promise);
49658
49658
  return req2;
@@ -50029,7 +50029,7 @@ var require_parse_proxy_response = __commonJS({
50029
50029
  var debug_1 = __importDefault2(require_src());
50030
50030
  var debug6 = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
50031
50031
  function parseProxyResponse(socket) {
50032
- return new Promise((resolve13, reject) => {
50032
+ return new Promise((resolve14, reject) => {
50033
50033
  let buffersLength = 0;
50034
50034
  const buffers = [];
50035
50035
  function read() {
@@ -50095,7 +50095,7 @@ var require_parse_proxy_response = __commonJS({
50095
50095
  }
50096
50096
  debug6("got proxy server response: %o %o", firstLine, headers);
50097
50097
  cleanup();
50098
- resolve13({
50098
+ resolve14({
50099
50099
  connect: {
50100
50100
  statusCode,
50101
50101
  statusText,
@@ -53353,11 +53353,11 @@ var require_socksclient = __commonJS({
53353
53353
  "use strict";
53354
53354
  var __awaiter3 = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
53355
53355
  function adopt(value) {
53356
- return value instanceof P ? value : new P(function(resolve13) {
53357
- resolve13(value);
53356
+ return value instanceof P ? value : new P(function(resolve14) {
53357
+ resolve14(value);
53358
53358
  });
53359
53359
  }
53360
- return new (P || (P = Promise))(function(resolve13, reject) {
53360
+ return new (P || (P = Promise))(function(resolve14, reject) {
53361
53361
  function fulfilled(value) {
53362
53362
  try {
53363
53363
  step(generator.next(value));
@@ -53373,7 +53373,7 @@ var require_socksclient = __commonJS({
53373
53373
  }
53374
53374
  }
53375
53375
  function step(result) {
53376
- result.done ? resolve13(result.value) : adopt(result.value).then(fulfilled, rejected);
53376
+ result.done ? resolve14(result.value) : adopt(result.value).then(fulfilled, rejected);
53377
53377
  }
53378
53378
  step((generator = generator.apply(thisArg, _arguments || [])).next());
53379
53379
  });
@@ -53407,13 +53407,13 @@ var require_socksclient = __commonJS({
53407
53407
  * @returns { Promise }
53408
53408
  */
53409
53409
  static createConnection(options, callback) {
53410
- return new Promise((resolve13, reject) => {
53410
+ return new Promise((resolve14, reject) => {
53411
53411
  try {
53412
53412
  (0, helpers_1.validateSocksClientOptions)(options, ["connect"]);
53413
53413
  } catch (err) {
53414
53414
  if (typeof callback === "function") {
53415
53415
  callback(err);
53416
- return resolve13(err);
53416
+ return resolve14(err);
53417
53417
  } else {
53418
53418
  return reject(err);
53419
53419
  }
@@ -53424,16 +53424,16 @@ var require_socksclient = __commonJS({
53424
53424
  client.removeAllListeners();
53425
53425
  if (typeof callback === "function") {
53426
53426
  callback(null, info);
53427
- resolve13(info);
53427
+ resolve14(info);
53428
53428
  } else {
53429
- resolve13(info);
53429
+ resolve14(info);
53430
53430
  }
53431
53431
  });
53432
53432
  client.once("error", (err) => {
53433
53433
  client.removeAllListeners();
53434
53434
  if (typeof callback === "function") {
53435
53435
  callback(err);
53436
- resolve13(err);
53436
+ resolve14(err);
53437
53437
  } else {
53438
53438
  reject(err);
53439
53439
  }
@@ -53450,13 +53450,13 @@ var require_socksclient = __commonJS({
53450
53450
  * @returns { Promise }
53451
53451
  */
53452
53452
  static createConnectionChain(options, callback) {
53453
- return new Promise((resolve13, reject) => __awaiter3(this, void 0, void 0, function* () {
53453
+ return new Promise((resolve14, reject) => __awaiter3(this, void 0, void 0, function* () {
53454
53454
  try {
53455
53455
  (0, helpers_1.validateSocksClientChainOptions)(options);
53456
53456
  } catch (err) {
53457
53457
  if (typeof callback === "function") {
53458
53458
  callback(err);
53459
- return resolve13(err);
53459
+ return resolve14(err);
53460
53460
  } else {
53461
53461
  return reject(err);
53462
53462
  }
@@ -53482,14 +53482,14 @@ var require_socksclient = __commonJS({
53482
53482
  }
53483
53483
  if (typeof callback === "function") {
53484
53484
  callback(null, { socket: sock });
53485
- resolve13({ socket: sock });
53485
+ resolve14({ socket: sock });
53486
53486
  } else {
53487
- resolve13({ socket: sock });
53487
+ resolve14({ socket: sock });
53488
53488
  }
53489
53489
  } catch (err) {
53490
53490
  if (typeof callback === "function") {
53491
53491
  callback(err);
53492
- resolve13(err);
53492
+ resolve14(err);
53493
53493
  } else {
53494
53494
  reject(err);
53495
53495
  }
@@ -54173,12 +54173,12 @@ var require_dist4 = __commonJS({
54173
54173
  let { host } = opts;
54174
54174
  const { port, lookup: lookupFn = dns.lookup } = opts;
54175
54175
  if (shouldLookup) {
54176
- host = await new Promise((resolve13, reject) => {
54176
+ host = await new Promise((resolve14, reject) => {
54177
54177
  lookupFn(host, {}, (err, res) => {
54178
54178
  if (err) {
54179
54179
  reject(err);
54180
54180
  } else {
54181
- resolve13(res);
54181
+ resolve14(res);
54182
54182
  }
54183
54183
  });
54184
54184
  });
@@ -55363,7 +55363,7 @@ var require_netUtils = __commonJS({
55363
55363
  return `${socket.remoteAddress}:${socket.remotePort}`;
55364
55364
  }
55365
55365
  function upgradeSocket(socket, options) {
55366
- return new Promise((resolve13, reject) => {
55366
+ return new Promise((resolve14, reject) => {
55367
55367
  const tlsOptions = Object.assign({}, options, {
55368
55368
  socket
55369
55369
  });
@@ -55373,7 +55373,7 @@ var require_netUtils = __commonJS({
55373
55373
  reject(tlsSocket.authorizationError);
55374
55374
  } else {
55375
55375
  tlsSocket.removeAllListeners("error");
55376
- resolve13(tlsSocket);
55376
+ resolve14(tlsSocket);
55377
55377
  }
55378
55378
  }).once("error", (error) => {
55379
55379
  reject(error);
@@ -55468,7 +55468,7 @@ var require_transfer = __commonJS({
55468
55468
  };
55469
55469
  }
55470
55470
  function connectForPassiveTransfer(host, port, ftp) {
55471
- return new Promise((resolve13, reject) => {
55471
+ return new Promise((resolve14, reject) => {
55472
55472
  let socket = ftp._newSocket();
55473
55473
  const handleConnErr = function(err) {
55474
55474
  err.message = "Can't open data connection in passive mode: " + err.message;
@@ -55496,7 +55496,7 @@ var require_transfer = __commonJS({
55496
55496
  socket.removeListener("error", handleConnErr);
55497
55497
  socket.removeListener("timeout", handleTimeout);
55498
55498
  ftp.dataSocket = socket;
55499
- resolve13();
55499
+ resolve14();
55500
55500
  });
55501
55501
  });
55502
55502
  }
@@ -57865,7 +57865,7 @@ var require_util2 = __commonJS({
57865
57865
  }
57866
57866
  path12 = url.path;
57867
57867
  }
57868
- var isAbsolute3 = exports.isAbsolute(path12);
57868
+ var isAbsolute5 = exports.isAbsolute(path12);
57869
57869
  var parts = path12.split(/\/+/);
57870
57870
  for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
57871
57871
  part = parts[i];
@@ -57885,7 +57885,7 @@ var require_util2 = __commonJS({
57885
57885
  }
57886
57886
  path12 = parts.join("/");
57887
57887
  if (path12 === "") {
57888
- path12 = isAbsolute3 ? "/" : ".";
57888
+ path12 = isAbsolute5 ? "/" : ".";
57889
57889
  }
57890
57890
  if (url) {
57891
57891
  url.path = path12;
@@ -67965,11 +67965,11 @@ function __metadata(metadataKey, metadataValue) {
67965
67965
  }
67966
67966
  function __awaiter2(thisArg, _arguments, P, generator) {
67967
67967
  function adopt(value) {
67968
- return value instanceof P ? value : new P(function(resolve13) {
67969
- resolve13(value);
67968
+ return value instanceof P ? value : new P(function(resolve14) {
67969
+ resolve14(value);
67970
67970
  });
67971
67971
  }
67972
- return new (P || (P = Promise))(function(resolve13, reject) {
67972
+ return new (P || (P = Promise))(function(resolve14, reject) {
67973
67973
  function fulfilled(value) {
67974
67974
  try {
67975
67975
  step(generator.next(value));
@@ -67985,7 +67985,7 @@ function __awaiter2(thisArg, _arguments, P, generator) {
67985
67985
  }
67986
67986
  }
67987
67987
  function step(result) {
67988
- result.done ? resolve13(result.value) : adopt(result.value).then(fulfilled, rejected);
67988
+ result.done ? resolve14(result.value) : adopt(result.value).then(fulfilled, rejected);
67989
67989
  }
67990
67990
  step((generator = generator.apply(thisArg, _arguments || [])).next());
67991
67991
  });
@@ -68176,14 +68176,14 @@ function __asyncValues2(o) {
68176
68176
  }, i);
68177
68177
  function verb(n) {
68178
68178
  i[n] = o[n] && function(v) {
68179
- return new Promise(function(resolve13, reject) {
68180
- v = o[n](v), settle(resolve13, reject, v.done, v.value);
68179
+ return new Promise(function(resolve14, reject) {
68180
+ v = o[n](v), settle(resolve14, reject, v.done, v.value);
68181
68181
  });
68182
68182
  };
68183
68183
  }
68184
- function settle(resolve13, reject, d, v) {
68184
+ function settle(resolve14, reject, d, v) {
68185
68185
  Promise.resolve(v).then(function(v2) {
68186
- resolve13({ value: v2, done: d });
68186
+ resolve14({ value: v2, done: d });
68187
68187
  }, reject);
68188
68188
  }
68189
68189
  }
@@ -71736,12 +71736,12 @@ var require_util3 = __commonJS({
71736
71736
  exports.isGMT = exports.dnsLookup = void 0;
71737
71737
  var dns_1 = __require("dns");
71738
71738
  function dnsLookup(host, opts) {
71739
- return new Promise((resolve13, reject) => {
71739
+ return new Promise((resolve14, reject) => {
71740
71740
  (0, dns_1.lookup)(host, opts, (err, res) => {
71741
71741
  if (err) {
71742
71742
  reject(err);
71743
71743
  } else {
71744
- resolve13(res);
71744
+ resolve14(res);
71745
71745
  }
71746
71746
  });
71747
71747
  });
@@ -72106,10 +72106,10 @@ var require_myIpAddress = __commonJS({
72106
72106
  var ip_1 = require_ip();
72107
72107
  var net_1 = __importDefault2(__require("net"));
72108
72108
  async function myIpAddress() {
72109
- return new Promise((resolve13, reject) => {
72109
+ return new Promise((resolve14, reject) => {
72110
72110
  const socket = net_1.default.connect({ host: "8.8.8.8", port: 53 });
72111
72111
  const onError = () => {
72112
- resolve13(ip_1.ip.address());
72112
+ resolve14(ip_1.ip.address());
72113
72113
  };
72114
72114
  socket.once("error", onError);
72115
72115
  socket.once("connect", () => {
@@ -72117,9 +72117,9 @@ var require_myIpAddress = __commonJS({
72117
72117
  const addr = socket.address();
72118
72118
  socket.destroy();
72119
72119
  if (typeof addr === "string") {
72120
- resolve13(addr);
72120
+ resolve14(addr);
72121
72121
  } else if (addr.address) {
72122
- resolve13(addr.address);
72122
+ resolve14(addr.address);
72123
72123
  } else {
72124
72124
  reject(new Error("Expected a `string`"));
72125
72125
  }
@@ -72697,8 +72697,8 @@ var require_deferred_promise = __commonJS({
72697
72697
  this.context = args.context;
72698
72698
  this.owner = args.context.runtime;
72699
72699
  this.handle = args.promiseHandle;
72700
- this.settled = new Promise((resolve13) => {
72701
- this.onSettled = resolve13;
72700
+ this.settled = new Promise((resolve14) => {
72701
+ this.onSettled = resolve14;
72702
72702
  });
72703
72703
  this.resolveHandle = args.resolveHandle;
72704
72704
  this.rejectHandle = args.rejectHandle;
@@ -73219,13 +73219,13 @@ var require_context = __commonJS({
73219
73219
  if (vmResolveResult.error) {
73220
73220
  return Promise.resolve(vmResolveResult);
73221
73221
  }
73222
- return new Promise((resolve13) => {
73222
+ return new Promise((resolve14) => {
73223
73223
  lifetime_1.Scope.withScope((scope) => {
73224
73224
  const resolveHandle = scope.manage(this.newFunction("resolve", (value) => {
73225
- resolve13({ value: value && value.dup() });
73225
+ resolve14({ value: value && value.dup() });
73226
73226
  }));
73227
73227
  const rejectHandle = scope.manage(this.newFunction("reject", (error) => {
73228
- resolve13({ error: error && error.dup() });
73228
+ resolve14({ error: error && error.dup() });
73229
73229
  }));
73230
73230
  const promiseHandle = scope.manage(vmResolveResult.value);
73231
73231
  const promiseThenHandle = scope.manage(this.getProp(promiseHandle, "then"));
@@ -75600,13 +75600,13 @@ import * as http from "node:http";
75600
75600
  import * as https from "node:https";
75601
75601
  import { URL as URL2, urlToHttpOptions } from "node:url";
75602
75602
  function headHttpRequest(url) {
75603
- return new Promise((resolve13) => {
75603
+ return new Promise((resolve14) => {
75604
75604
  const request3 = httpRequest(url, "HEAD", (response) => {
75605
75605
  response.resume();
75606
- resolve13(response.statusCode === 200);
75606
+ resolve14(response.statusCode === 200);
75607
75607
  }, false);
75608
75608
  request3.on("error", () => {
75609
- resolve13(false);
75609
+ resolve14(false);
75610
75610
  });
75611
75611
  });
75612
75612
  }
@@ -75634,7 +75634,7 @@ function httpRequest(url, method, response, keepAlive = true) {
75634
75634
  return request3;
75635
75635
  }
75636
75636
  function downloadFile(url, destinationPath, progressCallback) {
75637
- return new Promise((resolve13, reject) => {
75637
+ return new Promise((resolve14, reject) => {
75638
75638
  let downloadedBytes = 0;
75639
75639
  let totalBytes = 0;
75640
75640
  function onData(chunk) {
@@ -75650,7 +75650,7 @@ function downloadFile(url, destinationPath, progressCallback) {
75650
75650
  }
75651
75651
  const file = createWriteStream(destinationPath);
75652
75652
  file.on("close", () => {
75653
- return resolve13();
75653
+ return resolve14();
75654
75654
  });
75655
75655
  file.on("error", (error) => {
75656
75656
  return reject(error);
@@ -75675,7 +75675,7 @@ async function getJSON(url) {
75675
75675
  }
75676
75676
  }
75677
75677
  function getText3(url) {
75678
- return new Promise((resolve13, reject) => {
75678
+ return new Promise((resolve14, reject) => {
75679
75679
  const request3 = httpRequest(url, "GET", (response) => {
75680
75680
  let data = "";
75681
75681
  if (response.statusCode && response.statusCode >= 400) {
@@ -75686,7 +75686,7 @@ function getText3(url) {
75686
75686
  });
75687
75687
  response.on("end", () => {
75688
75688
  try {
75689
- return resolve13(String(data));
75689
+ return resolve14(String(data));
75690
75690
  } catch {
75691
75691
  return reject(new Error(`Failed to read text response from ${url}`));
75692
75692
  }
@@ -77078,7 +77078,7 @@ var init_launch = __esm({
77078
77078
  if (opts.onExit) {
77079
77079
  this.#onExitHook = opts.onExit;
77080
77080
  }
77081
- this.#browserProcessExiting = new Promise((resolve13, reject) => {
77081
+ this.#browserProcessExiting = new Promise((resolve14, reject) => {
77082
77082
  this.#browserProcess.once("exit", async () => {
77083
77083
  debugLaunch(`Browser process ${this.#browserProcess.pid} onExit`);
77084
77084
  this.#clearListeners();
@@ -77089,7 +77089,7 @@ var init_launch = __esm({
77089
77089
  reject(err);
77090
77090
  return;
77091
77091
  }
77092
- resolve13();
77092
+ resolve14();
77093
77093
  });
77094
77094
  });
77095
77095
  }
@@ -77205,7 +77205,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
77205
77205
  return [...this.#logs];
77206
77206
  }
77207
77207
  waitForLineOutput(regex, timeout2 = 0) {
77208
- return new Promise((resolve13, reject) => {
77208
+ return new Promise((resolve14, reject) => {
77209
77209
  const onClose = (errorOrCode) => {
77210
77210
  cleanup();
77211
77211
  reject(new Error([
@@ -77241,7 +77241,7 @@ Error cause: ${isErrorLike2(error) ? error.stack : error}`);
77241
77241
  return;
77242
77242
  }
77243
77243
  cleanup();
77244
- resolve13(match2[1]);
77244
+ resolve14(match2[1]);
77245
77245
  }
77246
77246
  });
77247
77247
  }
@@ -77710,7 +77710,7 @@ var require_get_stream = __commonJS({
77710
77710
  };
77711
77711
  const { maxBuffer } = options;
77712
77712
  let stream2;
77713
- await new Promise((resolve13, reject) => {
77713
+ await new Promise((resolve14, reject) => {
77714
77714
  const rejectPromise = (error) => {
77715
77715
  if (error && stream2.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
77716
77716
  error.bufferedData = stream2.getBufferedValue();
@@ -77722,7 +77722,7 @@ var require_get_stream = __commonJS({
77722
77722
  rejectPromise(error);
77723
77723
  return;
77724
77724
  }
77725
- resolve13();
77725
+ resolve14();
77726
77726
  });
77727
77727
  stream2.on("data", () => {
77728
77728
  if (stream2.getBufferedLength() > maxBuffer) {
@@ -79011,7 +79011,7 @@ var require_extract_zip = __commonJS({
79011
79011
  debug6("opening", this.zipPath, "with opts", this.opts);
79012
79012
  this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
79013
79013
  this.canceled = false;
79014
- return new Promise((resolve13, reject) => {
79014
+ return new Promise((resolve14, reject) => {
79015
79015
  this.zipfile.on("error", (err) => {
79016
79016
  this.canceled = true;
79017
79017
  reject(err);
@@ -79020,7 +79020,7 @@ var require_extract_zip = __commonJS({
79020
79020
  this.zipfile.on("close", () => {
79021
79021
  if (!this.canceled) {
79022
79022
  debug6("zip extraction complete");
79023
- resolve13();
79023
+ resolve14();
79024
79024
  }
79025
79025
  });
79026
79026
  this.zipfile.on("entry", async (entry) => {
@@ -80277,8 +80277,8 @@ var require_streamx = __commonJS({
80277
80277
  return this;
80278
80278
  },
80279
80279
  next() {
80280
- return new Promise(function(resolve13, reject) {
80281
- promiseResolve = resolve13;
80280
+ return new Promise(function(resolve14, reject) {
80281
+ promiseResolve = resolve14;
80282
80282
  promiseReject = reject;
80283
80283
  const data = stream2.read();
80284
80284
  if (data !== null) ondata(data);
@@ -80308,11 +80308,11 @@ var require_streamx = __commonJS({
80308
80308
  }
80309
80309
  function destroy(err) {
80310
80310
  stream2.destroy(err);
80311
- return new Promise((resolve13, reject) => {
80312
- if (stream2._duplexState & DESTROYED) return resolve13({ value: void 0, done: true });
80311
+ return new Promise((resolve14, reject) => {
80312
+ if (stream2._duplexState & DESTROYED) return resolve14({ value: void 0, done: true });
80313
80313
  stream2.once("close", function() {
80314
80314
  if (err) reject(err);
80315
- else resolve13({ value: void 0, done: true });
80315
+ else resolve14({ value: void 0, done: true });
80316
80316
  });
80317
80317
  });
80318
80318
  }
@@ -80356,8 +80356,8 @@ var require_streamx = __commonJS({
80356
80356
  const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
80357
80357
  if (writes === 0) return Promise.resolve(true);
80358
80358
  if (state.drains === null) state.drains = [];
80359
- return new Promise((resolve13) => {
80360
- state.drains.push({ writes, resolve: resolve13 });
80359
+ return new Promise((resolve14) => {
80360
+ state.drains.push({ writes, resolve: resolve14 });
80361
80361
  });
80362
80362
  }
80363
80363
  write(data) {
@@ -80462,10 +80462,10 @@ var require_streamx = __commonJS({
80462
80462
  cb(null);
80463
80463
  }
80464
80464
  function pipelinePromise(...streams) {
80465
- return new Promise((resolve13, reject) => {
80465
+ return new Promise((resolve14, reject) => {
80466
80466
  return pipeline(...streams, (err) => {
80467
80467
  if (err) return reject(err);
80468
- resolve13();
80468
+ resolve14();
80469
80469
  });
80470
80470
  });
80471
80471
  }
@@ -81120,16 +81120,16 @@ var require_extract = __commonJS({
81120
81120
  entryCallback = null;
81121
81121
  cb(err);
81122
81122
  }
81123
- function onnext(resolve13, reject) {
81123
+ function onnext(resolve14, reject) {
81124
81124
  if (error) {
81125
81125
  return reject(error);
81126
81126
  }
81127
81127
  if (entryStream) {
81128
- resolve13({ value: entryStream, done: false });
81128
+ resolve14({ value: entryStream, done: false });
81129
81129
  entryStream = null;
81130
81130
  return;
81131
81131
  }
81132
- promiseResolve = resolve13;
81132
+ promiseResolve = resolve14;
81133
81133
  promiseReject = reject;
81134
81134
  consumeCallback(null);
81135
81135
  if (extract._finished && promiseResolve) {
@@ -81157,11 +81157,11 @@ var require_extract = __commonJS({
81157
81157
  function destroy(err) {
81158
81158
  extract.destroy(err);
81159
81159
  consumeCallback(err);
81160
- return new Promise((resolve13, reject) => {
81161
- if (extract.destroyed) return resolve13({ value: void 0, done: true });
81160
+ return new Promise((resolve14, reject) => {
81161
+ if (extract.destroyed) return resolve14({ value: void 0, done: true });
81162
81162
  extract.once("close", function() {
81163
81163
  if (err) reject(err);
81164
- else resolve13({ value: void 0, done: true });
81164
+ else resolve14({ value: void 0, done: true });
81165
81165
  });
81166
81166
  });
81167
81167
  }
@@ -84930,13 +84930,13 @@ function usage(yargs, shim3) {
84930
84930
  };
84931
84931
  self2.stringifiedValues = function stringifiedValues(values, separator) {
84932
84932
  let string = "";
84933
- const sep = separator || ", ";
84933
+ const sep2 = separator || ", ";
84934
84934
  const array = [].concat(values);
84935
84935
  if (!values || !array.length)
84936
84936
  return string;
84937
84937
  array.forEach((value) => {
84938
84938
  if (string.length)
84939
- string += sep;
84939
+ string += sep2;
84940
84940
  string += JSON.stringify(value);
84941
84941
  });
84942
84942
  return string;
@@ -86137,12 +86137,12 @@ var init_yargs_factory = __esm({
86137
86137
  async getCompletion(args, done) {
86138
86138
  argsert("<array> [function]", [args, done], arguments.length);
86139
86139
  if (!done) {
86140
- return new Promise((resolve13, reject) => {
86140
+ return new Promise((resolve14, reject) => {
86141
86141
  __classPrivateFieldGet2(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
86142
86142
  if (err)
86143
86143
  reject(err);
86144
86144
  else
86145
- resolve13(completions);
86145
+ resolve14(completions);
86146
86146
  });
86147
86147
  });
86148
86148
  } else {
@@ -88943,8 +88943,8 @@ var init_ScreenRecorder = __esm({
88943
88943
  static {
88944
88944
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
88945
88945
  __esDecorate23(this, _private_writeFrame_descriptor = { value: __setFunctionName6(async function(buffer) {
88946
- const error = await new Promise((resolve13) => {
88947
- this.#process.stdin.write(buffer, resolve13);
88946
+ const error = await new Promise((resolve14) => {
88947
+ this.#process.stdin.write(buffer, resolve14);
88948
88948
  });
88949
88949
  if (error) {
88950
88950
  console.log(`ffmpeg failed to write: ${error.message}.`);
@@ -89134,8 +89134,8 @@ var init_ScreenRecorder = __esm({
89134
89134
  const [buffer, timestamp] = await this.#lastFrame;
89135
89135
  await Promise.all(Array(Math.max(1, Math.round(this.#fps * (performance.now() - timestamp) / 1e3))).fill(buffer).map(this.#writeFrame.bind(this)));
89136
89136
  this.#process.stdin.end();
89137
- await new Promise((resolve13) => {
89138
- this.#process.once("close", resolve13);
89137
+ await new Promise((resolve14) => {
89138
+ this.#process.once("close", resolve14);
89139
89139
  });
89140
89140
  }
89141
89141
  /**
@@ -93033,8 +93033,8 @@ var CustomElementRegistry = class {
93033
93033
  } : (element) => element.localName === localName;
93034
93034
  registry.set(localName, { Class, check });
93035
93035
  if (waiting.has(localName)) {
93036
- for (const resolve13 of waiting.get(localName))
93037
- resolve13(Class);
93036
+ for (const resolve14 of waiting.get(localName))
93037
+ resolve14(Class);
93038
93038
  waiting.delete(localName);
93039
93039
  }
93040
93040
  ownerDocument.querySelectorAll(
@@ -93074,13 +93074,13 @@ var CustomElementRegistry = class {
93074
93074
  */
93075
93075
  whenDefined(localName) {
93076
93076
  const { registry, waiting } = this;
93077
- return new Promise((resolve13) => {
93077
+ return new Promise((resolve14) => {
93078
93078
  if (registry.has(localName))
93079
- resolve13(registry.get(localName).Class);
93079
+ resolve14(registry.get(localName).Class);
93080
93080
  else {
93081
93081
  if (!waiting.has(localName))
93082
93082
  waiting.set(localName, []);
93083
- waiting.get(localName).push(resolve13);
93083
+ waiting.get(localName).push(resolve14);
93084
93084
  }
93085
93085
  });
93086
93086
  }
@@ -98730,7 +98730,7 @@ function resolveConfig(overrides) {
98730
98730
  hdr: (() => {
98731
98731
  const raw2 = env2("PRODUCER_HDR_TRANSFER");
98732
98732
  if (raw2 === "hlg" || raw2 === "pq") return { transfer: raw2 };
98733
- return void 0;
98733
+ return false;
98734
98734
  })(),
98735
98735
  hdrAutoDetect: envBool("PRODUCER_HDR_AUTO_DETECT", DEFAULT_CONFIG.hdrAutoDetect),
98736
98736
  audioGain: envNum("PRODUCER_AUDIO_GAIN", DEFAULT_CONFIG.audioGain),
@@ -101132,7 +101132,8 @@ async function injectVideoFramesBatch(page, updates) {
101132
101132
  let img = video.nextElementSibling;
101133
101133
  const isNewImage = !img || !img.classList.contains("__render_frame__");
101134
101134
  const computedStyle = window.getComputedStyle(video);
101135
- const computedOpacity = parseFloat(computedStyle.opacity) || 1;
101135
+ const opacityParsed = parseFloat(computedStyle.opacity);
101136
+ const computedOpacity = Number.isNaN(opacityParsed) ? 1 : opacityParsed;
101136
101137
  const sourceIsStatic = !computedStyle.position || computedStyle.position === "static";
101137
101138
  if (isNewImage) {
101138
101139
  img = document.createElement("img");
@@ -101178,7 +101179,6 @@ async function injectVideoFramesBatch(page, updates) {
101178
101179
  img.style.opacity = String(computedOpacity);
101179
101180
  img.style.visibility = "visible";
101180
101181
  video.style.setProperty("visibility", "hidden", "important");
101181
- video.style.setProperty("opacity", "0", "important");
101182
101182
  video.style.setProperty("pointer-events", "none", "important");
101183
101183
  }
101184
101184
  if (pendingDecodes.length > 0) {
@@ -101205,7 +101205,6 @@ async function syncVideoFrameVisibility(page, activeVideoIds) {
101205
101205
  } else {
101206
101206
  video.style.removeProperty("display");
101207
101207
  video.style.setProperty("visibility", "hidden", "important");
101208
- video.style.setProperty("opacity", "0", "important");
101209
101208
  video.style.setProperty("pointer-events", "none", "important");
101210
101209
  if (hasImg) {
101211
101210
  img.style.visibility = "hidden";
@@ -101296,7 +101295,7 @@ async function pollPageExpression(page, expression, timeoutMs, intervalMs = 100)
101296
101295
  while (Date.now() < deadline) {
101297
101296
  const ready = Boolean(await page.evaluate(expression));
101298
101297
  if (ready) return true;
101299
- await new Promise((resolve13) => setTimeout(resolve13, intervalMs));
101298
+ await new Promise((resolve14) => setTimeout(resolve14, intervalMs));
101300
101299
  }
101301
101300
  return Boolean(await page.evaluate(expression));
101302
101301
  }
@@ -101527,9 +101526,15 @@ async function captureFrameToBuffer(session, frameIndex, time) {
101527
101526
  return { buffer, captureTimeMs };
101528
101527
  }
101529
101528
  async function closeCaptureSession(session) {
101530
- if (session.page) await session.page.close().catch(() => {
101531
- });
101532
- if (session.browser) await releaseBrowser(session.browser, session.config);
101529
+ if (!session.pageReleased && session.page) {
101530
+ await session.page.close().catch(() => {
101531
+ });
101532
+ session.pageReleased = true;
101533
+ }
101534
+ if (!session.browserReleased && session.browser) {
101535
+ await releaseBrowser(session.browser, session.config);
101536
+ session.browserReleased = true;
101537
+ }
101533
101538
  session.isInitialized = false;
101534
101539
  }
101535
101540
  function prepareCaptureSessionForReuse(session, outputDir, onBeforeCapture) {
@@ -101573,7 +101578,7 @@ import { join as join6, dirname as dirname5 } from "path";
101573
101578
  // ../engine/src/utils/gpuEncoder.ts
101574
101579
  import { spawn as spawn3 } from "child_process";
101575
101580
  async function detectGpuEncoder() {
101576
- return new Promise((resolve13) => {
101581
+ return new Promise((resolve14) => {
101577
101582
  const ffmpeg = spawn3("ffmpeg", ["-encoders"], {
101578
101583
  stdio: ["pipe", "pipe", "pipe"]
101579
101584
  });
@@ -101582,13 +101587,13 @@ async function detectGpuEncoder() {
101582
101587
  stdout += data.toString();
101583
101588
  });
101584
101589
  ffmpeg.on("close", () => {
101585
- if (stdout.includes("h264_nvenc")) resolve13("nvenc");
101586
- else if (stdout.includes("h264_videotoolbox")) resolve13("videotoolbox");
101587
- else if (stdout.includes("h264_vaapi")) resolve13("vaapi");
101588
- else if (stdout.includes("h264_qsv")) resolve13("qsv");
101589
- else resolve13(null);
101590
+ if (stdout.includes("h264_nvenc")) resolve14("nvenc");
101591
+ else if (stdout.includes("h264_videotoolbox")) resolve14("videotoolbox");
101592
+ else if (stdout.includes("h264_vaapi")) resolve14("vaapi");
101593
+ else if (stdout.includes("h264_qsv")) resolve14("qsv");
101594
+ else resolve14(null);
101590
101595
  });
101591
- ffmpeg.on("error", () => resolve13(null));
101596
+ ffmpeg.on("error", () => resolve14(null));
101592
101597
  });
101593
101598
  }
101594
101599
  var cachedGpuEncoder = void 0;
@@ -101613,16 +101618,93 @@ function getGpuEncoderName(encoder, codec) {
101613
101618
  return codec === "h264" ? "libx264" : "libx265";
101614
101619
  }
101615
101620
  }
101621
+ var NVENC_PRESET_MAP = {
101622
+ ultrafast: "p1",
101623
+ superfast: "p1",
101624
+ veryfast: "p2",
101625
+ faster: "p3",
101626
+ fast: "p4",
101627
+ medium: "p4",
101628
+ slow: "p5",
101629
+ slower: "p6",
101630
+ veryslow: "p7",
101631
+ placebo: "p7"
101632
+ };
101633
+ var QSV_PRESET_MAP = {
101634
+ ultrafast: "veryfast",
101635
+ superfast: "veryfast",
101636
+ placebo: "veryslow"
101637
+ };
101638
+ function mapPresetForGpuEncoder(encoder, preset) {
101639
+ switch (encoder) {
101640
+ case "nvenc":
101641
+ if (/^p[1-7]$/.test(preset)) return preset;
101642
+ return NVENC_PRESET_MAP[preset] ?? "p4";
101643
+ case "qsv":
101644
+ return QSV_PRESET_MAP[preset] ?? preset;
101645
+ default:
101646
+ return preset;
101647
+ }
101648
+ }
101649
+
101650
+ // ../engine/src/utils/hdr.ts
101651
+ function isHdrColorSpace(cs) {
101652
+ if (!cs) return false;
101653
+ return cs.colorPrimaries.includes("bt2020") || cs.colorSpace.includes("bt2020") || cs.colorTransfer === "smpte2084" || cs.colorTransfer === "arib-std-b67";
101654
+ }
101655
+ function detectTransfer(cs) {
101656
+ if (cs?.colorTransfer === "smpte2084") return "pq";
101657
+ return "hlg";
101658
+ }
101659
+ var DEFAULT_HDR10_MASTERING = {
101660
+ masterDisplay: "G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)",
101661
+ maxCll: "1000,400"
101662
+ };
101663
+ function getHdrEncoderColorParams(transfer, mastering = DEFAULT_HDR10_MASTERING) {
101664
+ const colorTrc = transfer === "pq" ? "smpte2084" : "arib-std-b67";
101665
+ const tagging = `colorprim=bt2020:transfer=${colorTrc}:colormatrix=bt2020nc`;
101666
+ const metadata = `master-display=${mastering.masterDisplay}:max-cll=${mastering.maxCll}`;
101667
+ return {
101668
+ colorPrimaries: "bt2020",
101669
+ colorTrc,
101670
+ colorspace: "bt2020nc",
101671
+ pixelFormat: "yuv420p10le",
101672
+ x265ColorParams: `${tagging}:${metadata}`,
101673
+ mastering
101674
+ };
101675
+ }
101676
+ function analyzeCompositionHdr(colorSpaces) {
101677
+ let hasPq = false;
101678
+ let hasHdr = false;
101679
+ for (const cs of colorSpaces) {
101680
+ if (!isHdrColorSpace(cs)) continue;
101681
+ hasHdr = true;
101682
+ if (cs?.colorTransfer === "smpte2084") hasPq = true;
101683
+ }
101684
+ if (!hasHdr) return { hasHdr: false, dominantTransfer: null };
101685
+ const dominantTransfer = hasPq ? "pq" : "hlg";
101686
+ return { hasHdr: true, dominantTransfer };
101687
+ }
101616
101688
 
101617
101689
  // ../engine/src/utils/runFfmpeg.ts
101618
101690
  import { spawn as spawn4 } from "child_process";
101619
101691
  var DEFAULT_TIMEOUT2 = 3e5;
101692
+ var DEFAULT_STDERR_TAIL_LINES = 15;
101693
+ function formatFfmpegError(exitCode, stderr, tailLines = DEFAULT_STDERR_TAIL_LINES) {
101694
+ const tail = (stderr ?? "").split(/\r?\n/).filter((line) => line.length > 0).slice(-tailLines).join("\n");
101695
+ if (exitCode === null) {
101696
+ return tail ? `[FFmpeg] ${tail}` : "[FFmpeg] process error";
101697
+ }
101698
+ return tail ? `FFmpeg exited with code ${exitCode}
101699
+ ffmpeg stderr (tail):
101700
+ ${tail}` : `FFmpeg exited with code ${exitCode}`;
101701
+ }
101620
101702
  async function runFfmpeg(args, opts) {
101621
101703
  const startMs = Date.now();
101622
101704
  const signal = opts?.signal;
101623
101705
  const timeout2 = opts?.timeout ?? DEFAULT_TIMEOUT2;
101624
101706
  const onStderr = opts?.onStderr;
101625
- return new Promise((resolve13) => {
101707
+ return new Promise((resolve14) => {
101626
101708
  const ffmpeg = spawn4("ffmpeg", args);
101627
101709
  let stderr = "";
101628
101710
  const onAbort = () => {
@@ -101648,7 +101730,7 @@ async function runFfmpeg(args, opts) {
101648
101730
  ffmpeg.on("close", (code) => {
101649
101731
  clearTimeout(timer2);
101650
101732
  if (signal) signal.removeEventListener("abort", onAbort);
101651
- resolve13({
101733
+ resolve14({
101652
101734
  success: !signal?.aborted && code === 0,
101653
101735
  exitCode: code,
101654
101736
  stderr,
@@ -101658,7 +101740,7 @@ async function runFfmpeg(args, opts) {
101658
101740
  ffmpeg.on("error", (err) => {
101659
101741
  clearTimeout(timer2);
101660
101742
  if (signal) signal.removeEventListener("abort", onAbort);
101661
- resolve13({
101743
+ resolve14({
101662
101744
  success: false,
101663
101745
  exitCode: null,
101664
101746
  stderr: err.message,
@@ -101713,6 +101795,12 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
101713
101795
  pixelFormat = "yuv420p",
101714
101796
  useGpu = false
101715
101797
  } = options;
101798
+ if (options.hdr && codec === "h264") {
101799
+ console.warn(
101800
+ "[chunkEncoder] HDR is not supported with codec=h264 (libx264 has no HDR support). Stripping HDR metadata and tagging output as SDR/BT.709. Use codec=h265 for HDR output."
101801
+ );
101802
+ options = { ...options, hdr: void 0 };
101803
+ }
101716
101804
  const args = [...inputArgs, "-r", String(fps)];
101717
101805
  const shouldUseGpu = useGpu && gpuEncoder !== null;
101718
101806
  if (codec === "h264" || codec === "h265") {
@@ -101721,7 +101809,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
101721
101809
  args.push("-c:v", encoderName);
101722
101810
  switch (gpuEncoder) {
101723
101811
  case "nvenc":
101724
- args.push("-preset", preset);
101812
+ args.push("-preset", mapPresetForGpuEncoder("nvenc", preset));
101725
101813
  if (bitrate) args.push("-b:v", bitrate);
101726
101814
  else args.push("-cq", String(quality));
101727
101815
  break;
@@ -101740,7 +101828,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
101740
101828
  else args.push("-qp", String(quality));
101741
101829
  break;
101742
101830
  case "qsv":
101743
- args.push("-preset", preset);
101831
+ args.push("-preset", mapPresetForGpuEncoder("qsv", preset));
101744
101832
  if (bitrate) args.push("-b:v", bitrate);
101745
101833
  else args.push("-global_quality", String(quality));
101746
101834
  break;
@@ -101751,7 +101839,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
101751
101839
  if (bitrate) args.push("-b:v", bitrate);
101752
101840
  else args.push("-crf", String(quality));
101753
101841
  const xParamsFlag = codec === "h264" ? "-x264-params" : "-x265-params";
101754
- const colorParams = "colorprim=bt709:transfer=bt709:colormatrix=bt709";
101842
+ const colorParams = codec === "h265" && options.hdr ? getHdrEncoderColorParams(options.hdr.transfer).x265ColorParams : "colorprim=bt709:transfer=bt709:colormatrix=bt709";
101755
101843
  if (preset === "ultrafast") {
101756
101844
  args.push(xParamsFlag, `aq-mode=3:${colorParams}`);
101757
101845
  } else {
@@ -101775,16 +101863,30 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
101775
101863
  return [...args, "-y", outputPath];
101776
101864
  }
101777
101865
  if (codec === "h264" || codec === "h265") {
101778
- args.push(
101779
- "-colorspace:v",
101780
- "bt709",
101781
- "-color_primaries:v",
101782
- "bt709",
101783
- "-color_trc:v",
101784
- "bt709",
101785
- "-color_range",
101786
- "tv"
101787
- );
101866
+ if (options.hdr) {
101867
+ const transferTag = options.hdr.transfer === "pq" ? "smpte2084" : "arib-std-b67";
101868
+ args.push(
101869
+ "-colorspace:v",
101870
+ "bt2020nc",
101871
+ "-color_primaries:v",
101872
+ "bt2020",
101873
+ "-color_trc:v",
101874
+ transferTag,
101875
+ "-color_range",
101876
+ "tv"
101877
+ );
101878
+ } else {
101879
+ args.push(
101880
+ "-colorspace:v",
101881
+ "bt709",
101882
+ "-color_primaries:v",
101883
+ "bt709",
101884
+ "-color_trc:v",
101885
+ "bt709",
101886
+ "-color_range",
101887
+ "tv"
101888
+ );
101889
+ }
101788
101890
  if (gpuEncoder === "vaapi") {
101789
101891
  const vfIdx = args.indexOf("-vf");
101790
101892
  if (vfIdx !== -1) {
@@ -101824,7 +101926,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
101824
101926
  const inputPath = join6(framesDir, framePattern);
101825
101927
  const inputArgs = ["-framerate", String(options.fps), "-i", inputPath];
101826
101928
  const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
101827
- return new Promise((resolve13) => {
101929
+ return new Promise((resolve14) => {
101828
101930
  const ffmpeg = spawn5("ffmpeg", args);
101829
101931
  let stderr = "";
101830
101932
  const onAbort = () => {
@@ -101849,7 +101951,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
101849
101951
  if (signal) signal.removeEventListener("abort", onAbort);
101850
101952
  const durationMs = Date.now() - startTime;
101851
101953
  if (signal?.aborted) {
101852
- resolve13({
101954
+ resolve14({
101853
101955
  success: false,
101854
101956
  outputPath,
101855
101957
  durationMs,
@@ -101860,23 +101962,23 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
101860
101962
  return;
101861
101963
  }
101862
101964
  if (code !== 0) {
101863
- resolve13({
101965
+ resolve14({
101864
101966
  success: false,
101865
101967
  outputPath,
101866
101968
  durationMs,
101867
101969
  framesEncoded: 0,
101868
101970
  fileSize: 0,
101869
- error: `FFmpeg exited with code ${code}`
101971
+ error: formatFfmpegError(code, stderr)
101870
101972
  });
101871
101973
  return;
101872
101974
  }
101873
101975
  const fileSize = existsSync5(outputPath) ? statSync3(outputPath).size : 0;
101874
- resolve13({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
101976
+ resolve14({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
101875
101977
  });
101876
101978
  ffmpeg.on("error", (err) => {
101877
101979
  clearTimeout(timer2);
101878
101980
  if (signal) signal.removeEventListener("abort", onAbort);
101879
- resolve13({
101981
+ resolve14({
101880
101982
  success: false,
101881
101983
  outputPath,
101882
101984
  durationMs: Date.now() - startTime,
@@ -101934,18 +102036,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
101934
102036
  let gpuEncoder = null;
101935
102037
  if (options.useGpu) gpuEncoder = await getCachedGpuEncoder();
101936
102038
  const args = buildEncoderArgs(options, inputArgs, chunkPath, gpuEncoder);
101937
- const chunkResult = await new Promise((resolve13) => {
102039
+ const chunkResult = await new Promise((resolve14) => {
101938
102040
  const ffmpeg = spawn5("ffmpeg", args);
101939
102041
  let stderr = "";
101940
102042
  ffmpeg.stderr.on("data", (d) => {
101941
102043
  stderr += d.toString();
101942
102044
  });
101943
102045
  ffmpeg.on("close", (code) => {
101944
- if (code === 0) resolve13({ success: true });
101945
- else resolve13({ success: false, error: `Chunk ${i} encode failed: ${stderr.slice(-400)}` });
102046
+ if (code === 0) resolve14({ success: true });
102047
+ else resolve14({ success: false, error: `Chunk ${i} encode failed: ${stderr.slice(-400)}` });
101946
102048
  });
101947
102049
  ffmpeg.on("error", (err) => {
101948
- resolve13({ success: false, error: `Chunk ${i} encode error: ${err.message}` });
102050
+ resolve14({ success: false, error: `Chunk ${i} encode error: ${err.message}` });
101949
102051
  });
101950
102052
  });
101951
102053
  if (!chunkResult.success) {
@@ -101975,18 +102077,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
101975
102077
  "-y",
101976
102078
  outputPath
101977
102079
  ];
101978
- const concatResult = await new Promise((resolve13) => {
102080
+ const concatResult = await new Promise((resolve14) => {
101979
102081
  const ffmpeg = spawn5("ffmpeg", concatArgs);
101980
102082
  let stderr = "";
101981
102083
  ffmpeg.stderr.on("data", (d) => {
101982
102084
  stderr += d.toString();
101983
102085
  });
101984
102086
  ffmpeg.on("close", (code) => {
101985
- if (code === 0) resolve13({ success: true });
101986
- else resolve13({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
102087
+ if (code === 0) resolve14({ success: true });
102088
+ else resolve14({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
101987
102089
  });
101988
102090
  ffmpeg.on("error", (err) => {
101989
- resolve13({ success: false, error: `Chunk concat error: ${err.message}` });
102091
+ resolve14({ success: false, error: `Chunk concat error: ${err.message}` });
101990
102092
  });
101991
102093
  });
101992
102094
  if (!concatResult.success) {
@@ -102036,7 +102138,7 @@ async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, confi
102036
102138
  success: result.success,
102037
102139
  outputPath,
102038
102140
  durationMs: result.durationMs,
102039
- error: !result.success ? result.exitCode !== null ? `FFmpeg exited with code ${result.exitCode}` : `[FFmpeg] ${result.stderr}` : void 0
102141
+ error: !result.success ? formatFfmpegError(result.exitCode, result.stderr) : void 0
102040
102142
  };
102041
102143
  }
102042
102144
  async function applyFaststart(inputPath, outputPath, signal, config2) {
@@ -102059,7 +102161,7 @@ async function applyFaststart(inputPath, outputPath, signal, config2) {
102059
102161
  success: result.success,
102060
102162
  outputPath,
102061
102163
  durationMs: result.durationMs,
102062
- error: !result.success ? result.exitCode !== null ? `FFmpeg exited with code ${result.exitCode}` : `[FFmpeg] ${result.stderr}` : void 0
102164
+ error: !result.success ? formatFfmpegError(result.exitCode, result.stderr) : void 0
102063
102165
  };
102064
102166
  }
102065
102167
 
@@ -102067,81 +102169,40 @@ async function applyFaststart(inputPath, outputPath, signal, config2) {
102067
102169
  import { spawn as spawn6 } from "child_process";
102068
102170
  import { existsSync as existsSync6, mkdirSync as mkdirSync3, statSync as statSync4 } from "fs";
102069
102171
  import { dirname as dirname6 } from "path";
102070
-
102071
- // ../engine/src/utils/hdr.ts
102072
- function isHdrColorSpace(cs) {
102073
- if (!cs) return false;
102074
- return cs.colorPrimaries.includes("bt2020") || cs.colorSpace.includes("bt2020") || cs.colorTransfer === "smpte2084" || cs.colorTransfer === "arib-std-b67";
102075
- }
102076
- function detectTransfer(cs) {
102077
- if (cs?.colorTransfer === "smpte2084") return "pq";
102078
- return "hlg";
102079
- }
102080
- var DEFAULT_HDR10_MASTERING = {
102081
- masterDisplay: "G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)",
102082
- maxCll: "1000,400"
102083
- };
102084
- function getHdrEncoderColorParams(transfer, mastering = DEFAULT_HDR10_MASTERING) {
102085
- const colorTrc = transfer === "pq" ? "smpte2084" : "arib-std-b67";
102086
- const tagging = `colorprim=bt2020:transfer=${colorTrc}:colormatrix=bt2020nc`;
102087
- const metadata = `master-display=${mastering.masterDisplay}:max-cll=${mastering.maxCll}`;
102088
- return {
102089
- colorPrimaries: "bt2020",
102090
- colorTrc,
102091
- colorspace: "bt2020nc",
102092
- pixelFormat: "yuv420p10le",
102093
- x265ColorParams: `${tagging}:${metadata}`,
102094
- mastering
102095
- };
102096
- }
102097
- function analyzeCompositionHdr(colorSpaces) {
102098
- let hasPq = false;
102099
- let hasHdr = false;
102100
- for (const cs of colorSpaces) {
102101
- if (!isHdrColorSpace(cs)) continue;
102102
- hasHdr = true;
102103
- if (cs?.colorTransfer === "smpte2084") hasPq = true;
102104
- }
102105
- if (!hasHdr) return { hasHdr: false, dominantTransfer: null };
102106
- const dominantTransfer = hasPq ? "pq" : "hlg";
102107
- return { hasHdr: true, dominantTransfer };
102108
- }
102109
-
102110
- // ../engine/src/services/streamingEncoder.ts
102111
102172
  function createFrameReorderBuffer(startFrame, endFrame) {
102112
102173
  let cursor = startFrame;
102113
102174
  const pending = /* @__PURE__ */ new Map();
102114
- const enqueueAt = (frame, resolve13) => {
102175
+ const enqueueAt = (frame, resolve14) => {
102115
102176
  const list = pending.get(frame);
102116
102177
  if (list === void 0) {
102117
- pending.set(frame, [resolve13]);
102178
+ pending.set(frame, [resolve14]);
102118
102179
  } else {
102119
- list.push(resolve13);
102180
+ list.push(resolve14);
102120
102181
  }
102121
102182
  };
102122
102183
  const flushAt = (frame) => {
102123
102184
  const list = pending.get(frame);
102124
102185
  if (list === void 0) return;
102125
102186
  pending.delete(frame);
102126
- for (const resolve13 of list) resolve13();
102187
+ for (const resolve14 of list) resolve14();
102127
102188
  };
102128
- const waitForFrame = (frame) => new Promise((resolve13) => {
102189
+ const waitForFrame = (frame) => new Promise((resolve14) => {
102129
102190
  if (frame === cursor) {
102130
- resolve13();
102191
+ resolve14();
102131
102192
  return;
102132
102193
  }
102133
- enqueueAt(frame, resolve13);
102194
+ enqueueAt(frame, resolve14);
102134
102195
  });
102135
102196
  const advanceTo = (frame) => {
102136
102197
  cursor = frame;
102137
102198
  flushAt(frame);
102138
102199
  };
102139
- const waitForAllDone = () => new Promise((resolve13) => {
102200
+ const waitForAllDone = () => new Promise((resolve14) => {
102140
102201
  if (cursor >= endFrame) {
102141
- resolve13();
102202
+ resolve14();
102142
102203
  return;
102143
102204
  }
102144
- enqueueAt(endFrame, resolve13);
102205
+ enqueueAt(endFrame, resolve14);
102145
102206
  });
102146
102207
  return { waitForFrame, advanceTo, waitForAllDone };
102147
102208
  }
@@ -102193,7 +102254,7 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
102193
102254
  args.push("-c:v", encoderName);
102194
102255
  switch (gpuEncoder) {
102195
102256
  case "nvenc":
102196
- args.push("-preset", preset);
102257
+ args.push("-preset", mapPresetForGpuEncoder("nvenc", preset));
102197
102258
  if (bitrate) args.push("-b:v", bitrate);
102198
102259
  else args.push("-cq", String(quality));
102199
102260
  break;
@@ -102212,7 +102273,7 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
102212
102273
  else args.push("-qp", String(quality));
102213
102274
  break;
102214
102275
  case "qsv":
102215
- args.push("-preset", preset);
102276
+ args.push("-preset", mapPresetForGpuEncoder("qsv", preset));
102216
102277
  if (bitrate) args.push("-b:v", bitrate);
102217
102278
  else args.push("-global_quality", String(quality));
102218
102279
  break;
@@ -102303,7 +102364,7 @@ async function spawnStreamingEncoder(outputPath, options, signal, config2) {
102303
102364
  let stderr = "";
102304
102365
  let exitCode = null;
102305
102366
  let exitPromiseResolve = null;
102306
- const exitPromise = new Promise((resolve13) => exitPromiseResolve = resolve13);
102367
+ const exitPromise = new Promise((resolve14) => exitPromiseResolve = resolve14);
102307
102368
  ffmpeg.stderr?.on("data", (data) => {
102308
102369
  stderr += data.toString();
102309
102370
  });
@@ -102349,8 +102410,8 @@ Process error: ${err.message}`;
102349
102410
  if (signal) signal.removeEventListener("abort", onAbort);
102350
102411
  const stdin = ffmpeg.stdin;
102351
102412
  if (stdin && !stdin.destroyed) {
102352
- await new Promise((resolve13) => {
102353
- stdin.end(() => resolve13());
102413
+ await new Promise((resolve14) => {
102414
+ stdin.end(() => resolve14());
102354
102415
  });
102355
102416
  }
102356
102417
  await exitPromise;
@@ -102368,7 +102429,7 @@ Process error: ${err.message}`;
102368
102429
  success: false,
102369
102430
  durationMs,
102370
102431
  fileSize: 0,
102371
- error: `FFmpeg exited with code ${exitCode}`
102432
+ error: formatFfmpegError(exitCode, stderr)
102372
102433
  };
102373
102434
  }
102374
102435
  const fileSize = existsSync6(outputPath) ? statSync4(outputPath).size : 0;
@@ -102382,14 +102443,14 @@ Process error: ${err.message}`;
102382
102443
  // ../engine/src/services/videoFrameExtractor.ts
102383
102444
  import { spawn as spawn8 } from "child_process";
102384
102445
  import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync4, rmSync } from "fs";
102385
- import { join as join8 } from "path";
102446
+ import { isAbsolute as isAbsolute2, join as join8 } from "path";
102386
102447
 
102387
102448
  // ../engine/src/utils/ffprobe.ts
102388
102449
  import { spawn as spawn7 } from "child_process";
102389
102450
  import { readFileSync as readFileSync5 } from "fs";
102390
102451
  import { extname as extname2 } from "path";
102391
102452
  function runFfprobe(args) {
102392
- return new Promise((resolve13, reject) => {
102453
+ return new Promise((resolve14, reject) => {
102393
102454
  const proc = spawn7("ffprobe", args);
102394
102455
  let stdout = "";
102395
102456
  let stderr = "";
@@ -102403,7 +102464,7 @@ function runFfprobe(args) {
102403
102464
  if (code !== 0) {
102404
102465
  reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
102405
102466
  } else {
102406
- resolve13(stdout);
102467
+ resolve14(stdout);
102407
102468
  }
102408
102469
  });
102409
102470
  proc.on("error", (err) => {
@@ -102497,7 +102558,7 @@ function parseFrameRate(frameRateStr) {
102497
102558
  }
102498
102559
  return parseFloat(frameRateStr) || 0;
102499
102560
  }
102500
- async function extractVideoMetadata(filePath) {
102561
+ async function extractMediaMetadata(filePath) {
102501
102562
  const cached = videoMetadataCache.get(filePath);
102502
102563
  if (cached) return cached;
102503
102564
  const probePromise = (async () => {
@@ -102783,7 +102844,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
102783
102844
  const { fps, outputDir, quality = 95, format: format3 = "jpg" } = options;
102784
102845
  const videoOutputDir = join8(outputDir, videoId);
102785
102846
  if (!existsSync8(videoOutputDir)) mkdirSync5(videoOutputDir, { recursive: true });
102786
- const metadata = await extractVideoMetadata(videoPath);
102847
+ const metadata = await extractMediaMetadata(videoPath);
102787
102848
  const framePattern = `frame_%05d.${format3}`;
102788
102849
  const outputPattern = join8(videoOutputDir, framePattern);
102789
102850
  const isHdr = isHdrColorSpace(metadata.colorSpace);
@@ -102802,7 +102863,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
102802
102863
  args.push("-q:v", format3 === "jpg" ? String(Math.ceil((100 - quality) / 3)) : "0");
102803
102864
  if (format3 === "png") args.push("-compression_level", "6");
102804
102865
  args.push("-y", outputPattern);
102805
- return new Promise((resolve13, reject) => {
102866
+ return new Promise((resolve14, reject) => {
102806
102867
  const ffmpeg = spawn8("ffmpeg", args);
102807
102868
  let stderr = "";
102808
102869
  const onAbort = () => {
@@ -102837,7 +102898,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
102837
102898
  files.forEach((file, index) => {
102838
102899
  framePaths.set(index, join8(videoOutputDir, file));
102839
102900
  });
102840
- resolve13({
102901
+ resolve14({
102841
102902
  videoId,
102842
102903
  srcPath: videoPath,
102843
102904
  outputDir: videoOutputDir,
@@ -102859,8 +102920,9 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
102859
102920
  });
102860
102921
  });
102861
102922
  }
102862
- async function convertSdrToHdr(inputPath, outputPath, signal, config2) {
102923
+ async function convertSdrToHdr(inputPath, outputPath, targetTransfer, signal, config2) {
102863
102924
  const timeout2 = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
102925
+ const colorTrc = targetTransfer === "pq" ? "smpte2084" : "arib-std-b67";
102864
102926
  const args = [
102865
102927
  "-i",
102866
102928
  inputPath,
@@ -102869,7 +102931,7 @@ async function convertSdrToHdr(inputPath, outputPath, signal, config2) {
102869
102931
  "-color_primaries",
102870
102932
  "bt2020",
102871
102933
  "-color_trc",
102872
- "arib-std-b67",
102934
+ colorTrc,
102873
102935
  "-colorspace",
102874
102936
  "bt2020nc",
102875
102937
  "-c:v",
@@ -102931,7 +102993,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
102931
102993
  if (signal?.aborted) break;
102932
102994
  try {
102933
102995
  let videoPath = video.src;
102934
- if (!videoPath.startsWith("/") && !isHttpUrl(videoPath)) {
102996
+ if (!isAbsolute2(videoPath) && !isHttpUrl(videoPath)) {
102935
102997
  const fromCompiled = compiledDir ? join8(compiledDir, videoPath) : null;
102936
102998
  videoPath = fromCompiled && existsSync8(fromCompiled) ? fromCompiled : join8(baseDir, videoPath);
102937
102999
  }
@@ -102951,12 +103013,13 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
102951
103013
  }
102952
103014
  const videoColorSpaces = await Promise.all(
102953
103015
  resolvedVideos.map(async ({ videoPath }) => {
102954
- const metadata = await extractVideoMetadata(videoPath);
103016
+ const metadata = await extractMediaMetadata(videoPath);
102955
103017
  return metadata.colorSpace;
102956
103018
  })
102957
103019
  );
102958
- const hasAnyHdr = videoColorSpaces.some(isHdrColorSpace);
102959
- if (hasAnyHdr) {
103020
+ const hdrInfo = analyzeCompositionHdr(videoColorSpaces);
103021
+ if (hdrInfo.hasHdr && hdrInfo.dominantTransfer) {
103022
+ const targetTransfer = hdrInfo.dominantTransfer;
102960
103023
  const convertDir = join8(options.outputDir, "_hdr_normalized");
102961
103024
  mkdirSync5(convertDir, { recursive: true });
102962
103025
  for (let i = 0; i < resolvedVideos.length; i++) {
@@ -102967,7 +103030,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
102967
103030
  if (!entry) continue;
102968
103031
  const convertedPath = join8(convertDir, `${entry.video.id}_hdr.mp4`);
102969
103032
  try {
102970
- await convertSdrToHdr(entry.videoPath, convertedPath, signal, config2);
103033
+ await convertSdrToHdr(entry.videoPath, convertedPath, targetTransfer, signal, config2);
102971
103034
  entry.videoPath = convertedPath;
102972
103035
  } catch (err) {
102973
103036
  errors.push({
@@ -102983,7 +103046,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
102983
103046
  if (signal?.aborted) break;
102984
103047
  const entry = resolvedVideos[i];
102985
103048
  if (!entry) continue;
102986
- const metadata = await extractVideoMetadata(entry.videoPath);
103049
+ const metadata = await extractMediaMetadata(entry.videoPath);
102987
103050
  if (!metadata.isVFR) continue;
102988
103051
  let segDuration = entry.video.end - entry.video.start;
102989
103052
  if (!Number.isFinite(segDuration) || segDuration <= 0) {
@@ -103019,7 +103082,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
103019
103082
  try {
103020
103083
  let videoDuration = video.end - video.start;
103021
103084
  if (!Number.isFinite(videoDuration) || videoDuration <= 0) {
103022
- const metadata = await extractVideoMetadata(videoPath);
103085
+ const metadata = await extractMediaMetadata(videoPath);
103023
103086
  const sourceDuration = metadata.durationSeconds - video.mediaStart;
103024
103087
  videoDuration = sourceDuration > 0 ? sourceDuration : metadata.durationSeconds;
103025
103088
  video.end = video.start + videoDuration;
@@ -103272,12 +103335,12 @@ async function queryElementStacking(page, nativeHdrIds) {
103272
103335
  function resolveRadius(value, el) {
103273
103336
  if (value.includes("%")) {
103274
103337
  const pct = parseFloat(value) / 100;
103275
- const htmlEl = el;
103276
- const w = htmlEl.offsetWidth || 0;
103277
- const h = htmlEl.offsetHeight || 0;
103338
+ const w = el instanceof HTMLElement ? el.offsetWidth : 0;
103339
+ const h = el instanceof HTMLElement ? el.offsetHeight : 0;
103278
103340
  return pct * Math.min(w, h);
103279
103341
  }
103280
- return parseFloat(value) || 0;
103342
+ const parsed = parseFloat(value);
103343
+ return Number.isNaN(parsed) ? 0 : parsed;
103281
103344
  }
103282
103345
  const selfCs = window.getComputedStyle(node);
103283
103346
  const selfRadii = [
@@ -103361,8 +103424,7 @@ async function queryElementStacking(page, nativeHdrIds) {
103361
103424
  const style = window.getComputedStyle(el);
103362
103425
  const zIndex = getEffectiveZIndex(el);
103363
103426
  const isHdrEl = hdrSet.has(id);
103364
- const opacityStartNode = isHdrEl ? el.parentElement : el;
103365
- const opacity = opacityStartNode ? getEffectiveOpacity(opacityStartNode) : 1;
103427
+ const opacity = getEffectiveOpacity(el);
103366
103428
  const visible = style.visibility !== "hidden" && style.display !== "none" && rect.width > 0 && rect.height > 0;
103367
103429
  const htmlEl = el instanceof HTMLElement ? el : null;
103368
103430
  results.push({
@@ -103395,7 +103457,7 @@ async function queryElementStacking(page, nativeHdrIds) {
103395
103457
 
103396
103458
  // ../engine/src/services/audioMixer.ts
103397
103459
  import { existsSync as existsSync9, mkdirSync as mkdirSync6, rmSync as rmSync2 } from "fs";
103398
- import { join as join9, dirname as dirname7 } from "path";
103460
+ import { isAbsolute as isAbsolute3, join as join9, dirname as dirname7 } from "path";
103399
103461
  function parseAudioElements(html) {
103400
103462
  const elements = [];
103401
103463
  const { document: document2 } = parseHTML(html);
@@ -103622,7 +103684,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
103622
103684
  }
103623
103685
  try {
103624
103686
  let srcPath = element.src;
103625
- if (!srcPath.startsWith("/") && !isHttpUrl(srcPath)) {
103687
+ if (!isAbsolute3(srcPath) && !isHttpUrl(srcPath)) {
103626
103688
  const fromCompiled = compiledDir ? join9(compiledDir, srcPath) : null;
103627
103689
  srcPath = fromCompiled && existsSync9(fromCompiled) ? fromCompiled : join9(baseDir, srcPath);
103628
103690
  }
@@ -106359,7 +106421,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
106359
106421
  });
106360
106422
  if (!chunk) {
106361
106423
  if (i === 1) {
106362
- await new Promise((resolve13) => setTimeout(resolve13));
106424
+ await new Promise((resolve14) => setTimeout(resolve14));
106363
106425
  maxReadCount = 3;
106364
106426
  continue;
106365
106427
  }
@@ -106972,13 +107034,51 @@ function normalizeObjectFit(value) {
106972
107034
  }
106973
107035
  function parseTransformMatrix(css) {
106974
107036
  if (!css || css === "none") return null;
106975
- const match2 = css.match(
107037
+ const match2d = css.match(
106976
107038
  /^matrix\(\s*([^,]+),\s*([^,]+),\s*([^,]+),\s*([^,]+),\s*([^,]+),\s*([^,)]+)\s*\)$/
106977
107039
  );
106978
- if (!match2) return null;
106979
- const values = match2.slice(1, 7).map(Number);
106980
- if (!values.every(Number.isFinite)) return null;
106981
- return values;
107040
+ if (match2d) {
107041
+ const values = match2d.slice(1, 7).map(Number);
107042
+ if (!values.every(Number.isFinite)) return null;
107043
+ return values;
107044
+ }
107045
+ const match3d = css.match(/^matrix3d\(\s*([^)]+)\)$/);
107046
+ if (match3d) {
107047
+ const raw2 = match3d[1];
107048
+ if (!raw2) return null;
107049
+ const parts = raw2.split(",").map((s) => Number(s.trim()));
107050
+ if (parts.length !== 16 || !parts.every(Number.isFinite)) return null;
107051
+ warnIfZSignificant(parts);
107052
+ return [
107053
+ parts[0],
107054
+ parts[1],
107055
+ parts[4],
107056
+ parts[5],
107057
+ parts[12],
107058
+ parts[13]
107059
+ ];
107060
+ }
107061
+ return null;
107062
+ }
107063
+ var warnedZSignificant = false;
107064
+ var Z_EPSILON = 1e-6;
107065
+ function warnIfZSignificant(parts) {
107066
+ if (warnedZSignificant) return;
107067
+ const a3 = parts[8] ?? 0;
107068
+ const b3 = parts[9] ?? 0;
107069
+ const c1 = parts[2] ?? 0;
107070
+ const c2 = parts[6] ?? 0;
107071
+ const c3 = parts[10] ?? 1;
107072
+ const d1 = parts[3] ?? 0;
107073
+ const d2 = parts[7] ?? 0;
107074
+ const d3 = parts[11] ?? 0;
107075
+ const d4 = parts[15] ?? 1;
107076
+ if (Math.abs(a3) > Z_EPSILON || Math.abs(b3) > Z_EPSILON || Math.abs(c1) > Z_EPSILON || Math.abs(c2) > Z_EPSILON || Math.abs(c3 - 1) > Z_EPSILON || Math.abs(d1) > Z_EPSILON || Math.abs(d2) > Z_EPSILON || Math.abs(d3) > Z_EPSILON || Math.abs(d4 - 1) > Z_EPSILON) {
107077
+ warnedZSignificant = true;
107078
+ console.warn(
107079
+ `[alphaBlit] parseTransformMatrix received a matrix3d with non-trivial 3D components (a3=${a3}, b3=${b3}, c1=${c1}, c2=${c2}, c3=${c3}, d1=${d1}, d2=${d2}, d3=${d3}, d4=${d4}). The engine projects 3D transforms to 2D (m11, m12, m21, m22, m41, m42) and silently discards perspective and out-of-plane rotation. If your composition uses real 3D (rotateX/Y, perspective), the rendered output will not match the studio preview. Z translation (translateZ) is dropped by design and does not trigger this warning. This warning is emitted once per process.`
107080
+ );
107081
+ }
106982
107082
  }
106983
107083
 
106984
107084
  // ../engine/src/utils/layerCompositor.ts
@@ -107632,14 +107732,14 @@ var ridgedBurn = (from2, to, out, w, h, p) => {
107632
107732
  TRANSITIONS["ridged-burn"] = ridgedBurn;
107633
107733
 
107634
107734
  // src/services/renderOrchestrator.ts
107635
- import { join as join15, dirname as dirname10, resolve as resolve10 } from "path";
107735
+ import { join as join15, dirname as dirname10, resolve as resolve11 } from "path";
107636
107736
  import { randomUUID } from "crypto";
107637
107737
  import { freemem as freemem2 } from "os";
107638
107738
  import { fileURLToPath as fileURLToPath3 } from "url";
107639
107739
 
107640
107740
  // src/services/fileServer.ts
107641
- import { readFileSync as readFileSync7, existsSync as existsSync12, statSync as statSync5 } from "node:fs";
107642
- import { join as join11, extname as extname4 } from "node:path";
107741
+ import { readFileSync as readFileSync7, existsSync as existsSync12, realpathSync, statSync as statSync5 } from "node:fs";
107742
+ import { join as join11, extname as extname4, resolve as resolve8, sep } from "node:path";
107643
107743
 
107644
107744
  // src/services/hyperframeRuntimeLoader.ts
107645
107745
  import { createHash as createHash2 } from "node:crypto";
@@ -107715,6 +107815,18 @@ function resolveVerifiedHyperframeRuntime() {
107715
107815
  }
107716
107816
 
107717
107817
  // src/services/fileServer.ts
107818
+ function isPathInside(child, parent, options = {}) {
107819
+ const { resolveSymlinks = false, pathModule } = options;
107820
+ const resolveFn = pathModule?.resolve ?? resolve8;
107821
+ const separator = pathModule?.sep ?? sep;
107822
+ const resolvedChild = resolveFn(child);
107823
+ const resolvedParent = resolveFn(parent);
107824
+ const normalizedChild = resolveSymlinks && existsSync12(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
107825
+ const normalizedParent = resolveSymlinks && existsSync12(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
107826
+ if (normalizedChild === normalizedParent) return true;
107827
+ const parentWithSep = normalizedParent.endsWith(separator) ? normalizedParent : normalizedParent + separator;
107828
+ return normalizedChild.startsWith(parentWithSep);
107829
+ }
107718
107830
  var MIME_TYPES = {
107719
107831
  ".html": "text/html; charset=utf-8",
107720
107832
  ".css": "text/css; charset=utf-8",
@@ -108107,12 +108219,20 @@ function createFileServer2(options) {
108107
108219
  let requestPath = c.req.path;
108108
108220
  if (requestPath === "/") requestPath = "/index.html";
108109
108221
  const relativePath = requestPath.replace(/^\//, "");
108110
- const compiledPath = compiledDir ? join11(compiledDir, relativePath) : null;
108111
- const hasCompiledFile = Boolean(
108112
- compiledPath && existsSync12(compiledPath) && statSync5(compiledPath).isFile()
108113
- );
108114
- const filePath = hasCompiledFile ? compiledPath : join11(projectDir, relativePath);
108115
- if (!existsSync12(filePath) || !statSync5(filePath).isFile()) {
108222
+ let filePath = null;
108223
+ if (compiledDir) {
108224
+ const candidate = join11(compiledDir, relativePath);
108225
+ if (existsSync12(candidate) && isPathInside(candidate, compiledDir, { resolveSymlinks: true }) && statSync5(candidate).isFile()) {
108226
+ filePath = candidate;
108227
+ }
108228
+ }
108229
+ if (!filePath) {
108230
+ const candidate = join11(projectDir, relativePath);
108231
+ if (existsSync12(candidate) && isPathInside(candidate, projectDir, { resolveSymlinks: true }) && statSync5(candidate).isFile()) {
108232
+ filePath = candidate;
108233
+ }
108234
+ }
108235
+ if (!filePath) {
108116
108236
  if (!/favicon\.ico$/i.test(requestPath)) {
108117
108237
  console.warn(`[FileServer] 404 Not Found: ${requestPath}`);
108118
108238
  }
@@ -108136,10 +108256,10 @@ function createFileServer2(options) {
108136
108256
  headers: { "Content-Type": contentType }
108137
108257
  });
108138
108258
  });
108139
- return new Promise((resolve13) => {
108259
+ return new Promise((resolve14) => {
108140
108260
  const connections = /* @__PURE__ */ new Set();
108141
108261
  const server = serve({ fetch: app.fetch, port }, (info) => {
108142
- resolve13({
108262
+ resolve14({
108143
108263
  url: `http://localhost:${info.port}`,
108144
108264
  port: info.port,
108145
108265
  close: () => {
@@ -108158,18 +108278,18 @@ function createFileServer2(options) {
108158
108278
 
108159
108279
  // src/services/htmlCompiler.ts
108160
108280
  import { readFileSync as readFileSync9, existsSync as existsSync14, mkdirSync as mkdirSync9 } from "fs";
108161
- import { join as join14, dirname as dirname9, resolve as resolve9 } from "path";
108281
+ import { join as join14, dirname as dirname9, resolve as resolve10 } from "path";
108162
108282
  import postcss from "postcss";
108163
108283
 
108164
108284
  // src/utils/paths.ts
108165
- import { resolve as resolve8, basename as basename2, join as join12, relative as relative2, isAbsolute as isAbsolute2 } from "node:path";
108166
- var DEFAULT_RENDERS_DIR = process.env.PRODUCER_RENDERS_DIR ?? resolve8(new URL(import.meta.url).pathname, "../../..", "renders");
108167
- function isPathInside(childPath, parentPath) {
108168
- const absChild = resolve8(childPath);
108169
- const absParent = resolve8(parentPath);
108285
+ import { resolve as resolve9, basename as basename2, join as join12, relative as relative2, isAbsolute as isAbsolute4 } from "node:path";
108286
+ var DEFAULT_RENDERS_DIR = process.env.PRODUCER_RENDERS_DIR ?? resolve9(new URL(import.meta.url).pathname, "../../..", "renders");
108287
+ function isPathInside2(childPath, parentPath) {
108288
+ const absChild = resolve9(childPath);
108289
+ const absParent = resolve9(parentPath);
108170
108290
  if (absChild === absParent) return true;
108171
108291
  const rel = relative2(absParent, absChild);
108172
- return rel !== "" && !rel.startsWith("..") && !isAbsolute2(rel);
108292
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute4(rel);
108173
108293
  }
108174
108294
  function toExternalAssetKey(absPath) {
108175
108295
  if (absPath.startsWith("hf-ext/")) return absPath;
@@ -108182,10 +108302,10 @@ function toExternalAssetKey(absPath) {
108182
108302
  return "hf-ext/" + normalised;
108183
108303
  }
108184
108304
  function resolveRenderPaths(projectDir, outputPath, rendersDir = DEFAULT_RENDERS_DIR) {
108185
- const absoluteProjectDir = resolve8(projectDir);
108305
+ const absoluteProjectDir = resolve9(projectDir);
108186
108306
  const projectName = basename2(absoluteProjectDir);
108187
108307
  const resolvedOutputPath = outputPath ?? join12(rendersDir, `${projectName}.mp4`);
108188
- const absoluteOutputPath = resolve8(resolvedOutputPath);
108308
+ const absoluteOutputPath = resolve9(resolvedOutputPath);
108189
108309
  return { absoluteProjectDir, absoluteOutputPath };
108190
108310
  }
108191
108311
 
@@ -108632,7 +108752,7 @@ async function resolveMediaDuration(src, mediaStart, baseDir, downloadDir, tagNa
108632
108752
  if (!existsSync14(filePath)) {
108633
108753
  return { duration: 0, resolvedPath: filePath };
108634
108754
  }
108635
- const metadata = tagName19 === "video" ? await extractVideoMetadata(filePath) : await extractAudioMetadata(filePath);
108755
+ const metadata = tagName19 === "video" ? await extractMediaMetadata(filePath) : await extractAudioMetadata(filePath);
108636
108756
  const fileDuration = metadata.durationSeconds;
108637
108757
  const effectiveDuration = fileDuration - mediaStart;
108638
108758
  const duration = effectiveDuration > 0 ? effectiveDuration : fileDuration;
@@ -108694,7 +108814,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
108694
108814
  const elEnd = elEndRaw ? parseFloat(elEndRaw) : Infinity;
108695
108815
  const absoluteStart = parentOffset + elStart;
108696
108816
  const absoluteEnd = Math.min(parentEnd, isFinite(elEnd) ? parentOffset + elEnd : Infinity);
108697
- const filePath = resolve9(projectDir, srcPath);
108817
+ const filePath = resolve10(projectDir, srcPath);
108698
108818
  if (visited.has(filePath)) {
108699
108819
  continue;
108700
108820
  }
@@ -108907,7 +109027,7 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
108907
109027
  if (!srcPath) continue;
108908
109028
  let compHtml = subCompositions.get(srcPath) || null;
108909
109029
  if (!compHtml) {
108910
- const filePath = resolve9(projectDir, srcPath);
109030
+ const filePath = resolve10(projectDir, srcPath);
108911
109031
  if (existsSync14(filePath)) {
108912
109032
  compHtml = readFileSync9(filePath, "utf-8");
108913
109033
  }
@@ -109124,7 +109244,7 @@ ${safeText}
109124
109244
  return wrappedFragment ? document2.body.innerHTML || "" : document2.toString();
109125
109245
  }
109126
109246
  function collectExternalAssets(html, projectDir) {
109127
- const absProjectDir = resolve9(projectDir);
109247
+ const absProjectDir = resolve10(projectDir);
109128
109248
  const externalAssets = /* @__PURE__ */ new Map();
109129
109249
  const CSS_URL_RE2 = /\burl\(\s*(["']?)([^)"']+)\1\s*\)/g;
109130
109250
  function processPath(rawPath) {
@@ -109132,8 +109252,8 @@ function collectExternalAssets(html, projectDir) {
109132
109252
  if (!trimmed || trimmed.startsWith("/") || trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("//") || trimmed.startsWith("data:") || trimmed.startsWith("#")) {
109133
109253
  return null;
109134
109254
  }
109135
- const absPath = resolve9(absProjectDir, trimmed);
109136
- if (isPathInside(absPath, absProjectDir)) {
109255
+ const absPath = resolve10(absProjectDir, trimmed);
109256
+ if (isPathInside2(absPath, absProjectDir)) {
109137
109257
  return null;
109138
109258
  }
109139
109259
  if (!existsSync14(absPath)) return null;
@@ -109213,9 +109333,9 @@ async function compileForRender(projectDir, htmlPath, downloadDir) {
109213
109333
  const images = dedupeElementsById([...mainImages, ...subImages]);
109214
109334
  for (const video of videos) {
109215
109335
  if (isHttpUrl(video.src)) continue;
109216
- const videoPath = resolve9(projectDir, video.src);
109336
+ const videoPath = resolve10(projectDir, video.src);
109217
109337
  const reencode = `ffmpeg -i "${video.src}" -c:v libx264 -r 30 -g 30 -keyint_min 30 -movflags +faststart -c:a copy output.mp4`;
109218
- Promise.all([analyzeKeyframeIntervals(videoPath), extractVideoMetadata(videoPath)]).then(([analysis, metadata]) => {
109338
+ Promise.all([analyzeKeyframeIntervals(videoPath), extractMediaMetadata(videoPath)]).then(([analysis, metadata]) => {
109219
109339
  if (analysis.isProblematic) {
109220
109340
  console.warn(
109221
109341
  `[Compiler] WARNING: Video "${video.id}" has sparse keyframes (max interval: ${analysis.maxIntervalSeconds}s). This causes seek failures and frame freezing. Re-encode with: ${reencode}`
@@ -109414,6 +109534,21 @@ function getMaxFrameIndex(frameDir) {
109414
109534
  frameDirMaxIndexCache.set(frameDir, max);
109415
109535
  return max;
109416
109536
  }
109537
+ function countNonZeroAlpha(rgba) {
109538
+ let n = 0;
109539
+ for (let p = 3; p < rgba.length; p += 4) {
109540
+ if (rgba[p] !== 0) n++;
109541
+ }
109542
+ return n;
109543
+ }
109544
+ function countNonZeroRgb48(buf) {
109545
+ let n = 0;
109546
+ for (let p = 0; p < buf.length; p += 6) {
109547
+ if (buf[p] !== 0 || buf[p + 1] !== 0 || buf[p + 2] !== 0 || buf[p + 3] !== 0 || buf[p + 4] !== 0 || buf[p + 5] !== 0)
109548
+ n++;
109549
+ }
109550
+ return n;
109551
+ }
109417
109552
  var RenderCancelledError = class extends Error {
109418
109553
  reason;
109419
109554
  constructor(message = "render_cancelled", reason = "aborted") {
@@ -109474,8 +109609,8 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
109474
109609
  writeFileSync4(outPath, html, "utf-8");
109475
109610
  }
109476
109611
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
109477
- const outPath = resolve10(join15(compileDir, relativePath));
109478
- if (!isPathInside(outPath, compileDir)) {
109612
+ const outPath = resolve11(join15(compileDir, relativePath));
109613
+ if (!isPathInside2(outPath, compileDir)) {
109479
109614
  console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
109480
109615
  continue;
109481
109616
  }
@@ -109621,6 +109756,165 @@ function blitHdrImageLayer(canvas, el, hdrImageBuffers, width, height, log, sour
109621
109756
  }
109622
109757
  }
109623
109758
  }
109759
+ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter, debugFrameIndex = -1) {
109760
+ const {
109761
+ log,
109762
+ domSession,
109763
+ beforeCaptureHook,
109764
+ width,
109765
+ height,
109766
+ fps,
109767
+ effectiveHdr,
109768
+ nativeHdrImageIds,
109769
+ hdrImageBuffers,
109770
+ hdrFrameDirs,
109771
+ hdrVideoStartTimes,
109772
+ imageTransfers,
109773
+ videoTransfers,
109774
+ debugDumpEnabled,
109775
+ debugDumpDir
109776
+ } = ctx;
109777
+ const filteredStacking = elementFilter ? fullStacking.filter((e) => elementFilter.has(e.id)) : fullStacking;
109778
+ const layers = groupIntoLayers(filteredStacking);
109779
+ const shouldLog = debugDumpEnabled && debugFrameIndex >= 0;
109780
+ if (shouldLog) {
109781
+ log.info("[diag] compositeToBuffer plan", {
109782
+ frame: debugFrameIndex,
109783
+ time: time.toFixed(3),
109784
+ filterSize: elementFilter?.size,
109785
+ fullStackingCount: fullStacking.length,
109786
+ filteredCount: filteredStacking.length,
109787
+ layerCount: layers.length,
109788
+ layers: layers.map(
109789
+ (l) => l.type === "hdr" ? {
109790
+ type: "hdr",
109791
+ id: l.element.id,
109792
+ z: l.element.zIndex,
109793
+ visible: l.element.visible,
109794
+ opacity: l.element.opacity,
109795
+ bounds: `${Math.round(l.element.x)},${Math.round(l.element.y)} ${Math.round(l.element.width)}x${Math.round(l.element.height)}`
109796
+ } : { type: "dom", ids: l.elementIds }
109797
+ )
109798
+ });
109799
+ }
109800
+ for (const [layerIdx, layer] of layers.entries()) {
109801
+ if (layer.type === "hdr") {
109802
+ const before2 = shouldLog ? countNonZeroRgb48(canvas) : 0;
109803
+ const isHdrImage = nativeHdrImageIds.has(layer.element.id);
109804
+ if (isHdrImage) {
109805
+ blitHdrImageLayer(
109806
+ canvas,
109807
+ layer.element,
109808
+ hdrImageBuffers,
109809
+ width,
109810
+ height,
109811
+ log,
109812
+ imageTransfers.get(layer.element.id),
109813
+ effectiveHdr.transfer
109814
+ );
109815
+ } else {
109816
+ blitHdrVideoLayer(
109817
+ canvas,
109818
+ layer.element,
109819
+ time,
109820
+ fps,
109821
+ hdrFrameDirs,
109822
+ hdrVideoStartTimes,
109823
+ width,
109824
+ height,
109825
+ log,
109826
+ videoTransfers.get(layer.element.id),
109827
+ effectiveHdr.transfer
109828
+ );
109829
+ }
109830
+ if (shouldLog) {
109831
+ const after2 = countNonZeroRgb48(canvas);
109832
+ if (isHdrImage) {
109833
+ const buf = hdrImageBuffers.get(layer.element.id);
109834
+ log.info("[diag] hdr layer blit", {
109835
+ frame: debugFrameIndex,
109836
+ layerIdx,
109837
+ id: layer.element.id,
109838
+ kind: "image",
109839
+ pixelsAdded: after2 - before2,
109840
+ totalNonZero: after2,
109841
+ bufferDecoded: !!buf,
109842
+ bufferDims: buf ? `${buf.width}x${buf.height}` : null
109843
+ });
109844
+ } else {
109845
+ const frameDir = hdrFrameDirs.get(layer.element.id);
109846
+ const startTime = hdrVideoStartTimes.get(layer.element.id) ?? 0;
109847
+ const localTime = time - startTime;
109848
+ const frameNum = Math.floor(localTime * fps) + 1;
109849
+ const expectedFrame = frameDir ? join15(frameDir, `frame_${String(frameNum).padStart(4, "0")}.png`) : null;
109850
+ log.info("[diag] hdr layer blit", {
109851
+ frame: debugFrameIndex,
109852
+ layerIdx,
109853
+ id: layer.element.id,
109854
+ kind: "video",
109855
+ pixelsAdded: after2 - before2,
109856
+ totalNonZero: after2,
109857
+ startTime,
109858
+ localTime: localTime.toFixed(3),
109859
+ hdrFrameNum: frameNum,
109860
+ expectedFrame,
109861
+ expectedFrameExists: expectedFrame ? existsSync15(expectedFrame) : false
109862
+ });
109863
+ }
109864
+ }
109865
+ } else {
109866
+ const allElementIds = fullStacking.map((e) => e.id);
109867
+ const layerIds = new Set(layer.elementIds);
109868
+ const hideIds = allElementIds.filter((id) => !layerIds.has(id));
109869
+ await domSession.page.evaluate((t) => {
109870
+ if (window.__hf && typeof window.__hf.seek === "function") window.__hf.seek(t);
109871
+ }, time);
109872
+ if (beforeCaptureHook) {
109873
+ await beforeCaptureHook(domSession.page, time);
109874
+ }
109875
+ await applyDomLayerMask(domSession.page, layer.elementIds, hideIds);
109876
+ const domPng = await captureAlphaPng(domSession.page, width, height);
109877
+ await removeDomLayerMask(domSession.page, hideIds);
109878
+ try {
109879
+ const { data: domRgba } = decodePng(domPng);
109880
+ const before2 = shouldLog ? countNonZeroRgb48(canvas) : 0;
109881
+ const alphaPixels = shouldLog ? countNonZeroAlpha(domRgba) : 0;
109882
+ blitRgba8OverRgb48le(domRgba, canvas, width, height, effectiveHdr.transfer);
109883
+ if (shouldLog && debugDumpDir) {
109884
+ const after2 = countNonZeroRgb48(canvas);
109885
+ const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
109886
+ const dumpPath = join15(debugDumpDir, dumpName);
109887
+ writeFileSync4(dumpPath, domPng);
109888
+ log.info("[diag] dom layer blit", {
109889
+ frame: debugFrameIndex,
109890
+ layerIdx,
109891
+ layerIds: layer.elementIds,
109892
+ hideCount: hideIds.length,
109893
+ pngBytes: domPng.length,
109894
+ alphaPixels,
109895
+ pixelsAdded: after2 - before2,
109896
+ totalNonZero: after2,
109897
+ dumpPath
109898
+ });
109899
+ }
109900
+ } catch (err) {
109901
+ log.warn("DOM layer decode/blit failed; skipping overlay", {
109902
+ layerIds: layer.elementIds,
109903
+ error: err instanceof Error ? err.message : String(err)
109904
+ });
109905
+ }
109906
+ }
109907
+ }
109908
+ if (shouldLog && debugDumpDir) {
109909
+ const finalNonZero = countNonZeroRgb48(canvas);
109910
+ log.info("[diag] compositeToBuffer end", {
109911
+ frame: debugFrameIndex,
109912
+ finalNonZeroPixels: finalNonZero,
109913
+ totalPixels: width * height,
109914
+ coverage: (finalNonZero / (width * height) * 100).toFixed(1) + "%"
109915
+ });
109916
+ }
109917
+ }
109624
109918
  function createRenderJob(config2) {
109625
109919
  return {
109626
109920
  id: randomUUID(),
@@ -109662,7 +109956,7 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
109662
109956
  }
109663
109957
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
109664
109958
  const moduleDir = dirname10(fileURLToPath3(import.meta.url));
109665
- const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve10(process.env.PRODUCER_RENDERS_DIR, "..") : resolve10(moduleDir, "../..");
109959
+ const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve11(process.env.PRODUCER_RENDERS_DIR, "..") : resolve11(moduleDir, "../..");
109666
109960
  const debugDir = join15(producerRoot, ".debug");
109667
109961
  const workDir = job.config.debug ? join15(debugDir, job.id) : join15(dirname10(outputPath), `work-${job.id}`);
109668
109962
  const pipelineStart = Date.now();
@@ -109965,7 +110259,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
109965
110259
  videoPath = fromCompiled;
109966
110260
  }
109967
110261
  if (!existsSync15(videoPath)) return;
109968
- const meta = await extractVideoMetadata(videoPath);
110262
+ const meta = await extractMediaMetadata(videoPath);
109969
110263
  if (isHdrColorSpace(meta.colorSpace)) {
109970
110264
  nativeHdrVideoIds.add(v.id);
109971
110265
  videoTransfers.set(v.id, detectTransfer(meta.colorSpace));
@@ -109986,7 +110280,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
109986
110280
  imgPath = fromCompiled;
109987
110281
  }
109988
110282
  if (!existsSync15(imgPath)) return null;
109989
- const meta = await extractVideoMetadata(imgPath);
110283
+ const meta = await extractMediaMetadata(imgPath);
109990
110284
  if (isHdrColorSpace(meta.colorSpace)) {
109991
110285
  nativeHdrImageIds.add(img.id);
109992
110286
  imageTransfers.set(img.id, detectTransfer(meta.colorSpace));
@@ -110098,6 +110392,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110098
110392
  format: needsAlpha ? "png" : "jpeg",
110099
110393
  quality: needsAlpha ? void 0 : job.config.quality === "draft" ? 80 : 95
110100
110394
  };
110395
+ const buildHdrCaptureOptions = () => ({
110396
+ ...captureOptions,
110397
+ skipReadinessVideoIds: Array.from(nativeHdrVideoIds)
110398
+ });
110101
110399
  const workerCount = calculateOptimalWorkers(totalFrames, job.config.workers, cfg);
110102
110400
  const FORMAT_EXT = { mp4: ".mp4", webm: ".webm", mov: ".mov" };
110103
110401
  const videoExt = FORMAT_EXT[outputFormat] ?? ".mp4";
@@ -110106,6 +110404,13 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110106
110404
  const hasHdrContent = effectiveHdr && nativeHdrIds.size > 0;
110107
110405
  const encoderHdr = hasHdrContent ? effectiveHdr : void 0;
110108
110406
  const preset = getEncoderPreset(job.config.quality, outputFormat, encoderHdr);
110407
+ if (job.config.crf != null && job.config.videoBitrate) {
110408
+ log.warn(
110409
+ `[Render] Both crf=${job.config.crf} and videoBitrate=${job.config.videoBitrate} were set. These are mutually exclusive; honoring crf and ignoring videoBitrate. Set only one to silence this warning.`
110410
+ );
110411
+ }
110412
+ const effectiveQuality = job.config.crf ?? preset.quality;
110413
+ const effectiveBitrate = job.config.crf != null ? void 0 : job.config.videoBitrate;
110109
110414
  job.framesRendered = 0;
110110
110415
  if (hasHdrContent) {
110111
110416
  log.info("[Render] HDR layered composite: z-ordered DOM + native HLG video layers");
@@ -110125,516 +110430,440 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110125
110430
  const domSession = await createCaptureSession(
110126
110431
  fileServer.url,
110127
110432
  framesDir,
110128
- { ...captureOptions, skipReadinessVideoIds: Array.from(nativeHdrVideoIds) },
110433
+ buildHdrCaptureOptions(),
110129
110434
  createVideoFrameInjector(frameLookup),
110130
110435
  cfg
110131
110436
  );
110132
- await initializeSession(domSession);
110133
- assertNotAborted();
110134
- lastBrowserConsole = domSession.browserConsoleBuffer;
110135
- await initTransparentBackground(domSession.page);
110136
- const transitionMeta = await domSession.page.evaluate(() => {
110137
- return window.__hf?.transitions ?? [];
110138
- });
110139
- const sceneElements = await domSession.page.evaluate(() => {
110140
- const scenes = document.querySelectorAll(".scene");
110141
- const map2 = {};
110142
- for (const scene of scenes) {
110143
- const els = scene.querySelectorAll("[data-start]");
110144
- map2[scene.id] = Array.from(els).map((e) => e.id);
110145
- }
110146
- return map2;
110147
- });
110148
- const transitionRanges = transitionMeta.map((t) => ({
110149
- ...t,
110150
- startFrame: Math.floor(t.time * job.config.fps),
110151
- endFrame: Math.ceil((t.time + t.duration) * job.config.fps)
110152
- }));
110153
- if (transitionRanges.length > 0) {
110154
- log.info("[Render] Detected shader transitions for HDR compositing", {
110155
- count: transitionRanges.length,
110156
- transitions: transitionRanges.map((t) => ({
110157
- shader: t.shader,
110158
- from: t.fromScene,
110159
- to: t.toScene,
110160
- frames: `${t.startFrame}-${t.endFrame}`
110161
- }))
110162
- });
110163
- }
110164
- const hdrEncoder = await spawnStreamingEncoder(
110165
- videoOnlyPath,
110166
- {
110167
- fps: job.config.fps,
110168
- width,
110169
- height,
110170
- codec: preset.codec,
110171
- preset: preset.preset,
110172
- quality: preset.quality,
110173
- pixelFormat: preset.pixelFormat,
110174
- hdr: preset.hdr,
110175
- rawInputFormat: "rgb48le"
110176
- },
110177
- abortSignal,
110178
- { ffmpegStreamingTimeout: 36e5 }
110179
- );
110180
- assertNotAborted();
110181
- const hdrExtractionDims = /* @__PURE__ */ new Map();
110182
- const hdrImageFitInfo = /* @__PURE__ */ new Map();
110183
- const hdrVideoStartTimes = /* @__PURE__ */ new Map();
110184
- for (const v of composition.videos) {
110185
- if (hdrVideoIds.includes(v.id)) {
110186
- hdrVideoStartTimes.set(v.id, v.start);
110187
- }
110188
- }
110189
- const hdrImageStartTimes = /* @__PURE__ */ new Map();
110190
- for (const img of composition.images) {
110191
- if (nativeHdrImageIds.has(img.id)) {
110192
- hdrImageStartTimes.set(img.id, img.start);
110193
- }
110194
- }
110195
- const uniqueStartTimes = [
110196
- .../* @__PURE__ */ new Set([...hdrVideoStartTimes.values(), ...hdrImageStartTimes.values()])
110197
- ].sort((a, b) => a - b);
110198
- for (const seekTime of uniqueStartTimes) {
110199
- await domSession.page.evaluate((t) => {
110200
- if (window.__hf && typeof window.__hf.seek === "function") window.__hf.seek(t);
110201
- }, seekTime);
110202
- if (domSession.onBeforeCapture) {
110203
- await domSession.onBeforeCapture(domSession.page, seekTime);
110204
- }
110205
- const stacking = await queryElementStacking(domSession.page, nativeHdrIds);
110206
- for (const el of stacking) {
110207
- if (el.isHdr && el.layoutWidth > 0 && el.layoutHeight > 0 && !hdrExtractionDims.has(el.id)) {
110208
- hdrExtractionDims.set(el.id, { width: el.layoutWidth, height: el.layoutHeight });
110209
- }
110210
- if (el.isHdr && nativeHdrImageIds.has(el.id) && !hdrImageFitInfo.has(el.id)) {
110211
- hdrImageFitInfo.set(el.id, {
110212
- fit: el.objectFit,
110213
- position: el.objectPosition
110214
- });
110215
- }
110216
- }
110217
- }
110437
+ let hdrEncoder = null;
110438
+ let hdrEncoderClosed = false;
110439
+ let domSessionClosed = false;
110218
110440
  const hdrFrameDirs = /* @__PURE__ */ new Map();
110219
- for (const [videoId, srcPath] of hdrVideoSrcPaths) {
110220
- const video = composition.videos.find((v) => v.id === videoId);
110221
- if (!video) continue;
110222
- const frameDir = join15(framesDir, `hdr_${videoId}`);
110223
- mkdirSync10(frameDir, { recursive: true });
110224
- const duration = video.end - video.start;
110225
- const dims = hdrExtractionDims.get(videoId) ?? { width, height };
110226
- const ffmpegArgs = [
110227
- "-ss",
110228
- String(video.mediaStart),
110229
- "-i",
110230
- srcPath,
110231
- "-t",
110232
- String(duration),
110233
- "-r",
110234
- String(job.config.fps),
110235
- "-vf",
110236
- `scale=${dims.width}:${dims.height}:force_original_aspect_ratio=increase,crop=${dims.width}:${dims.height}`,
110237
- "-pix_fmt",
110238
- "rgb48le",
110239
- "-c:v",
110240
- "png",
110241
- "-y",
110242
- join15(frameDir, "frame_%04d.png")
110243
- ];
110244
- const result = await runFfmpeg(ffmpegArgs, { signal: abortSignal });
110245
- if (!result.success) {
110246
- hdrDiagnostics.videoExtractionFailures += 1;
110247
- log.error("HDR frame pre-extraction failed; aborting render", {
110248
- videoId,
110249
- srcPath,
110250
- stderr: result.stderr.slice(-400)
110251
- });
110252
- throw new Error(
110253
- `HDR frame extraction failed for video "${videoId}". Aborting render to avoid shipping black HDR layers.`
110254
- );
110255
- }
110256
- hdrFrameDirs.set(videoId, frameDir);
110257
- }
110258
- const hdrImageBuffers = /* @__PURE__ */ new Map();
110259
- for (const [imageId, srcPath] of hdrImageSrcPaths) {
110260
- try {
110261
- const decoded = decodePngToRgb48le(readFileSync10(srcPath));
110262
- const layout2 = hdrExtractionDims.get(imageId);
110263
- const fitInfo = hdrImageFitInfo.get(imageId);
110264
- if (layout2 && (layout2.width !== decoded.width || layout2.height !== decoded.height)) {
110265
- const fit = normalizeObjectFit(fitInfo?.fit);
110266
- const resampled = resampleRgb48leObjectFit(
110267
- decoded.data,
110268
- decoded.width,
110269
- decoded.height,
110270
- layout2.width,
110271
- layout2.height,
110272
- fit,
110273
- fitInfo?.position
110274
- );
110275
- hdrImageBuffers.set(imageId, {
110276
- data: resampled,
110277
- width: layout2.width,
110278
- height: layout2.height
110279
- });
110280
- } else {
110281
- hdrImageBuffers.set(imageId, {
110282
- data: Buffer.from(decoded.data),
110283
- width: decoded.width,
110284
- height: decoded.height
110285
- });
110441
+ try {
110442
+ await initializeSession(domSession);
110443
+ assertNotAborted();
110444
+ lastBrowserConsole = domSession.browserConsoleBuffer;
110445
+ await initTransparentBackground(domSession.page);
110446
+ const transitionMeta = await domSession.page.evaluate(() => {
110447
+ return window.__hf?.transitions ?? [];
110448
+ });
110449
+ const sceneElements = await domSession.page.evaluate(() => {
110450
+ const scenes = document.querySelectorAll(".scene");
110451
+ const map2 = {};
110452
+ for (const scene of scenes) {
110453
+ const els = scene.querySelectorAll("[data-start]");
110454
+ map2[scene.id] = Array.from(els).map((e) => e.id);
110286
110455
  }
110287
- } catch (err) {
110288
- hdrDiagnostics.imageDecodeFailures += 1;
110289
- log.error("HDR image decode failed; aborting render", {
110290
- imageId,
110291
- srcPath,
110292
- error: err instanceof Error ? err.message : String(err)
110456
+ return map2;
110457
+ });
110458
+ const transitionRanges = transitionMeta.map((t) => ({
110459
+ ...t,
110460
+ startFrame: Math.floor(t.time * job.config.fps),
110461
+ endFrame: Math.ceil((t.time + t.duration) * job.config.fps)
110462
+ }));
110463
+ if (transitionRanges.length > 0) {
110464
+ log.info("[Render] Detected shader transitions for HDR compositing", {
110465
+ count: transitionRanges.length,
110466
+ transitions: transitionRanges.map((t) => ({
110467
+ shader: t.shader,
110468
+ from: t.fromScene,
110469
+ to: t.toScene,
110470
+ frames: `${t.startFrame}-${t.endFrame}`
110471
+ }))
110293
110472
  });
110294
- throw new Error(
110295
- `HDR image decode failed for image "${imageId}". Aborting render to avoid shipping missing HDR image layers.`
110296
- );
110297
110473
  }
110298
- }
110299
- assertNotAborted();
110300
- try {
110301
- let countNonZeroAlpha2 = function(rgba) {
110302
- let n = 0;
110303
- for (let p = 3; p < rgba.length; p += 4) {
110304
- if (rgba[p] !== 0) n++;
110474
+ hdrEncoder = await spawnStreamingEncoder(
110475
+ videoOnlyPath,
110476
+ {
110477
+ fps: job.config.fps,
110478
+ width,
110479
+ height,
110480
+ codec: preset.codec,
110481
+ preset: preset.preset,
110482
+ quality: effectiveQuality,
110483
+ bitrate: effectiveBitrate,
110484
+ pixelFormat: preset.pixelFormat,
110485
+ hdr: preset.hdr,
110486
+ rawInputFormat: "rgb48le"
110487
+ },
110488
+ abortSignal,
110489
+ { ffmpegStreamingTimeout: 36e5 }
110490
+ );
110491
+ assertNotAborted();
110492
+ const hdrExtractionDims = /* @__PURE__ */ new Map();
110493
+ const hdrImageFitInfo = /* @__PURE__ */ new Map();
110494
+ const hdrVideoStartTimes = /* @__PURE__ */ new Map();
110495
+ for (const v of composition.videos) {
110496
+ if (hdrVideoIds.includes(v.id)) {
110497
+ hdrVideoStartTimes.set(v.id, v.start);
110305
110498
  }
110306
- return n;
110307
- }, countNonZeroRgb482 = function(buf) {
110308
- let n = 0;
110309
- for (let p = 0; p < buf.length; p += 6) {
110310
- if (buf[p] !== 0 || buf[p + 1] !== 0 || buf[p + 2] !== 0) n++;
110499
+ }
110500
+ const hdrImageStartTimes = /* @__PURE__ */ new Map();
110501
+ for (const img of composition.images) {
110502
+ if (nativeHdrImageIds.has(img.id)) {
110503
+ hdrImageStartTimes.set(img.id, img.start);
110311
110504
  }
110312
- return n;
110313
- };
110314
- var countNonZeroAlpha = countNonZeroAlpha2, countNonZeroRgb48 = countNonZeroRgb482;
110315
- const beforeCaptureHook = domSession.onBeforeCapture;
110316
- const cleanedUpVideos = /* @__PURE__ */ new Set();
110317
- const hdrVideoEndTimes = /* @__PURE__ */ new Map();
110318
- for (const v of composition.videos) {
110319
- if (hdrFrameDirs.has(v.id)) {
110320
- hdrVideoEndTimes.set(v.id, v.end);
110321
- }
110322
- }
110323
- const debugDumpEnabled = process.env.KEEP_TEMP === "1";
110324
- const debugDumpDir = debugDumpEnabled ? join15(framesDir, "debug-composite") : null;
110325
- if (debugDumpDir && !existsSync15(debugDumpDir)) {
110326
- mkdirSync10(debugDumpDir, { recursive: true });
110327
- }
110328
- async function compositeToBuffer(canvas, time, fullStacking, elementFilter, debugFrameIndex = -1) {
110329
- const filteredStacking = elementFilter ? fullStacking.filter((e) => elementFilter.has(e.id)) : fullStacking;
110330
- const layers = groupIntoLayers(filteredStacking);
110331
- const shouldLog = debugDumpEnabled && debugFrameIndex >= 0;
110332
- if (shouldLog) {
110333
- log.info("[diag] compositeToBuffer plan", {
110334
- frame: debugFrameIndex,
110335
- time: time.toFixed(3),
110336
- filterSize: elementFilter?.size,
110337
- fullStackingCount: fullStacking.length,
110338
- filteredCount: filteredStacking.length,
110339
- layerCount: layers.length,
110340
- layers: layers.map(
110341
- (l) => l.type === "hdr" ? {
110342
- type: "hdr",
110343
- id: l.element.id,
110344
- z: l.element.zIndex,
110345
- visible: l.element.visible,
110346
- opacity: l.element.opacity,
110347
- bounds: `${Math.round(l.element.x)},${Math.round(l.element.y)} ${Math.round(l.element.width)}x${Math.round(l.element.height)}`
110348
- } : { type: "dom", ids: l.elementIds }
110349
- )
110350
- });
110505
+ }
110506
+ const uniqueStartTimes = [
110507
+ .../* @__PURE__ */ new Set([...hdrVideoStartTimes.values(), ...hdrImageStartTimes.values()])
110508
+ ].sort((a, b) => a - b);
110509
+ for (const seekTime of uniqueStartTimes) {
110510
+ await domSession.page.evaluate((t) => {
110511
+ if (window.__hf && typeof window.__hf.seek === "function") window.__hf.seek(t);
110512
+ }, seekTime);
110513
+ if (domSession.onBeforeCapture) {
110514
+ await domSession.onBeforeCapture(domSession.page, seekTime);
110515
+ }
110516
+ const stacking = await queryElementStacking(domSession.page, nativeHdrIds);
110517
+ for (const el of stacking) {
110518
+ if (el.isHdr && el.layoutWidth > 0 && el.layoutHeight > 0 && !hdrExtractionDims.has(el.id)) {
110519
+ hdrExtractionDims.set(el.id, { width: el.layoutWidth, height: el.layoutHeight });
110520
+ }
110521
+ if (el.isHdr && nativeHdrImageIds.has(el.id) && !hdrImageFitInfo.has(el.id)) {
110522
+ hdrImageFitInfo.set(el.id, {
110523
+ fit: el.objectFit,
110524
+ position: el.objectPosition
110525
+ });
110526
+ }
110351
110527
  }
110352
- for (const [layerIdx, layer] of layers.entries()) {
110353
- if (layer.type === "hdr") {
110354
- const before2 = shouldLog ? countNonZeroRgb482(canvas) : 0;
110355
- const isHdrImage = nativeHdrImageIds.has(layer.element.id);
110356
- if (isHdrImage) {
110357
- blitHdrImageLayer(
110358
- canvas,
110359
- layer.element,
110360
- hdrImageBuffers,
110361
- width,
110362
- height,
110363
- log,
110364
- imageTransfers.get(layer.element.id),
110365
- effectiveHdr?.transfer
110366
- );
110367
- } else {
110368
- blitHdrVideoLayer(
110369
- canvas,
110370
- layer.element,
110371
- time,
110372
- job.config.fps,
110373
- hdrFrameDirs,
110374
- hdrVideoStartTimes,
110375
- width,
110376
- height,
110377
- log,
110378
- videoTransfers.get(layer.element.id),
110379
- effectiveHdr?.transfer
110380
- );
110381
- }
110382
- if (shouldLog) {
110383
- const after2 = countNonZeroRgb482(canvas);
110384
- if (isHdrImage) {
110385
- const buf = hdrImageBuffers.get(layer.element.id);
110386
- log.info("[diag] hdr layer blit", {
110387
- frame: debugFrameIndex,
110388
- layerIdx,
110389
- id: layer.element.id,
110390
- kind: "image",
110391
- pixelsAdded: after2 - before2,
110392
- totalNonZero: after2,
110393
- bufferDecoded: !!buf,
110394
- bufferDims: buf ? `${buf.width}x${buf.height}` : null
110395
- });
110396
- } else {
110397
- const frameDir = hdrFrameDirs.get(layer.element.id);
110398
- const startTime = hdrVideoStartTimes.get(layer.element.id) ?? 0;
110399
- const localTime = time - startTime;
110400
- const frameNum = Math.floor(localTime * job.config.fps) + 1;
110401
- const expectedFrame = frameDir ? join15(frameDir, `frame_${String(frameNum).padStart(4, "0")}.png`) : null;
110402
- log.info("[diag] hdr layer blit", {
110403
- frame: debugFrameIndex,
110404
- layerIdx,
110405
- id: layer.element.id,
110406
- kind: "video",
110407
- pixelsAdded: after2 - before2,
110408
- totalNonZero: after2,
110409
- startTime,
110410
- localTime: localTime.toFixed(3),
110411
- hdrFrameNum: frameNum,
110412
- expectedFrame,
110413
- expectedFrameExists: expectedFrame ? existsSync15(expectedFrame) : false
110414
- });
110415
- }
110416
- }
110417
- } else {
110418
- const allElementIds = fullStacking.map((e) => e.id);
110419
- const layerIds = new Set(layer.elementIds);
110420
- const hideIds = allElementIds.filter((id) => !layerIds.has(id));
110421
- await domSession.page.evaluate((t) => {
110422
- if (window.__hf && typeof window.__hf.seek === "function") window.__hf.seek(t);
110423
- }, time);
110424
- if (beforeCaptureHook) {
110425
- await beforeCaptureHook(domSession.page, time);
110426
- }
110427
- await applyDomLayerMask(domSession.page, layer.elementIds, hideIds);
110428
- const domPng = await captureAlphaPng(domSession.page, width, height);
110429
- await removeDomLayerMask(domSession.page, hideIds);
110430
- try {
110431
- const { data: domRgba } = decodePng(domPng);
110432
- if (!effectiveHdr) {
110433
- throw new Error(
110434
- "Invariant violation: effectiveHdr is undefined inside HDR layer branch"
110435
- );
110436
- }
110437
- const before2 = shouldLog ? countNonZeroRgb482(canvas) : 0;
110438
- const alphaPixels = shouldLog ? countNonZeroAlpha2(domRgba) : 0;
110439
- blitRgba8OverRgb48le(domRgba, canvas, width, height, effectiveHdr.transfer);
110440
- if (shouldLog && debugDumpDir) {
110441
- const after2 = countNonZeroRgb482(canvas);
110442
- const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
110443
- const dumpPath = join15(debugDumpDir, dumpName);
110444
- writeFileSync4(dumpPath, domPng);
110445
- log.info("[diag] dom layer blit", {
110446
- frame: debugFrameIndex,
110447
- layerIdx,
110448
- layerIds: layer.elementIds,
110449
- hideCount: hideIds.length,
110450
- pngBytes: domPng.length,
110451
- alphaPixels,
110452
- pixelsAdded: after2 - before2,
110453
- totalNonZero: after2,
110454
- dumpPath
110455
- });
110456
- }
110457
- } catch (err) {
110458
- log.warn("DOM layer decode/blit failed; skipping overlay", {
110459
- layerIds: layer.elementIds,
110460
- error: err instanceof Error ? err.message : String(err)
110461
- });
110528
+ }
110529
+ for (const [imageId, startTime] of hdrImageStartTimes) {
110530
+ if (hdrExtractionDims.has(imageId)) continue;
110531
+ const img = composition.images.find((i) => i.id === imageId);
110532
+ if (!img) continue;
110533
+ const duration = img.end - img.start;
110534
+ const retryTime = startTime + Math.min(0.5, duration * 0.1);
110535
+ await domSession.page.evaluate((t) => {
110536
+ if (window.__hf && typeof window.__hf.seek === "function") window.__hf.seek(t);
110537
+ }, retryTime);
110538
+ if (domSession.onBeforeCapture) {
110539
+ await domSession.onBeforeCapture(domSession.page, retryTime);
110540
+ }
110541
+ const retryStacking = await queryElementStacking(domSession.page, nativeHdrIds);
110542
+ for (const el of retryStacking) {
110543
+ if (el.id === imageId && el.isHdr && el.layoutWidth > 0 && el.layoutHeight > 0) {
110544
+ hdrExtractionDims.set(el.id, { width: el.layoutWidth, height: el.layoutHeight });
110545
+ if (!hdrImageFitInfo.has(el.id)) {
110546
+ hdrImageFitInfo.set(el.id, { fit: el.objectFit, position: el.objectPosition });
110462
110547
  }
110548
+ break;
110463
110549
  }
110464
110550
  }
110465
- if (shouldLog && debugDumpDir) {
110466
- const finalNonZero = countNonZeroRgb482(canvas);
110467
- log.info("[diag] compositeToBuffer end", {
110468
- frame: debugFrameIndex,
110469
- finalNonZeroPixels: finalNonZero,
110470
- totalPixels: width * height,
110471
- coverage: (finalNonZero / (width * height) * 100).toFixed(1) + "%"
110551
+ }
110552
+ for (const [videoId, srcPath] of hdrVideoSrcPaths) {
110553
+ const video = composition.videos.find((v) => v.id === videoId);
110554
+ if (!video) continue;
110555
+ const frameDir = join15(framesDir, `hdr_${videoId}`);
110556
+ mkdirSync10(frameDir, { recursive: true });
110557
+ const duration = video.end - video.start;
110558
+ const dims = hdrExtractionDims.get(videoId) ?? { width, height };
110559
+ const ffmpegArgs = [
110560
+ "-ss",
110561
+ String(video.mediaStart),
110562
+ "-i",
110563
+ srcPath,
110564
+ "-t",
110565
+ String(duration),
110566
+ "-r",
110567
+ String(job.config.fps),
110568
+ "-vf",
110569
+ `scale=${dims.width}:${dims.height}:force_original_aspect_ratio=increase,crop=${dims.width}:${dims.height}`,
110570
+ "-pix_fmt",
110571
+ "rgb48le",
110572
+ "-c:v",
110573
+ "png",
110574
+ "-y",
110575
+ join15(frameDir, "frame_%04d.png")
110576
+ ];
110577
+ const result = await runFfmpeg(ffmpegArgs, { signal: abortSignal });
110578
+ if (!result.success) {
110579
+ hdrDiagnostics.videoExtractionFailures += 1;
110580
+ log.error("HDR frame pre-extraction failed; aborting render", {
110581
+ videoId,
110582
+ srcPath,
110583
+ stderr: result.stderr.slice(-400)
110472
110584
  });
110585
+ throw new Error(
110586
+ `HDR frame extraction failed for video "${videoId}". Aborting render to avoid shipping black HDR layers.`
110587
+ );
110473
110588
  }
110589
+ hdrFrameDirs.set(videoId, frameDir);
110474
110590
  }
110475
- const bufSize = width * height * 6;
110476
- const hasTransitions = transitionRanges.length > 0;
110477
- const transBufferA = hasTransitions ? Buffer.alloc(bufSize) : null;
110478
- const transBufferB = hasTransitions ? Buffer.alloc(bufSize) : null;
110479
- const transOutput = hasTransitions ? Buffer.alloc(bufSize) : null;
110480
- const normalCanvas = Buffer.alloc(bufSize);
110481
- for (let i = 0; i < totalFrames; i++) {
110482
- assertNotAborted();
110483
- const time = i / job.config.fps;
110484
- await domSession.page.evaluate((t) => {
110485
- if (window.__hf && typeof window.__hf.seek === "function") window.__hf.seek(t);
110486
- }, time);
110487
- if (beforeCaptureHook) {
110488
- await beforeCaptureHook(domSession.page, time);
110489
- }
110490
- const stackingInfo = await queryElementStacking(domSession.page, nativeHdrIds);
110491
- const activeTransition = transitionRanges.find(
110492
- (t) => i >= t.startFrame && i <= t.endFrame
110493
- );
110494
- if (i % 30 === 0) {
110495
- const hdrEl = stackingInfo.find((e) => e.isHdr);
110496
- log.debug("[Render] HDR layer composite frame", {
110497
- frame: i,
110498
- time: time.toFixed(2),
110499
- hdrElement: hdrEl ? { z: hdrEl.zIndex, visible: hdrEl.visible, width: hdrEl.width } : null,
110500
- stackingCount: stackingInfo.length,
110501
- activeTransition: activeTransition?.shader
110591
+ const hdrImageBuffers = /* @__PURE__ */ new Map();
110592
+ for (const [imageId, srcPath] of hdrImageSrcPaths) {
110593
+ try {
110594
+ const decoded = decodePngToRgb48le(readFileSync10(srcPath));
110595
+ const layout2 = hdrExtractionDims.get(imageId);
110596
+ const fitInfo = hdrImageFitInfo.get(imageId);
110597
+ if (layout2 && (layout2.width !== decoded.width || layout2.height !== decoded.height)) {
110598
+ const fit = normalizeObjectFit(fitInfo?.fit);
110599
+ const resampled = resampleRgb48leObjectFit(
110600
+ decoded.data,
110601
+ decoded.width,
110602
+ decoded.height,
110603
+ layout2.width,
110604
+ layout2.height,
110605
+ fit,
110606
+ fitInfo?.position
110607
+ );
110608
+ hdrImageBuffers.set(imageId, {
110609
+ data: resampled,
110610
+ width: layout2.width,
110611
+ height: layout2.height
110612
+ });
110613
+ } else {
110614
+ hdrImageBuffers.set(imageId, {
110615
+ data: Buffer.from(decoded.data),
110616
+ width: decoded.width,
110617
+ height: decoded.height
110618
+ });
110619
+ }
110620
+ } catch (err) {
110621
+ hdrDiagnostics.imageDecodeFailures += 1;
110622
+ log.error("HDR image decode failed; aborting render", {
110623
+ imageId,
110624
+ srcPath,
110625
+ error: err instanceof Error ? err.message : String(err)
110502
110626
  });
110627
+ throw new Error(
110628
+ `HDR image decode failed for image "${imageId}". Aborting render to avoid shipping missing HDR image layers.`
110629
+ );
110503
110630
  }
110504
- if (activeTransition && transBufferA && transBufferB && transOutput) {
110505
- const progress = activeTransition.endFrame === activeTransition.startFrame ? 1 : (i - activeTransition.startFrame) / (activeTransition.endFrame - activeTransition.startFrame);
110506
- const sceneAIds = new Set(sceneElements[activeTransition.fromScene] ?? []);
110507
- const sceneBIds = new Set(sceneElements[activeTransition.toScene] ?? []);
110508
- transBufferA.fill(0);
110509
- transBufferB.fill(0);
110510
- for (const [sceneBuf, sceneIds] of [
110511
- [transBufferA, sceneAIds],
110512
- [transBufferB, sceneBIds]
110513
- ]) {
110514
- await domSession.page.evaluate((t) => {
110515
- if (window.__hf && typeof window.__hf.seek === "function") window.__hf.seek(t);
110516
- }, time);
110517
- if (beforeCaptureHook) {
110518
- await beforeCaptureHook(domSession.page, time);
110519
- }
110520
- for (const el of stackingInfo) {
110521
- if (!el.isHdr || !sceneIds.has(el.id)) continue;
110522
- if (nativeHdrImageIds.has(el.id)) {
110523
- blitHdrImageLayer(
110524
- sceneBuf,
110525
- el,
110526
- hdrImageBuffers,
110527
- width,
110528
- height,
110529
- log,
110530
- imageTransfers.get(el.id),
110531
- effectiveHdr?.transfer
110532
- );
110533
- } else {
110534
- blitHdrVideoLayer(
110631
+ }
110632
+ assertNotAborted();
110633
+ try {
110634
+ const beforeCaptureHook = domSession.onBeforeCapture;
110635
+ const cleanedUpVideos = /* @__PURE__ */ new Set();
110636
+ const hdrVideoEndTimes = /* @__PURE__ */ new Map();
110637
+ for (const v of composition.videos) {
110638
+ if (hdrFrameDirs.has(v.id)) {
110639
+ hdrVideoEndTimes.set(v.id, v.end);
110640
+ }
110641
+ }
110642
+ const debugDumpEnabled = process.env.KEEP_TEMP === "1";
110643
+ const debugDumpDir = debugDumpEnabled ? join15(framesDir, "debug-composite") : null;
110644
+ if (debugDumpDir && !existsSync15(debugDumpDir)) {
110645
+ mkdirSync10(debugDumpDir, { recursive: true });
110646
+ }
110647
+ if (!effectiveHdr) {
110648
+ throw new Error(
110649
+ "Internal: HDR render path entered without effectiveHdr \u2014 this is a bug."
110650
+ );
110651
+ }
110652
+ const hdrCompositeCtx = {
110653
+ log,
110654
+ domSession,
110655
+ beforeCaptureHook,
110656
+ width,
110657
+ height,
110658
+ fps: job.config.fps,
110659
+ effectiveHdr,
110660
+ nativeHdrImageIds,
110661
+ hdrImageBuffers,
110662
+ hdrFrameDirs,
110663
+ hdrVideoStartTimes,
110664
+ imageTransfers,
110665
+ videoTransfers,
110666
+ debugDumpEnabled,
110667
+ debugDumpDir
110668
+ };
110669
+ const bufSize = width * height * 6;
110670
+ const hasTransitions = transitionRanges.length > 0;
110671
+ const transBufferA = hasTransitions ? Buffer.alloc(bufSize) : null;
110672
+ const transBufferB = hasTransitions ? Buffer.alloc(bufSize) : null;
110673
+ const transOutput = hasTransitions ? Buffer.alloc(bufSize) : null;
110674
+ const normalCanvas = Buffer.alloc(bufSize);
110675
+ for (let i = 0; i < totalFrames; i++) {
110676
+ assertNotAborted();
110677
+ const time = i / job.config.fps;
110678
+ await domSession.page.evaluate((t) => {
110679
+ if (window.__hf && typeof window.__hf.seek === "function") window.__hf.seek(t);
110680
+ }, time);
110681
+ if (beforeCaptureHook) {
110682
+ await beforeCaptureHook(domSession.page, time);
110683
+ }
110684
+ const stackingInfo = await queryElementStacking(domSession.page, nativeHdrIds);
110685
+ const activeTransition = transitionRanges.find(
110686
+ (t) => i >= t.startFrame && i <= t.endFrame
110687
+ );
110688
+ if (i % 30 === 0) {
110689
+ const hdrEl = stackingInfo.find((e) => e.isHdr);
110690
+ log.debug("[Render] HDR layer composite frame", {
110691
+ frame: i,
110692
+ time: time.toFixed(2),
110693
+ hdrElement: hdrEl ? { z: hdrEl.zIndex, visible: hdrEl.visible, width: hdrEl.width } : null,
110694
+ stackingCount: stackingInfo.length,
110695
+ activeTransition: activeTransition?.shader
110696
+ });
110697
+ }
110698
+ if (activeTransition && transBufferA && transBufferB && transOutput) {
110699
+ const progress = activeTransition.endFrame === activeTransition.startFrame ? 1 : (i - activeTransition.startFrame) / (activeTransition.endFrame - activeTransition.startFrame);
110700
+ const sceneAIds = new Set(sceneElements[activeTransition.fromScene] ?? []);
110701
+ const sceneBIds = new Set(sceneElements[activeTransition.toScene] ?? []);
110702
+ transBufferA.fill(0);
110703
+ transBufferB.fill(0);
110704
+ for (const [sceneBuf, sceneIds] of [
110705
+ [transBufferA, sceneAIds],
110706
+ [transBufferB, sceneBIds]
110707
+ ]) {
110708
+ assertNotAborted();
110709
+ await domSession.page.evaluate((t) => {
110710
+ if (window.__hf && typeof window.__hf.seek === "function") window.__hf.seek(t);
110711
+ }, time);
110712
+ if (beforeCaptureHook) {
110713
+ await beforeCaptureHook(domSession.page, time);
110714
+ }
110715
+ for (const el of stackingInfo) {
110716
+ if (!el.isHdr || !sceneIds.has(el.id)) continue;
110717
+ if (nativeHdrImageIds.has(el.id)) {
110718
+ blitHdrImageLayer(
110719
+ sceneBuf,
110720
+ el,
110721
+ hdrImageBuffers,
110722
+ width,
110723
+ height,
110724
+ log,
110725
+ imageTransfers.get(el.id),
110726
+ effectiveHdr?.transfer
110727
+ );
110728
+ } else {
110729
+ blitHdrVideoLayer(
110730
+ sceneBuf,
110731
+ el,
110732
+ time,
110733
+ job.config.fps,
110734
+ hdrFrameDirs,
110735
+ hdrVideoStartTimes,
110736
+ width,
110737
+ height,
110738
+ log,
110739
+ videoTransfers.get(el.id),
110740
+ effectiveHdr?.transfer
110741
+ );
110742
+ }
110743
+ }
110744
+ const showIds = Array.from(sceneIds);
110745
+ const hideIds = stackingInfo.map((e) => e.id).filter((id) => !sceneIds.has(id) || nativeHdrIds.has(id));
110746
+ await applyDomLayerMask(domSession.page, showIds, hideIds);
110747
+ const domPng = await captureAlphaPng(domSession.page, width, height);
110748
+ await removeDomLayerMask(domSession.page, hideIds);
110749
+ try {
110750
+ const { data: domRgba } = decodePng(domPng);
110751
+ if (!effectiveHdr) {
110752
+ throw new Error(
110753
+ "Invariant violation: effectiveHdr is undefined inside hasHdrVideo branch"
110754
+ );
110755
+ }
110756
+ blitRgba8OverRgb48le(
110757
+ domRgba,
110535
110758
  sceneBuf,
110536
- el,
110537
- time,
110538
- job.config.fps,
110539
- hdrFrameDirs,
110540
- hdrVideoStartTimes,
110541
110759
  width,
110542
110760
  height,
110543
- log,
110544
- videoTransfers.get(el.id),
110545
- effectiveHdr?.transfer
110761
+ effectiveHdr.transfer
110546
110762
  );
110763
+ } catch (err) {
110764
+ log.warn("DOM layer decode/blit failed; skipping overlay for transition scene", {
110765
+ frameIndex: i,
110766
+ sceneIds: Array.from(sceneIds),
110767
+ error: err instanceof Error ? err.message : String(err)
110768
+ });
110547
110769
  }
110548
110770
  }
110549
- const showIds = Array.from(sceneIds);
110550
- const hideIds = stackingInfo.map((e) => e.id).filter((id) => !sceneIds.has(id) || nativeHdrIds.has(id));
110551
- await applyDomLayerMask(domSession.page, showIds, hideIds);
110552
- const domPng = await captureAlphaPng(domSession.page, width, height);
110553
- await removeDomLayerMask(domSession.page, hideIds);
110554
- try {
110555
- const { data: domRgba } = decodePng(domPng);
110556
- if (!effectiveHdr) {
110557
- throw new Error(
110558
- "Invariant violation: effectiveHdr is undefined inside hasHdrVideo branch"
110559
- );
110560
- }
110561
- blitRgba8OverRgb48le(
110562
- domRgba,
110563
- sceneBuf,
110564
- width,
110565
- height,
110566
- effectiveHdr.transfer
110771
+ const transitionFn = TRANSITIONS[activeTransition.shader] ?? crossfade;
110772
+ transitionFn(transBufferA, transBufferB, transOutput, width, height, progress);
110773
+ hdrEncoder.writeFrame(transOutput);
110774
+ } else {
110775
+ normalCanvas.fill(0);
110776
+ await compositeHdrFrame(
110777
+ hdrCompositeCtx,
110778
+ normalCanvas,
110779
+ time,
110780
+ stackingInfo,
110781
+ void 0,
110782
+ i
110783
+ );
110784
+ if (debugDumpEnabled && debugDumpDir && i % 30 === 0) {
110785
+ const previewPath = join15(
110786
+ debugDumpDir,
110787
+ `frame_${String(i).padStart(4, "0")}_final_rgb48le.bin`
110567
110788
  );
110568
- } catch (err) {
110569
- log.warn("DOM layer decode/blit failed; skipping overlay for transition scene", {
110570
- frameIndex: i,
110571
- sceneIds: Array.from(sceneIds),
110572
- error: err instanceof Error ? err.message : String(err)
110573
- });
110789
+ writeFileSync4(previewPath, normalCanvas);
110574
110790
  }
110575
- }
110576
- const transitionFn = TRANSITIONS[activeTransition.shader] ?? crossfade;
110577
- transitionFn(transBufferA, transBufferB, transOutput, width, height, progress);
110578
- hdrEncoder.writeFrame(transOutput);
110579
- } else {
110580
- normalCanvas.fill(0);
110581
- await compositeToBuffer(normalCanvas, time, stackingInfo, void 0, i);
110582
- if (debugDumpEnabled && debugDumpDir && i % 30 === 0) {
110583
- const previewPath = join15(
110584
- debugDumpDir,
110585
- `frame_${String(i).padStart(4, "0")}_final_rgb48le.bin`
110586
- );
110587
- writeFileSync4(previewPath, normalCanvas);
110588
- }
110589
- hdrEncoder.writeFrame(normalCanvas);
110590
- }
110591
- if (process.env.KEEP_TEMP !== "1") {
110592
- for (const [videoId, endTime] of hdrVideoEndTimes) {
110593
- if (time > endTime && !cleanedUpVideos.has(videoId)) {
110594
- const stillNeeded = activeTransition && (sceneElements[activeTransition.fromScene]?.includes(videoId) || sceneElements[activeTransition.toScene]?.includes(videoId));
110595
- if (!stillNeeded) {
110596
- const frameDir = hdrFrameDirs.get(videoId);
110597
- if (frameDir) {
110598
- try {
110599
- rmSync3(frameDir, { recursive: true, force: true });
110600
- } catch (err) {
110601
- log.warn("Failed to clean up HDR frame directory", {
110602
- videoId,
110603
- frameDir,
110604
- error: err instanceof Error ? err.message : String(err)
110605
- });
110791
+ hdrEncoder.writeFrame(normalCanvas);
110792
+ }
110793
+ if (process.env.KEEP_TEMP !== "1") {
110794
+ for (const [videoId, endTime] of hdrVideoEndTimes) {
110795
+ if (time > endTime && !cleanedUpVideos.has(videoId)) {
110796
+ const stillNeeded = activeTransition && (sceneElements[activeTransition.fromScene]?.includes(videoId) || sceneElements[activeTransition.toScene]?.includes(videoId));
110797
+ if (!stillNeeded) {
110798
+ const frameDir = hdrFrameDirs.get(videoId);
110799
+ if (frameDir) {
110800
+ try {
110801
+ rmSync3(frameDir, { recursive: true, force: true });
110802
+ } catch (err) {
110803
+ log.warn("Failed to clean up HDR frame directory", {
110804
+ videoId,
110805
+ frameDir,
110806
+ error: err instanceof Error ? err.message : String(err)
110807
+ });
110808
+ }
110809
+ frameDirMaxIndexCache.delete(frameDir);
110810
+ hdrFrameDirs.delete(videoId);
110606
110811
  }
110812
+ cleanedUpVideos.add(videoId);
110607
110813
  }
110608
- cleanedUpVideos.add(videoId);
110609
110814
  }
110610
110815
  }
110611
110816
  }
110817
+ job.framesRendered = i + 1;
110818
+ if ((i + 1) % 10 === 0 || i + 1 === totalFrames) {
110819
+ const frameProgress = (i + 1) / totalFrames;
110820
+ updateJobStatus(
110821
+ job,
110822
+ "rendering",
110823
+ `HDR composite frame ${i + 1}/${job.totalFrames}`,
110824
+ Math.round(25 + frameProgress * 55),
110825
+ onProgress
110826
+ );
110827
+ }
110612
110828
  }
110613
- job.framesRendered = i + 1;
110614
- if ((i + 1) % 10 === 0 || i + 1 === totalFrames) {
110615
- const frameProgress = (i + 1) / totalFrames;
110616
- updateJobStatus(
110617
- job,
110618
- "rendering",
110619
- `HDR composite frame ${i + 1}/${job.totalFrames}`,
110620
- Math.round(25 + frameProgress * 55),
110621
- onProgress
110622
- );
110623
- }
110829
+ } finally {
110830
+ lastBrowserConsole = domSession.browserConsoleBuffer;
110831
+ await closeCaptureSession(domSession);
110832
+ domSessionClosed = true;
110624
110833
  }
110834
+ const hdrEncodeResult = await hdrEncoder.close();
110835
+ hdrEncoderClosed = true;
110836
+ assertNotAborted();
110837
+ if (!hdrEncodeResult.success) {
110838
+ throw new Error(`HDR encode failed: ${hdrEncodeResult.error}`);
110839
+ }
110840
+ perfStages.captureMs = Date.now() - stage4Start;
110841
+ perfStages.encodeMs = hdrEncodeResult.durationMs;
110625
110842
  } finally {
110626
- lastBrowserConsole = domSession.browserConsoleBuffer;
110627
- await closeCaptureSession(domSession);
110628
- }
110629
- const hdrEncodeResult = await hdrEncoder.close();
110630
- assertNotAborted();
110631
- if (!hdrEncodeResult.success) {
110632
- throw new Error(`HDR encode failed: ${hdrEncodeResult.error}`);
110843
+ if (hdrEncoder && !hdrEncoderClosed) {
110844
+ try {
110845
+ await hdrEncoder.close();
110846
+ } catch (err) {
110847
+ log.warn("hdrEncoder defensive close failed", {
110848
+ err: err instanceof Error ? err.message : String(err)
110849
+ });
110850
+ }
110851
+ }
110852
+ if (!domSessionClosed) {
110853
+ await closeCaptureSession(domSession).catch((err) => {
110854
+ log.warn("closeCaptureSession defensive close failed", {
110855
+ err: err instanceof Error ? err.message : String(err)
110856
+ });
110857
+ });
110858
+ }
110859
+ for (const frameDir of hdrFrameDirs.values()) {
110860
+ frameDirMaxIndexCache.delete(frameDir);
110861
+ }
110862
+ hdrFrameDirs.clear();
110633
110863
  }
110634
- perfStages.captureMs = Date.now() - stage4Start;
110635
- perfStages.encodeMs = hdrEncodeResult.durationMs;
110636
110864
  } else {
110637
110865
  let streamingEncoder = null;
110866
+ let streamingEncoderClosed = false;
110638
110867
  if (enableStreamingEncode) {
110639
110868
  streamingEncoder = await spawnStreamingEncoder(
110640
110869
  videoOnlyPath,
@@ -110644,7 +110873,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110644
110873
  height,
110645
110874
  codec: preset.codec,
110646
110875
  preset: preset.preset,
110647
- quality: preset.quality,
110876
+ quality: effectiveQuality,
110877
+ bitrate: effectiveBitrate,
110648
110878
  pixelFormat: preset.pixelFormat,
110649
110879
  useGpu: job.config.useGpu,
110650
110880
  imageFormat: captureOptions.format || "jpeg",
@@ -110654,201 +110884,215 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
110654
110884
  );
110655
110885
  assertNotAborted();
110656
110886
  }
110657
- if (enableStreamingEncode && streamingEncoder) {
110658
- const reorderBuffer = createFrameReorderBuffer(0, totalFrames);
110659
- const currentEncoder = streamingEncoder;
110660
- if (workerCount > 1) {
110661
- const tasks = distributeFrames(job.totalFrames, workerCount, workDir);
110662
- const onFrameBuffer = async (frameIndex, buffer) => {
110663
- await reorderBuffer.waitForFrame(frameIndex);
110664
- currentEncoder.writeFrame(buffer);
110665
- reorderBuffer.advanceTo(frameIndex + 1);
110666
- };
110667
- await executeParallelCapture(
110668
- fileServer.url,
110669
- workDir,
110670
- tasks,
110671
- { ...captureOptions, skipReadinessVideoIds: Array.from(nativeHdrVideoIds) },
110672
- () => createVideoFrameInjector(frameLookup),
110673
- abortSignal,
110674
- (progress) => {
110675
- job.framesRendered = progress.capturedFrames;
110676
- const frameProgress = progress.capturedFrames / progress.totalFrames;
110677
- const progressPct = 25 + frameProgress * 55;
110678
- if (progress.capturedFrames % 30 === 0 || progress.capturedFrames === progress.totalFrames) {
110887
+ try {
110888
+ if (enableStreamingEncode && streamingEncoder) {
110889
+ const reorderBuffer = createFrameReorderBuffer(0, totalFrames);
110890
+ const currentEncoder = streamingEncoder;
110891
+ if (workerCount > 1) {
110892
+ const tasks = distributeFrames(job.totalFrames, workerCount, workDir);
110893
+ const onFrameBuffer = async (frameIndex, buffer) => {
110894
+ await reorderBuffer.waitForFrame(frameIndex);
110895
+ currentEncoder.writeFrame(buffer);
110896
+ reorderBuffer.advanceTo(frameIndex + 1);
110897
+ };
110898
+ await executeParallelCapture(
110899
+ fileServer.url,
110900
+ workDir,
110901
+ tasks,
110902
+ buildHdrCaptureOptions(),
110903
+ () => createVideoFrameInjector(frameLookup),
110904
+ abortSignal,
110905
+ (progress) => {
110906
+ job.framesRendered = progress.capturedFrames;
110907
+ const frameProgress = progress.capturedFrames / progress.totalFrames;
110908
+ const progressPct = 25 + frameProgress * 55;
110909
+ if (progress.capturedFrames % 30 === 0 || progress.capturedFrames === progress.totalFrames) {
110910
+ updateJobStatus(
110911
+ job,
110912
+ "rendering",
110913
+ `Streaming frame ${progress.capturedFrames}/${progress.totalFrames} (${workerCount} workers)`,
110914
+ Math.round(progressPct),
110915
+ onProgress
110916
+ );
110917
+ }
110918
+ },
110919
+ onFrameBuffer,
110920
+ cfg
110921
+ );
110922
+ if (probeSession) {
110923
+ lastBrowserConsole = probeSession.browserConsoleBuffer;
110924
+ await closeCaptureSession(probeSession);
110925
+ probeSession = null;
110926
+ }
110927
+ } else {
110928
+ const videoInjector = createVideoFrameInjector(frameLookup);
110929
+ const session = probeSession ?? await createCaptureSession(
110930
+ fileServer.url,
110931
+ framesDir,
110932
+ buildHdrCaptureOptions(),
110933
+ videoInjector,
110934
+ cfg
110935
+ );
110936
+ if (probeSession) {
110937
+ prepareCaptureSessionForReuse(session, framesDir, videoInjector);
110938
+ probeSession = null;
110939
+ }
110940
+ try {
110941
+ if (!session.isInitialized) {
110942
+ await initializeSession(session);
110943
+ }
110944
+ assertNotAborted();
110945
+ lastBrowserConsole = session.browserConsoleBuffer;
110946
+ for (let i = 0; i < totalFrames; i++) {
110947
+ assertNotAborted();
110948
+ const time = i / job.config.fps;
110949
+ const { buffer } = await captureFrameToBuffer(session, i, time);
110950
+ await reorderBuffer.waitForFrame(i);
110951
+ currentEncoder.writeFrame(buffer);
110952
+ reorderBuffer.advanceTo(i + 1);
110953
+ job.framesRendered = i + 1;
110954
+ const frameProgress = (i + 1) / totalFrames;
110955
+ const progress = 25 + frameProgress * 55;
110679
110956
  updateJobStatus(
110680
110957
  job,
110681
110958
  "rendering",
110682
- `Streaming frame ${progress.capturedFrames}/${progress.totalFrames} (${workerCount} workers)`,
110683
- Math.round(progressPct),
110959
+ `Streaming frame ${i + 1}/${job.totalFrames}`,
110960
+ Math.round(progress),
110684
110961
  onProgress
110685
110962
  );
110686
110963
  }
110687
- },
110688
- onFrameBuffer,
110689
- cfg
110690
- );
110691
- if (probeSession) {
110692
- lastBrowserConsole = probeSession.browserConsoleBuffer;
110693
- await closeCaptureSession(probeSession);
110694
- probeSession = null;
110964
+ } finally {
110965
+ lastBrowserConsole = session.browserConsoleBuffer;
110966
+ await closeCaptureSession(session);
110967
+ }
110695
110968
  }
110696
- } else {
110697
- const videoInjector = createVideoFrameInjector(frameLookup);
110698
- const session = probeSession ?? await createCaptureSession(
110699
- fileServer.url,
110700
- framesDir,
110701
- { ...captureOptions, skipReadinessVideoIds: Array.from(nativeHdrVideoIds) },
110702
- videoInjector,
110703
- cfg
110704
- );
110705
- if (probeSession) {
110706
- prepareCaptureSessionForReuse(session, framesDir, videoInjector);
110707
- probeSession = null;
110969
+ const encodeResult = await currentEncoder.close();
110970
+ streamingEncoderClosed = true;
110971
+ assertNotAborted();
110972
+ if (!encodeResult.success) {
110973
+ throw new Error(`Streaming encode failed: ${encodeResult.error}`);
110708
110974
  }
110709
- try {
110710
- if (!session.isInitialized) {
110711
- await initializeSession(session);
110975
+ perfStages.captureMs = Date.now() - stage4Start;
110976
+ perfStages.encodeMs = encodeResult.durationMs;
110977
+ } else {
110978
+ if (workerCount > 1) {
110979
+ const tasks = distributeFrames(job.totalFrames, workerCount, workDir);
110980
+ await executeParallelCapture(
110981
+ fileServer.url,
110982
+ workDir,
110983
+ tasks,
110984
+ buildHdrCaptureOptions(),
110985
+ () => createVideoFrameInjector(frameLookup),
110986
+ abortSignal,
110987
+ (progress) => {
110988
+ job.framesRendered = progress.capturedFrames;
110989
+ const frameProgress = progress.capturedFrames / progress.totalFrames;
110990
+ const progressPct = 25 + frameProgress * 45;
110991
+ if (progress.capturedFrames % 30 === 0 || progress.capturedFrames === progress.totalFrames) {
110992
+ updateJobStatus(
110993
+ job,
110994
+ "rendering",
110995
+ `Capturing frame ${progress.capturedFrames}/${progress.totalFrames} (${workerCount} workers)`,
110996
+ Math.round(progressPct),
110997
+ onProgress
110998
+ );
110999
+ }
111000
+ },
111001
+ void 0,
111002
+ cfg
111003
+ );
111004
+ await mergeWorkerFrames(workDir, tasks, framesDir);
111005
+ if (probeSession) {
111006
+ lastBrowserConsole = probeSession.browserConsoleBuffer;
111007
+ await closeCaptureSession(probeSession);
111008
+ probeSession = null;
110712
111009
  }
110713
- assertNotAborted();
110714
- lastBrowserConsole = session.browserConsoleBuffer;
110715
- for (let i = 0; i < totalFrames; i++) {
110716
- assertNotAborted();
110717
- const time = i / job.config.fps;
110718
- const { buffer } = await captureFrameToBuffer(session, i, time);
110719
- await reorderBuffer.waitForFrame(i);
110720
- currentEncoder.writeFrame(buffer);
110721
- reorderBuffer.advanceTo(i + 1);
110722
- job.framesRendered = i + 1;
110723
- const frameProgress = (i + 1) / totalFrames;
110724
- const progress = 25 + frameProgress * 55;
110725
- updateJobStatus(
110726
- job,
110727
- "rendering",
110728
- `Streaming frame ${i + 1}/${job.totalFrames}`,
110729
- Math.round(progress),
110730
- onProgress
110731
- );
111010
+ } else {
111011
+ const videoInjector = createVideoFrameInjector(frameLookup);
111012
+ const session = probeSession ?? await createCaptureSession(
111013
+ fileServer.url,
111014
+ framesDir,
111015
+ buildHdrCaptureOptions(),
111016
+ videoInjector,
111017
+ cfg
111018
+ );
111019
+ if (probeSession) {
111020
+ prepareCaptureSessionForReuse(session, framesDir, videoInjector);
111021
+ probeSession = null;
110732
111022
  }
110733
- } finally {
110734
- lastBrowserConsole = session.browserConsoleBuffer;
110735
- await closeCaptureSession(session);
110736
- }
110737
- }
110738
- const encodeResult = await currentEncoder.close();
110739
- assertNotAborted();
110740
- if (!encodeResult.success) {
110741
- throw new Error(`Streaming encode failed: ${encodeResult.error}`);
110742
- }
110743
- perfStages.captureMs = Date.now() - stage4Start;
110744
- perfStages.encodeMs = encodeResult.durationMs;
110745
- } else {
110746
- if (workerCount > 1) {
110747
- const tasks = distributeFrames(job.totalFrames, workerCount, workDir);
110748
- await executeParallelCapture(
110749
- fileServer.url,
110750
- workDir,
110751
- tasks,
110752
- { ...captureOptions, skipReadinessVideoIds: Array.from(nativeHdrVideoIds) },
110753
- () => createVideoFrameInjector(frameLookup),
110754
- abortSignal,
110755
- (progress) => {
110756
- job.framesRendered = progress.capturedFrames;
110757
- const frameProgress = progress.capturedFrames / progress.totalFrames;
110758
- const progressPct = 25 + frameProgress * 45;
110759
- if (progress.capturedFrames % 30 === 0 || progress.capturedFrames === progress.totalFrames) {
111023
+ try {
111024
+ if (!session.isInitialized) {
111025
+ await initializeSession(session);
111026
+ }
111027
+ assertNotAborted();
111028
+ lastBrowserConsole = session.browserConsoleBuffer;
111029
+ for (let i = 0; i < job.totalFrames; i++) {
111030
+ assertNotAborted();
111031
+ const time = i / job.config.fps;
111032
+ await captureFrame(session, i, time);
111033
+ job.framesRendered = i + 1;
111034
+ const frameProgress = (i + 1) / job.totalFrames;
111035
+ const progress = 25 + frameProgress * 45;
110760
111036
  updateJobStatus(
110761
111037
  job,
110762
111038
  "rendering",
110763
- `Capturing frame ${progress.capturedFrames}/${progress.totalFrames} (${workerCount} workers)`,
110764
- Math.round(progressPct),
111039
+ `Capturing frame ${i + 1}/${job.totalFrames}`,
111040
+ Math.round(progress),
110765
111041
  onProgress
110766
111042
  );
110767
111043
  }
110768
- },
110769
- void 0,
110770
- cfg
110771
- );
110772
- await mergeWorkerFrames(workDir, tasks, framesDir);
110773
- if (probeSession) {
110774
- lastBrowserConsole = probeSession.browserConsoleBuffer;
110775
- await closeCaptureSession(probeSession);
110776
- probeSession = null;
111044
+ } finally {
111045
+ lastBrowserConsole = session.browserConsoleBuffer;
111046
+ await closeCaptureSession(session);
111047
+ }
110777
111048
  }
110778
- } else {
110779
- const videoInjector = createVideoFrameInjector(frameLookup);
110780
- const session = probeSession ?? await createCaptureSession(
110781
- fileServer.url,
111049
+ perfStages.captureMs = Date.now() - stage4Start;
111050
+ const stage5Start = Date.now();
111051
+ updateJobStatus(job, "encoding", "Encoding video", 75, onProgress);
111052
+ const frameExt = needsAlpha ? "png" : "jpg";
111053
+ const framePattern = `frame_%06d.${frameExt}`;
111054
+ const encoderOpts = {
111055
+ fps: job.config.fps,
111056
+ width,
111057
+ height,
111058
+ codec: preset.codec,
111059
+ preset: preset.preset,
111060
+ quality: effectiveQuality,
111061
+ bitrate: effectiveBitrate,
111062
+ pixelFormat: preset.pixelFormat,
111063
+ useGpu: job.config.useGpu,
111064
+ hdr: preset.hdr
111065
+ };
111066
+ const encodeResult = enableChunkedEncode ? await encodeFramesChunkedConcat(
110782
111067
  framesDir,
110783
- { ...captureOptions, skipReadinessVideoIds: Array.from(nativeHdrVideoIds) },
110784
- videoInjector,
110785
- cfg
111068
+ framePattern,
111069
+ videoOnlyPath,
111070
+ encoderOpts,
111071
+ chunkedEncodeSize,
111072
+ abortSignal
111073
+ ) : await encodeFramesFromDir(
111074
+ framesDir,
111075
+ framePattern,
111076
+ videoOnlyPath,
111077
+ encoderOpts,
111078
+ abortSignal
110786
111079
  );
110787
- if (probeSession) {
110788
- prepareCaptureSessionForReuse(session, framesDir, videoInjector);
110789
- probeSession = null;
111080
+ assertNotAborted();
111081
+ if (!encodeResult.success) {
111082
+ throw new Error(`Encoding failed: ${encodeResult.error}`);
110790
111083
  }
111084
+ perfStages.encodeMs = Date.now() - stage5Start;
111085
+ }
111086
+ } finally {
111087
+ if (streamingEncoder && !streamingEncoderClosed) {
110791
111088
  try {
110792
- if (!session.isInitialized) {
110793
- await initializeSession(session);
110794
- }
110795
- assertNotAborted();
110796
- lastBrowserConsole = session.browserConsoleBuffer;
110797
- for (let i = 0; i < job.totalFrames; i++) {
110798
- assertNotAborted();
110799
- const time = i / job.config.fps;
110800
- await captureFrame(session, i, time);
110801
- job.framesRendered = i + 1;
110802
- const frameProgress = (i + 1) / job.totalFrames;
110803
- const progress = 25 + frameProgress * 45;
110804
- updateJobStatus(
110805
- job,
110806
- "rendering",
110807
- `Capturing frame ${i + 1}/${job.totalFrames}`,
110808
- Math.round(progress),
110809
- onProgress
110810
- );
110811
- }
110812
- } finally {
110813
- lastBrowserConsole = session.browserConsoleBuffer;
110814
- await closeCaptureSession(session);
111089
+ await streamingEncoder.close();
111090
+ } catch (err) {
111091
+ log.warn("streamingEncoder defensive close failed", {
111092
+ err: err instanceof Error ? err.message : String(err)
111093
+ });
110815
111094
  }
110816
111095
  }
110817
- perfStages.captureMs = Date.now() - stage4Start;
110818
- const stage5Start = Date.now();
110819
- updateJobStatus(job, "encoding", "Encoding video", 75, onProgress);
110820
- const frameExt = needsAlpha ? "png" : "jpg";
110821
- const framePattern = `frame_%06d.${frameExt}`;
110822
- const encoderOpts = {
110823
- fps: job.config.fps,
110824
- width,
110825
- height,
110826
- codec: preset.codec,
110827
- preset: preset.preset,
110828
- quality: preset.quality,
110829
- pixelFormat: preset.pixelFormat,
110830
- useGpu: job.config.useGpu,
110831
- hdr: preset.hdr
110832
- };
110833
- const encodeResult = enableChunkedEncode ? await encodeFramesChunkedConcat(
110834
- framesDir,
110835
- framePattern,
110836
- videoOnlyPath,
110837
- encoderOpts,
110838
- chunkedEncodeSize,
110839
- abortSignal
110840
- ) : await encodeFramesFromDir(
110841
- framesDir,
110842
- framePattern,
110843
- videoOnlyPath,
110844
- encoderOpts,
110845
- abortSignal
110846
- );
110847
- assertNotAborted();
110848
- if (!encodeResult.success) {
110849
- throw new Error(`Encoding failed: ${encodeResult.error}`);
110850
- }
110851
- perfStages.encodeMs = Date.now() - stage5Start;
110852
111096
  }
110853
111097
  }
110854
111098
  if (probeSession !== null) {
@@ -111020,7 +111264,7 @@ import {
111020
111264
  rmSync as rmSync4,
111021
111265
  createReadStream as createReadStream2
111022
111266
  } from "node:fs";
111023
- import { resolve as resolve12, dirname as dirname11, join as join17 } from "node:path";
111267
+ import { resolve as resolve13, dirname as dirname11, join as join17 } from "node:path";
111024
111268
  import { tmpdir as tmpdir2 } from "node:os";
111025
111269
  import { parseArgs } from "node:util";
111026
111270
  import crypto2 from "node:crypto";
@@ -111176,7 +111420,7 @@ var streamSSE = (c, cb, onError) => {
111176
111420
 
111177
111421
  // src/services/hyperframeLint.ts
111178
111422
  import { existsSync as existsSync16, readFileSync as readFileSync11, statSync as statSync6 } from "node:fs";
111179
- import { resolve as resolve11, join as join16 } from "node:path";
111423
+ import { resolve as resolve12, join as join16 } from "node:path";
111180
111424
  function isStringRecord(value) {
111181
111425
  if (!value || typeof value !== "object" || Array.isArray(value)) {
111182
111426
  return false;
@@ -111203,7 +111447,7 @@ function pickEntryFile(files, preferredEntryFile) {
111203
111447
  return null;
111204
111448
  }
111205
111449
  function readProjectEntryFile(projectDir, preferredEntryFile) {
111206
- const absProjectDir = resolve11(projectDir);
111450
+ const absProjectDir = resolve12(projectDir);
111207
111451
  if (!existsSync16(absProjectDir) || !statSync6(absProjectDir).isDirectory()) {
111208
111452
  return { error: `Project directory not found: ${absProjectDir}` };
111209
111453
  }
@@ -111211,7 +111455,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
111211
111455
  (value) => typeof value === "string" && value.trim().length > 0
111212
111456
  );
111213
111457
  for (const entryFile of entryCandidates) {
111214
- const absoluteEntryPath = resolve11(absProjectDir, entryFile);
111458
+ const absoluteEntryPath = resolve12(absProjectDir, entryFile);
111215
111459
  if (!absoluteEntryPath.startsWith(absProjectDir)) {
111216
111460
  return { error: `Entry file must stay inside project directory: ${entryFile}` };
111217
111461
  }
@@ -111276,10 +111520,10 @@ var Semaphore = class {
111276
111520
  this.active++;
111277
111521
  return () => this.release();
111278
111522
  }
111279
- return new Promise((resolve13) => {
111523
+ return new Promise((resolve14) => {
111280
111524
  this.queue.push(() => {
111281
111525
  this.active++;
111282
- resolve13(() => this.release());
111526
+ resolve14(() => this.release());
111283
111527
  });
111284
111528
  });
111285
111529
  }
@@ -111314,12 +111558,12 @@ async function prepareRenderBody(body) {
111314
111558
  const options = parseRenderOptions(body);
111315
111559
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
111316
111560
  if (projectDir) {
111317
- const absProjectDir = resolve12(projectDir);
111561
+ const absProjectDir = resolve13(projectDir);
111318
111562
  if (!existsSync17(absProjectDir) || !statSync7(absProjectDir).isDirectory()) {
111319
111563
  return { error: `Project directory not found: ${absProjectDir}` };
111320
111564
  }
111321
111565
  const entry = options.entryFile || "index.html";
111322
- if (!existsSync17(resolve12(absProjectDir, entry))) {
111566
+ if (!existsSync17(resolve13(absProjectDir, entry))) {
111323
111567
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
111324
111568
  }
111325
111569
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -111360,7 +111604,7 @@ function resolveOutputPath(projectDir, outputCandidate, rendersDir, log) {
111360
111604
  try {
111361
111605
  return resolveRenderPaths(projectDir, outputCandidate, rendersDir).absoluteOutputPath;
111362
111606
  } catch (error) {
111363
- const fallbackPath = resolve12(rendersDir, `producer-fallback-${Date.now()}.mp4`);
111607
+ const fallbackPath = resolve13(rendersDir, `producer-fallback-${Date.now()}.mp4`);
111364
111608
  log.warn("Failed to resolve output path, using fallback", {
111365
111609
  fallback: fallbackPath,
111366
111610
  error: error instanceof Error ? error.message : String(error)
@@ -111739,7 +111983,7 @@ function startServer(options = {}) {
111739
111983
  process.on("SIGINT", () => shutdown("SIGINT"));
111740
111984
  return server;
111741
111985
  }
111742
- var entryScript = process.argv[1] ? resolve12(process.argv[1]) : "";
111986
+ var entryScript = process.argv[1] ? resolve13(process.argv[1]) : "";
111743
111987
  var isPublicServerEntry = entryScript.endsWith("/public-server.js") || entryScript.endsWith("/src/server.ts");
111744
111988
  if (isPublicServerEntry) {
111745
111989
  const { values } = parseArgs({