@hyperframes/producer 0.8.207 → 0.8.209

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.
@@ -794,7 +794,7 @@ function createFileServer(options) {
794
794
  if (!streamOwnsFd) closeSync(fd);
795
795
  }
796
796
  });
797
- return new Promise((resolve10) => {
797
+ return new Promise((resolve10, reject) => {
798
798
  const connections = /* @__PURE__ */ new Set();
799
799
  const server = serve({ fetch: app.fetch, port, hostname: "127.0.0.1" }, (info) => {
800
800
  resolve10({
@@ -814,6 +814,7 @@ function createFileServer(options) {
814
814
  connections.add(socket);
815
815
  socket.on("close", () => connections.delete(socket));
816
816
  });
817
+ server.on("error", reject);
817
818
  });
818
819
  }
819
820
 
@@ -1858,7 +1859,7 @@ import { gsapCdnDist, normalizeGsapBaseUrl } from "@hyperframes/core/gsap-cdn";
1858
1859
  import {
1859
1860
  assignBundledRuntimeCompositionIds,
1860
1861
  assignMediaRenderIds,
1861
- buildVariablesByCompScript,
1862
+ emitVariablesByCompScript,
1862
1863
  inlineSubCompositions as inlineSubCompositionsShared,
1863
1864
  ensureExternalLinkTag,
1864
1865
  ensureExternalScriptTag,
@@ -3430,9 +3431,9 @@ function inlineSubCompositions(html, subCompositions, projectDir, variableOverri
3430
3431
  }
3431
3432
  }
3432
3433
  }
3433
- const variablesByCompScript = buildVariablesByCompScript(result.variablesByComp);
3434
+ emitVariablesByCompScript(document2, result.variablesByComp);
3434
3435
  if (body) {
3435
- let pending = variablesByCompScript ? [variablesByCompScript] : [];
3436
+ let pending = [];
3436
3437
  const flushInline = () => {
3437
3438
  if (!pending.length) return;
3438
3439
  const joined = pending.join("\n;\n");
@@ -5446,10 +5447,11 @@ var VideoExtractionStageError = class extends Error {
5446
5447
  kind: failure.kind,
5447
5448
  affectedElementCount: failure.count
5448
5449
  }))
5449
- )) {
5450
+ ), ffmpegReason) {
5450
5451
  const total = failures.reduce((sum2, failure) => sum2 + failure.count, 0);
5451
5452
  const breakdown = failures.map((failure) => `${failure.kind}=${failure.count}`).join(",");
5452
- super(`Video extraction failed for ${total} source(s) [${code}; ${breakdown}]`);
5453
+ const reason = ffmpegReason ? `: ffmpeg said: ${ffmpegReason}` : "";
5454
+ super(`Video extraction failed for ${total} source(s) [${code}; ${breakdown}]${reason}`);
5453
5455
  this.code = code;
5454
5456
  this.retryable = retryable;
5455
5457
  this.failures = failures;
@@ -5496,7 +5498,8 @@ function buildVideoExtractionStageError(result) {
5496
5498
  retryable ? "VIDEO_EXTRACTION_FAILED" : "VIDEO_SOURCE_UNRENDERABLE",
5497
5499
  retryable,
5498
5500
  failures,
5499
- extractionFailureMetadataFromResult(result)
5501
+ extractionFailureMetadataFromResult(result),
5502
+ result.errors.find((failure) => failure.ffmpegReason)?.ffmpegReason
5500
5503
  );
5501
5504
  }
5502
5505
  function buildHdrProbeStageError(failures) {
@@ -6501,6 +6504,7 @@ async function runCaptureStage(input) {
6501
6504
  dedupPerfs,
6502
6505
  pageErrorLines: workerPageErrors,
6503
6506
  openAttempt: input.openAttempt,
6507
+ verifyFirstSession: input.verifyFirstSession,
6504
6508
  onProgress: (progress) => {
6505
6509
  if (progress.latestWorkerPhase) {
6506
6510
  if (progress.capturedFrames === 0) reportWorkerStartup(job, progress, onProgress);
@@ -7371,7 +7375,8 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
7371
7375
  });
7372
7376
  } : void 0,
7373
7377
  void 0,
7374
- options.cfg
7378
+ options.cfg,
7379
+ { verifyFirstSession: options.verifyFirstSession }
7375
7380
  );
