@hyperframes/producer 0.8.184 → 0.8.186

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.
@@ -2255,7 +2255,10 @@ function stripCompilerMountBootstrap(source) {
2255
2255
  ""
2256
2256
  );
2257
2257
  }
2258
- function detectRenderModeHints(html) {
2258
+ function runtimeRoot(document2) {
2259
+ return document2.querySelector('[data-composition-id][data-root="true"]') ?? document2.querySelector("[data-composition-id]");
2260
+ }
2261
+ function detectRenderModeHints(html, pageMotionBlur) {
2259
2262
  const reasons = [];
2260
2263
  const { document: document2 } = parseHTML4(html);
2261
2264
  if (document2.querySelector("canvas[layoutsubtree]")) {
@@ -2263,6 +2266,11 @@ function detectRenderModeHints(html) {
2263
2266
  code: "htmlInCanvas",
2264
2267
  message: "Detected html-in-canvas API (layoutsubtree canvas). Chrome does not support concurrent drawElementImage across multiple workers; render is pinned to a single worker."
2265
2268
  });
2269
+ } else if (pageMotionBlur !== "off" && runtimeRoot(document2)?.getAttribute("data-motion-blur") === "on") {
2270
+ reasons.push({
2271
+ code: "captureMotionBlur",
2272
+ message: 'Detected capture motion blur (data-motion-blur="on"), which draws each frame with html-in-canvas; routed through screenshot capture mode.'
2273
+ });
2266
2274
  }
2267
2275
  if (document2.querySelector("iframe")) {
2268
2276
  reasons.push({
@@ -3294,7 +3302,7 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
3294
3302
  /(<(?:video|audio)\b[^>]*?)\s+preload\s*=\s*["']none["']/gi,
3295
3303
  "$1"
3296
3304
  );
3297
- const renderModeHints = detectRenderModeHints(sanitizedHtml);
3305
+ const renderModeHints = detectRenderModeHints(sanitizedHtml, options.pageMotionBlur);
3298
3306
  const hasShaderTransitions = detectShaderTransitionUsage(sanitizedHtml);
3299
3307
  const usesThreeDTransforms = detectThreeDTransformUsage(sanitizedHtml);
3300
3308
  const usesMixBlendMode = detectMixBlendModeUsage(sanitizedHtml);
@@ -3779,6 +3787,7 @@ async function runCompileStage(input) {
3779
3787
  abortSignal,
3780
3788
  variables: input.variables,
3781
3789
  urlByAbsentLocalPath: input.urlByAbsentLocalPath,
3790
+ pageMotionBlur: input.pageMotionBlur,
3782
3791
  animatedGifCacheDir: cfg.extractCacheDir ? join6(cfg.extractCacheDir, "animated-gif") : void 0,
3783
3792
  ffmpegProcessTimeout: cfg.ffmpegProcessTimeout
3784
3793
  });
@@ -4075,6 +4084,7 @@ async function runProbeStage(input) {
4075
4084
  variables: job.config.variables,
4076
4085
  deviceScaleFactor,
4077
4086
  motionBlur,
4087
+ pageMotionBlur: job.config.pageMotionBlur,
4078
4088
  requiresWebGpu: compositionRequiresWebGpu(compiled.html),
4079
4089
  subTimelineWaitMemo
4080
4090
  };
@@ -5990,7 +6000,6 @@ async function enforceAacTruePeak(input) {
5990
6000
  try {
5991
6001
  scratchDir = mkdtempSync2(join13(dirname6(input.audioPath), ".true-peak-"));
5992
6002
  const correctedPath = join13(scratchDir, "audio.m4a");
5993
- const correctionTargetDbfs = AAC_DELIVERY_TRUE_PEAK_DBFS - AAC_TRUE_PEAK_CORRECTION_HEADROOM_DB;
5994
6003
  const measurements = [];
5995
6004
  let attenuationDb = 0;
5996
6005
  let measuredPath = input.audioPath;
@@ -6008,7 +6017,8 @@ async function enforceAacTruePeak(input) {
6008
6017
  return { success: true, loweredDb: Number((-attenuationDb).toFixed(2)) };
6009
6018
  }
6010
6019
  if (pass === MAX_TRUE_PEAK_CORRECTION_PASSES) break;
6011
- attenuationDb += correctionTargetDbfs - truePeakDbfs;
6020
+ const headroomDb = AAC_TRUE_PEAK_CORRECTION_HEADROOM_DB * 2 ** pass;
6021
+ attenuationDb += AAC_DELIVERY_TRUE_PEAK_DBFS - headroomDb - truePeakDbfs;
6012
6022
  const result = await input.encode(
6013
6023
  input.audioPath,
6014
6024
  correctedPath,
@@ -6806,7 +6816,8 @@ function buildSyntheticRenderJob(input) {
6806
6816
  hdrMode: input.hdrMode,
6807
6817
  strictness: input.strictness,
6808
6818
  producerConfig: input.producerConfig,
6809
- variables: input.variables
6819
+ variables: input.variables,
6820
+ pageMotionBlur: "off"
6810
6821
  };
6811
6822
  return createRenderJob(renderConfig);
6812
6823
  }
@@ -6851,7 +6862,14 @@ var RenderChunkValidationError = class extends Error {
6851
6862
  }
6852
6863
  };
6853
6864
  function createChunkVideoFrameInjectorFactory(frameLookup) {
6854
- return () => createVideoFrameInjector2(frameLookup);
6865
+ if (!(frameLookup instanceof Promise)) return () => createVideoFrameInjector2(frameLookup);
6866
+ return () => {
6867
+ let hook;
6868
+ return async (page, time, heldVideoTime) => {
6869
+ hook ??= createVideoFrameInjector2(await frameLookup);
6870
+ await hook?.(page, time, heldVideoTime);
6871
+ };
6872
+ };
6855
6873
  }
6856
6874
  function frameNumberFromFileName(name) {
6857
6875
  const match = /(\d+)(?=\.[^.]+$)/.exec(name);
@@ -6923,6 +6941,7 @@ function buildChunkCaptureOptions(input) {
6923
6941
  skipReadinessVideoIds: input.skipReadinessVideoIds,
6924
6942
  videoMetadataHints: input.videoMetadataHints,
6925
6943
  ...videoCaptureBeyondViewport !== void 0 ? { captureBeyondViewport: videoCaptureBeyondViewport } : {},
6944
+ pageMotionBlur: "distributed-render",
6926
6945
  // A fixed warmup count keeps `beginFrameTimeTicks` host-independent.
6927
6946
  lockWarmupTicks: true,
6928
6947
  requiresWebGpu: compositionRequiresWebGpu3(input.html)
@@ -8589,7 +8608,8 @@ async function compilePlanComposition(projectDir, config, planDir, options) {
8589
8608
  // Distributed renders must not capture host-specific system fonts —
8590
8609
  // the Lambda/worker filesystem won't have the same fonts installed.
8591
8610
  allowSystemFontCapture: false,
8592
- variables: config.variables
8611
+ variables: config.variables,
8612
+ pageMotionBlur: job.config.pageMotionBlur
8593
8613
  });
8594
8614
  logPlanStage(log, "compile", stageStarted);
8595
8615
  let compiled = compileResult.compiled;
@@ -10507,6 +10527,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
10507
10527
  const captureAttempts = [];
10508
10528
  let forceScreenshotForChunk = encoder.forceScreenshot;
10509
10529
  let shownBoxes;
10530
+ let extraction;
10510
10531
  try {
10511
10532
  if (chunkWorkerCount === 1 || !forceScreenshotForChunk) {
10512
10533
  const bootStarted = Date.now();
@@ -10563,7 +10584,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
10563
10584
  session = null;
10564
10585
  }
10565
10586
  }
10566
- const deferredVideoFrames = planVideos ? await extractDeferredVideoFramesForChunk({
10587
+ const deferredVideoFrames = planVideos ? extractDeferredVideoFramesForChunk({
10567
10588
  planDir,
10568
10589
  planVideos,
10569
10590
  frames: chunkFrameNumbers,
@@ -10572,19 +10593,24 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
10572
10593
  cfg,
10573
10594
  remoteSources,
10574
10595
  shownBoxes
10575
- }) : [];
10576
- const videoFrameLookup = planVideos && planVideos.extracted.length > 0 ? createFrameLookupTable5(
10577
- planVideos.videos,
10578
- [
10579
- ...rebuildExtractedFramesFromPlanDir(
10580
- planDir,
10581
- planVideos.extracted.filter((video) => !video.deferredRange),
10582
- v2Manifest === null ? "dense-v1" : "sparse-v2"
10583
- ),
10584
- ...deferredVideoFrames
10585
- ],
10586
- resolveRenderFpsConfig(job.config.fps).value
10596
+ }) : Promise.resolve([]);
10597
+ extraction = deferredVideoFrames;
10598
+ const videoFrameLookup = planVideos && planVideos.extracted.length > 0 ? deferredVideoFrames.then(
10599
+ (deferred) => createFrameLookupTable5(
10600
+ planVideos.videos,
10601
+ [
10602
+ ...rebuildExtractedFramesFromPlanDir(
10603
+ planDir,
10604
+ planVideos.extracted.filter((video) => !video.deferredRange),
10605
+ v2Manifest === null ? "dense-v1" : "sparse-v2"
10606
+ ),
10607
+ ...deferred
10608
+ ],
10609
+ resolveRenderFpsConfig(job.config.fps).value
10610
+ )
10587
10611
  ) : null;
10612
+ videoFrameLookup?.catch(() => {
10613
+ });
10588
10614
  const createChunkVideoFrameInjector = createChunkVideoFrameInjectorFactory(videoFrameLookup);
10589
10615
  const captureStarted = Date.now();
10590
10616
  captureMode = await runCaptureWithScreenshotFallback({
@@ -10667,7 +10693,11 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
10667
10693
  }
10668
10694
  );
10669
10695
  }
10696
+ }).catch(async (captureError) => {
10697
+ await deferredVideoFrames;
10698
+ throw captureError;
10670
10699
  });
10700
+ await deferredVideoFrames;
10671
10701
  captureStageMs = Date.now() - captureStarted;
10672
10702
  applyRenderWarningPolicy(
10673
10703
  job,
@@ -10746,6 +10776,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
10746
10776
  }
10747
10777
  encodeStageMs = Date.now() - encodeStarted;
10748
10778
  } finally {
10779
+ await extraction?.catch(() => {
10780
+ });
10749
10781
  if (session) {
10750
10782
  try {
10751
10783
  await closeCaptureSession10(session);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "0.1.0",
3
3
  "buildId": "dev",
4
- "sha256": "fea4702bf337d3efdccc5f67da5d2d744a83ac9ab0cde7a82b0a378ab7e8e211",
4
+ "sha256": "70c934b140617fa19f8ceb0444d107d1232d9c56987c0207d4e05fc658356a42",
5
5
  "artifacts": {
6
6
  "iife": "hyperframe.runtime.iife.js",
7
7
  "esm": "hyperframe.runtime.mjs"