7376
7381
  pushWorkerDedupPerfs(workerResults, options.dedupPerfs);
7377
7382
  if (options.pageErrorLines) pushWorkerPageErrors(workerResults, options.pageErrorLines);
@@ -11432,16 +11437,18 @@ function observedChunkCaptureMode(perfs) {
11432
11437
  }
11433
11438
  return mode;
11434
11439
  }
11440
+ var PROBE_SELECTED_SCREENSHOT = "[renderChunk] probe selected screenshot capture";
11435
11441
  function shouldRetryChunkCaptureWithScreenshot(error) {
11436
11442
  const failure = classifyCaptureFailure4(error);
11437
11443
  if (failure.kind === "cancelled" || failure.kind === "memory_exhaustion") return false;
11438
- return /HeadlessExperimental\.beginFrame/i.test(failure.message) || /beginFrame probe timeout/i.test(failure.message) || /Another frame is pending|Frame still pending/i.test(failure.message);
11444
+ return /HeadlessExperimental\.beginFrame/i.test(failure.message) || /beginFrame probe timeout/i.test(failure.message) || failure.message.includes(PROBE_SELECTED_SCREENSHOT) || /Another frame is pending|Frame still pending/i.test(failure.message);
11439
11445
  }
11440
11446
  async function runCaptureWithScreenshotFallback(input) {
11441
11447
  try {
11442
11448
  return await input.run(input.forceScreenshot);
11443
11449
  } catch (error) {
11444
- if (input.forceScreenshot || !shouldRetryChunkCaptureWithScreenshot(error)) throw error;
11450
+ if (input.forceScreenshot || await input.canRetry?.() === false) throw error;
11451
+ if (!shouldRetryChunkCaptureWithScreenshot(error)) throw error;
11445
11452
  input.onFallback?.(error);
11446
11453
  await input.resetForScreenshotRetry();
11447
11454
  return await input.run(true);
@@ -11650,7 +11657,24 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11650
11657
  let extraction;
11651
11658
  const overlap = { current: null };
11652
11659
  try {
11653
- if (chunkWorkerCount === 1 || !forceScreenshotForChunk) {
11660
+ const verifyInWorker = chunkWorkerCount > 1 && !forceScreenshotForChunk;
11661
+ let boxesMeasured;
11662
+ let boxesFailed;
11663
+ const boxesReady = new Promise((resolve10, reject) => {
11664
+ boxesMeasured = resolve10;
11665
+ boxesFailed = reject;
11666
+ });
11667
+ boxesReady.catch(() => {
11668
+ });
11669
+ const measureBoxes = async (page) => {
11670
+ shownBoxes = await measureVideoShownBoxes(
11671
+ page,
11672
+ [...shownFrames.keys()],
11673
+ chunkFrameNumbers.map((frame) => frame * chunkFps.den / chunkFps.num)
11674
+ );
11675
+ boxesMeasured();
11676
+ };
11677
+ if (chunkWorkerCount === 1) {
11654
11678
  const bootStarted = Date.now();
11655
11679
  session = await createVerifiedDistributedCaptureSession(
11656
11680
  fileServer.url,
@@ -11659,11 +11683,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11659
11683
  cfg
11660
11684
  );
11661
11685
  sessionBootMs = Date.now() - bootStarted;
11662
- shownBoxes = await measureVideoShownBoxes(
11663
- session.page,
11664
- [...shownFrames.keys()],
11665
- chunkFrameNumbers.map((frame) => frame * chunkFps.den / chunkFps.num)
11666
- );
11686
+ await measureBoxes(session.page);
11667
11687
  const browserSelectedScreenshot = session.launchCaptureMode === "screenshot";
11668
11688
  const beginFrameStalled = !browserSelectedScreenshot && await beginFrameSessionNeedsScreenshotFallback(session);
11669
11689
  if (browserSelectedScreenshot) {
@@ -11672,10 +11692,6 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11672
11692
  "[renderChunk] Browser capability probe selected screenshot capture for the entire chunk",
11673
11693
  { chunkIndex }
11674
11694
  );
11675
- if (chunkWorkerCount > 1) {
11676
- await closeCaptureSession10(session);
11677
- session = null;
11678
- }
11679
11695
  } else if (beginFrameStalled) {
11680
11696
  forceScreenshotForChunk = true;
11681
11697
  log.warn(
@@ -11685,41 +11701,66 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11685
11701
  await closeCaptureSession10(session).catch(() => {
11686
11702
  });
11687
11703
  session = null;
11688
- if (chunkWorkerCount === 1) {
11689
- const screenshotBootStarted = Date.now();
11690
- const screenshotCfg = {
11691
- ...cfg,
11692
- forceScreenshot: true,
11693
- forceScreenshotExplicitlyOptedOut: false
11694
- };
11695
- session = await createVerifiedDistributedCaptureSession(
11696
- fileServer.url,
11697
- framesDir,
11698
- captureOptions,
11699
- screenshotCfg
11704
+ const screenshotBootStarted = Date.now();
11705
+ const screenshotCfg = {
11706
+ ...cfg,
11707
+ forceScreenshot: true,
11708
+ forceScreenshotExplicitlyOptedOut: false
11709
+ };
11710
+ session = await createVerifiedDistributedCaptureSession(
11711
+ fileServer.url,
11712
+ framesDir,
11713
+ captureOptions,
11714
+ screenshotCfg
11715
+ );
11716
+ sessionBootMs += Date.now() - screenshotBootStarted;
11717
+ }
11718
+ } else if (!verifyInWorker) {
11719
+ boxesMeasured();
11720
+ }
11721
+ let verification;
11722
+ const verifyFirstWorker = (first) => verification ??= (async () => {
11723
+ sessionBootMs = Date.now() - verifyStarted;
11724
+ try {
11725
+ await measureBoxes(first.page);
11726
+ const selectedScreenshot = first.launchCaptureMode === "screenshot";
11727
+ if (selectedScreenshot || await beginFrameSessionNeedsScreenshotFallback(first)) {
11728
+ forceScreenshotForChunk = true;
11729
+ log.warn(
11730
+ selectedScreenshot ? "[renderChunk] Browser capability probe selected screenshot capture for the entire chunk" : "[renderChunk] BeginFrame liveness probe failed; using screenshot capture for the entire chunk",
11731
+ { chunkIndex }
11700
11732
  );
11701
- sessionBootMs += Date.now() - screenshotBootStarted;
11733
+ throw new Error(PROBE_SELECTED_SCREENSHOT);
11702
11734
  }
11703
- } else if (chunkWorkerCount > 1) {
11704
- await closeCaptureSession10(session);
11705
- session = null;
11735
+ } catch (error) {
11736
+ if (!forceScreenshotForChunk) {
11737
+ verifyFailure = error;
11738
+ boxesFailed(error);
11739
+ }
11740
+ throw error;
11706
11741
  }
11707
- }
11708
- const extractStarted = Date.now();
11709
- const deferredVideoFrames = planVideos ? extractDeferredVideoFramesForChunk({
11710
- planDir,
11711
- planVideos,
11712
- frames: chunkFrameNumbers,
11713
- fps: chunkFps,
11714
- outputRoot: videoFramesDir,
11715
- cfg,
11716
- remoteSources,
11717
- shownBoxes
11718
- }).then((frames) => {
11719
- videoExtractMs = Date.now() - extractStarted;
11720
- return frames;
11721
- }) : Promise.resolve([]);
11742
+ })();
11743
+ let verifyStarted = 0;
11744
+ let verifyFailure;
11745
+ const deferredVideoFrames = planVideos ? boxesReady.then(() => {
11746
+ const extractStarted = Date.now();
11747
+ return extractDeferredVideoFramesForChunk({
11748
+ planDir,
11749
+ planVideos,
11750
+ frames: chunkFrameNumbers,
11751
+ fps: chunkFps,
11752
+ outputRoot: videoFramesDir,
11753
+ cfg,
11754
+ remoteSources,
11755
+ shownBoxes
11756
+ }).then((frames) => {
11757
+ videoExtractMs = Date.now() - extractStarted;
11758
+ return frames;
11759
+ });
11760
+ }) : boxesReady.then(() => []);
11722
11761
  extraction = deferredVideoFrames;
11762
+ deferredVideoFrames.catch(() => {
11763
+ });
11723
11764
  const videoFrameLookup = planVideos && planVideos.extracted.length > 0 ? deferredVideoFrames.then(
11724
11765
  (deferred) => createFrameLookupTable5(
11725
11766
  planVideos.videos,
@@ -11798,6 +11839,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11798
11839
  const captureStarted = Date.now();
11799
11840
  captureMode = await runCaptureWithScreenshotFallback({
11800
11841
  forceScreenshot: forceScreenshotForChunk,
11842
+ canRetry: () => verifyFailure === void 0,
11801
11843
  // fallow-ignore-next-line complexity
11802
11844
  run: async (forceScreenshot) => {
11803
11845
  const captureCfg = cfg.forceScreenshot === forceScreenshot ? cfg : {
@@ -11827,6 +11869,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11827
11869
  }
11828
11870
  const captureSession = session;
11829
11871
  session = null;
11872
+ verifyStarted = Date.now();
11830
11873
  overlap.current = canEncodeWhileCapturing(encodeInput, chunkWorkerCount, cpus().length) ? encodeWhileCapturing(encodeInput, framesInChunk) : null;
11831
11874
  await observeRenderStage(
11832
11875
  new RenderObservabilityRecorder({ pipelineStartMs: start, log }),
@@ -11854,7 +11897,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11854
11897
  frameRange: range,
11855
11898
  onFrameLanded: (frame) => overlap.current?.onFrameLanded(frame),
11856
11899
  interleaveFrames: interleavesCapture(overlap.current !== null, options),
11857
- openAttempt
11900
+ openAttempt,
11901
+ verifyFirstSession: forceScreenshot || !verifyInWorker ? void 0 : verifyFirstWorker
11858
11902
  }),
11859
11903
  { stall: frameStallRule(job) }
11860
11904
  ).catch(async (captureError) => {
@@ -11866,6 +11910,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11866
11910
  },
11867
11911
  resetForScreenshotRetry: () => {
11868
11912
  rmSync11(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
11913
+ boxesMeasured();
11869
11914
  mkdirSync14(framesDir, { recursive: true });
11870
11915
  capturePerfs.length = 0;
11871
11916
  captureAttempts.length = 0;
@@ -11881,6 +11926,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
11881
11926
  );
11882
11927
  }
11883
11928
  }).catch(async (captureError) => {
11929
+ if (verifyFailure !== void 0) throw verifyFailure;
11930
+ boxesFailed(captureError);
11884
11931
  await deferredVideoFrames;
11885
11932
  throw captureError;
11886
11933
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "0.1.0",
3
3
  "buildId": "dev",
4
- "sha256": "98ef5d9ded07a8647d7220aa648089eaf8ad2c3ddee0e2e6d563f80ba60a7a58",
4
+ "sha256": "d294fc169f5c0e16d5272a816ae4f0fd6e78a652c61fd6939c882c9bee81efeb",
5
5
  "artifacts": {
6
6
  "iife": "hyperframe.runtime.iife.js",
7
7
  "esm": "hyperframe.runtime.mjs"