@hyperframes/producer 0.8.193 → 0.8.195

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.
@@ -1583,8 +1583,11 @@ function assertDurationWithinTolerance(expectedSeconds, probedSeconds, tolerance
1583
1583
  `Render artifact is truncated: expected ${expectedSeconds.toFixed(3)}s, probed ${probedSeconds.toFixed(3)}s (deficit ${deficit.toFixed(3)}s exceeds tolerance ${toleranceSeconds.toFixed(3)}s). Artifact: ${stagingPath}`
1584
1584
  );
1585
1585
  }
1586
+ function hasUsableFrameCount(frames) {
1587
+ return frames !== void 0 && Number.isFinite(frames) && frames > 0;
1588
+ }
1586
1589
  function assertFrameCountWithinTolerance(expectedFrames, probedFrames, stagingPath, toleranceFrames = 1) {
1587
- if (probedFrames === void 0 || !Number.isFinite(probedFrames) || probedFrames <= 0) {
1590
+ if (!hasUsableFrameCount(probedFrames)) {
1588
1591
  return;
1589
1592
  }
1590
1593
  const shortfall = expectedFrames - probedFrames;
@@ -1604,9 +1607,10 @@ function assertSizeMatches(expected, probed, stagingPath) {
1604
1607
  );
1605
1608
  }
1606
1609
  var ArtifactTransaction = class {
1607
- constructor(destinationPath, kind, fileSystem = defaultFileSystem, durationProbe = defaultArtifactDurationProbe) {
1610
+ constructor(destinationPath, kind, fileSystem = defaultFileSystem, durationProbe = defaultArtifactDurationProbe, logger = defaultLogger) {
1608
1611
  this.kind = kind;
1609
1612
  this.fileSystem = fileSystem;
1613
+ this.logger = logger;
1610
1614
  this.destinationPath = resolve4(destinationPath);
1611
1615
  this.transactionDirectory = createSiblingTransactionDirectory(this.destinationPath);
1612
1616
  this.stagingPath = join5(this.transactionDirectory, basename3(this.destinationPath));
@@ -1689,6 +1693,19 @@ var ArtifactTransaction = class {
1689
1693
  probePath
1690
1694
  );
1691
1695
  if (expected.expectedFrames !== void 0) {
1696
+ if (!hasUsableFrameCount(probed.frames)) {
1697
+ try {
1698
+ this.logger.debug(
1699
+ "[Render] Frame-count validation skipped: no usable frame count was reported.",
1700
+ {
1701
+ event: "artifact_frame_count_unavailable",
1702
+ artifact: this.destinationPath,
1703
+ expectedFrames: expected.expectedFrames
1704
+ }
1705
+ );
1706
+ } catch {
1707
+ }
1708
+ }
1692
1709
  assertFrameCountWithinTolerance(expected.expectedFrames, probed.frames, probePath);
1693
1710
  }
1694
1711
  assertSizeMatches(expected, probed, probePath);
@@ -5271,12 +5288,15 @@ import {
5271
5288
  readMediaStart,
5272
5289
  redactTelemetryString as redactTelemetryString2,
5273
5290
  resolveNaturalMediaTimelineDurationFromValues,
5291
+ rewriteAssetPath,
5274
5292
  rewriteAssetPaths,
5275
5293
  rewriteCssAssetUrls,
5276
5294
  rewriteInlineStyleAssetUrls
5277
5295
  } from "@hyperframes/core";
5278
5296
  import { MAX_AUDIO_GAIN } from "@hyperframes/core/audio-gain";
5279
- import { gsapCdnDist } from "@hyperframes/core/gsap-cdn";
5297
+ import { readPlaybackRate } from "@hyperframes/parsers/media-duration";
5298
+ import { resolveRateSpec } from "@hyperframes/core/speed-ramp";
5299
+ import { gsapCdnDist, normalizeGsapBaseUrl } from "@hyperframes/core/gsap-cdn";
5280
5300
  import {
5281
5301
  assignBundledRuntimeCompositionIds,
5282
5302
  assignMediaRenderIds,
@@ -6309,7 +6329,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, visited = /*
6309
6329
  const results = await Promise.all(
6310
6330
  workItems.map(async (item) => {
6311
6331
  const { html: compiledSub } = await compileHtmlFile(
6312
- item.rawSubHtml,
6332
+ rewriteUnresolvableGsapToCdn(item.rawSubHtml, projectDir, item.srcPath),
6313
6333
  dirname6(item.filePath),
6314
6334
  downloadDir,
6315
6335
  void 0,
@@ -6483,7 +6503,9 @@ function inlineSubCompositions(html, subCompositions, projectDir, variableOverri
6483
6503
  let compHtml = subCompositions.get(srcPath) || null;
6484
6504
  if (!compHtml) {
6485
6505
  const read = readProjectFile(resolve6(projectDir, srcPath));
6486
- if (read.kind === "file") compHtml = read.text;
6506
+ if (read.kind === "file") {
6507
+ compHtml = rewriteUnresolvableGsapToCdn(read.text, projectDir, srcPath);
6508
+ }
6487
6509
  }
6488
6510
  return compHtml;
6489
6511
  },
@@ -7026,18 +7048,27 @@ async function embedLocalFontFaces(html, projectDir) {
7026
7048
  }
7027
7049
  return result;
7028
7050
  }
7029
- var GSAP_CDN_BASE = gsapCdnDist();
7030
- function rewriteUnresolvableGsapToCdn(html, projectDir) {
7051
+ function renderGsapDist() {
7052
+ try {
7053
+ return gsapCdnDist(void 0, normalizeGsapBaseUrl(process.env.HYPERFRAMES_GSAP_BASE_URL));
7054
+ } catch (cause) {
7055
+ throw new Error(
7056
+ "Invalid HYPERFRAMES_GSAP_BASE_URL: use an absolute HTTPS npm mirror root (plain HTTP only for localhost) without credentials, query, or fragment",
7057
+ { cause }
7058
+ );
7059
+ }
7060
+ }
7061
+ function rewriteUnresolvableGsapToCdn(html, projectDir, compSrcPath) {
7062
+ let gsapDist;
7063
+ const exists = (path) => existsSync10(resolve6(projectDir, path));
7031
7064
  return html.replace(
7032
7065
  /(<script\b[^>]*\bsrc=["'])([^"']*gsap[^"']*\/dist\/([^"']+))(["'][^>]*>)/gi,
7033
7066
  (full, prefix, src, file, suffix) => {
7034
7067
  if (/^https?:\/\//i.test(src)) return full;
7035
- const absPath = resolve6(projectDir, src);
7036
- if (existsSync10(absPath)) return full;
7037
- defaultLogger.info(
7038
- `[Compiler] Rewriting missing gsap script to CDN: ${src} \u2192 ${GSAP_CDN_BASE}${file}`
7039
- );
7040
- return `${prefix}${GSAP_CDN_BASE}${file}${suffix}`;
7068
+ if (exists(compSrcPath ? rewriteAssetPath(compSrcPath, src, exists) : src)) return full;
7069
+ gsapDist ??= renderGsapDist();
7070
+ defaultLogger.info(`[Compiler] Rewriting missing gsap script: ${src} \u2192 ${gsapDist}${file}`);
7071
+ return `${prefix}${gsapDist}${file}${suffix}`;
7041
7072
  }
7042
7073
  );
7043
7074
  }
@@ -7251,6 +7282,9 @@ async function discoverMediaFromBrowser(page) {
7251
7282
  const intrinsicDuration = isImage ? 0 : htmlEl.duration;
7252
7283
  const playbackStartRaw = htmlEl.getAttribute("data-playback-start");
7253
7284
  const mediaStartRaw = htmlEl.getAttribute("data-media-start");
7285
+ const playbackRateRaw = htmlEl.getAttribute("data-playback-rate");
7286
+ const automationRaw = htmlEl.getAttribute("data-automation");
7287
+ const defaultPlaybackRate = isImage ? 1 : htmlEl.defaultPlaybackRate;
7254
7288
  const loop = htmlEl.hasAttribute("loop");
7255
7289
  const hasAudio = htmlEl.getAttribute("data-has-audio") === "true";
7256
7290
  const volume = parseFloat(htmlEl.getAttribute("data-volume") || "1");
@@ -7266,6 +7300,9 @@ async function discoverMediaFromBrowser(page) {
7266
7300
  durationInferred,
7267
7301
  playbackStartRaw,
7268
7302
  mediaStartRaw,
7303
+ playbackRateRaw,
7304
+ automationRaw,
7305
+ defaultPlaybackRate,
7269
7306
  loop,
7270
7307
  hasAudio,
7271
7308
  volume,
@@ -7275,7 +7312,17 @@ async function discoverMediaFromBrowser(page) {
7275
7312
  return results;
7276
7313
  });
7277
7314
  return elements.map(
7278
- ({ endRaw, durationRaw, intrinsicDuration, playbackStartRaw, mediaStartRaw, ...element }) => ({
7315
+ ({
7316
+ endRaw,
7317
+ durationRaw,
7318
+ intrinsicDuration,
7319
+ playbackStartRaw,
7320
+ mediaStartRaw,
7321
+ playbackRateRaw,
7322
+ automationRaw,
7323
+ defaultPlaybackRate,
7324
+ ...element
7325
+ }) => ({
7279
7326
  ...element,
7280
7327
  end: parseStrictFiniteTimingNumber(endRaw) ?? 0,
7281
7328
  duration: element.durationInferred && Number.isFinite(intrinsicDuration) && intrinsicDuration > 0 ? intrinsicDuration : parseStrictFiniteTimingNumber(durationRaw) ?? 0,
@@ -7285,7 +7332,14 @@ async function discoverMediaFromBrowser(page) {
7285
7332
  if (name === "data-media-start") return mediaStartRaw;
7286
7333
  return null;
7287
7334
  }
7288
- })
7335
+ }),
7336
+ playbackRate: resolveRateSpec(
7337
+ automationRaw,
7338
+ readPlaybackRate(
7339
+ (name) => name === "data-playback-rate" ? playbackRateRaw : null,
7340
+ defaultPlaybackRate
7341
+ )
7342
+ )
7289
7343
  })
7290
7344
  );
7291
7345
  }
@@ -7705,9 +7759,18 @@ import {
7705
7759
  getCompositionDuration,
7706
7760
  initializeSession as initializeSession4,
7707
7761
  isTransientBrowserError,
7708
- probeBeginFrameLiveness
7762
+ probeBeginFrameLiveness,
7763
+ videoAudioId
7709
7764
  } from "@hyperframes/engine";
7710
- import { MEDIA_RENDER_ID_ATTR as MEDIA_RENDER_ID_ATTR2, fpsToNumber as fpsToNumber7, readMediaStart as readMediaStart2 } from "@hyperframes/core";
7765
+ import {
7766
+ MEDIA_RENDER_ID_ATTR as MEDIA_RENDER_ID_ATTR2,
7767
+ fpsToNumber as fpsToNumber7,
7768
+ normalizeRateSpec as normalizeRateSpec3,
7769
+ readMediaStart as readMediaStart2,
7770
+ shiftRateLane as shiftRateLane2,
7771
+ sourceTimeAt as sourceTimeAt3,
7772
+ timeAtSourceTime
7773
+ } from "@hyperframes/core";
7711
7774
  import { extractMediaSrcMutations } from "@hyperframes/parsers";
7712
7775
 
7713
7776
  // src/services/render/stages/probeFailures.ts
@@ -7766,16 +7829,28 @@ function authoredMediaStarts(html) {
7766
7829
  }
7767
7830
  return starts;
7768
7831
  }
7769
- function adoptRuntimeMediaStart(composition, el, authored) {
7832
+ function isVideoAudio(audio, videoId) {
7833
+ return audio.type === "video" && audio.id === videoAudioId(videoId);
7834
+ }
7835
+ function adoptRuntimeMediaTiming(composition, el, authored) {
7770
7836
  const shift = el.mediaStart - authored;
7771
- if (el.mediaStart <= 0 || Math.abs(shift) <= BROWSER_MEDIA_EPSILON) return;
7772
7837
  const entries = el.tagName === "video" ? [
7773
7838
  ...composition.videos.filter((video) => video.id === el.id),
7774
- ...composition.audios.filter(
7775
- (audio) => audio.type === "video" && audio.id === `${el.id}-audio`
7776
- )
7839
+ ...composition.audios.filter((audio) => isVideoAudio(audio, el.id))
7777
7840
  ] : composition.audios.filter((audio) => audio.type !== "video" && audio.id === el.id);
7778
- for (const entry of entries) entry.mediaStart += shift;
7841
+ for (const entry of entries) {
7842
+ if (typeof entry.playbackRate !== "object") {
7843
+ if (typeof el.playbackRate === "object") {
7844
+ const consumed = Math.max(0, entry.mediaStart - authored);
7845
+ const head = timeAtSourceTime(normalizeRateSpec3(entry.playbackRate), consumed);
7846
+ entry.mediaStart += sourceTimeAt3(el.playbackRate, head) - consumed;
7847
+ entry.playbackRate = shiftRateLane2(el.playbackRate, head);
7848
+ } else {
7849
+ entry.playbackRate = el.playbackRate;
7850
+ }
7851
+ }
7852
+ if (el.mediaStart > 0 && Math.abs(shift) > BROWSER_MEDIA_EPSILON) entry.mediaStart += shift;
7853
+ }
7779
7854
  }
7780
7855
  function reconcileBrowserMediaEnd(existingEnd, projectedEnd, sourceChanged, durationInferred) {
7781
7856
  if (projectedEnd <= 0) return existingEnd;
@@ -8059,7 +8134,7 @@ async function runProbeStage(input) {
8059
8134
  sourceChanged,
8060
8135
  el.durationInferred
8061
8136
  );
8062
- adoptRuntimeMediaStart(
8137
+ adoptRuntimeMediaTiming(
8063
8138
  composition,
8064
8139
  el,
8065
8140
  authoredStarts.get(el.id) ?? existing.mediaStart
@@ -8082,6 +8157,7 @@ async function runProbeStage(input) {
8082
8157
  start: el.start,
8083
8158
  end: resolveBrowserMediaEnd(el.start, el.end, el.duration),
8084
8159
  mediaStart: el.mediaStart,
8160
+ playbackRate: el.playbackRate,
8085
8161
  loop: el.loop,
8086
8162
  hasAudio: el.hasAudio && !el.muted
8087
8163
  });
@@ -8106,7 +8182,7 @@ async function runProbeStage(input) {
8106
8182
  sourceChanged,
8107
8183
  el.durationInferred
8108
8184
  );
8109
- adoptRuntimeMediaStart(
8185
+ adoptRuntimeMediaTiming(
8110
8186
  composition,
8111
8187
  el,
8112
8188
  authoredStarts.get(el.id) ?? existing.mediaStart
@@ -8124,6 +8200,7 @@ async function runProbeStage(input) {
8124
8200
  end: resolveBrowserMediaEnd(el.start, el.end, el.duration),
8125
8201
  mediaStart: el.mediaStart,
8126
8202
  loop: el.loop,
8203
+ playbackRate: el.playbackRate,
8127
8204
  layer: 0,
8128
8205
  volume: el.volume,
8129
8206
  type: "audio"
@@ -8353,7 +8430,8 @@ import {
8353
8430
  isHttpUrl as isHttpUrl2,
8354
8431
  resolveProjectRelativeSrc as resolveProjectRelativeSrc3,
8355
8432
  runVideoExtractionWithRetry,
8356
- safeVideoExtractionSourceIdentity
8433
+ safeVideoExtractionSourceIdentity,
8434
+ videoAudioId as videoAudioId2
8357
8435
  } from "@hyperframes/engine";
8358
8436
 
8359
8437
  // src/services/render/extractionFailureMetadata.ts
@@ -8706,7 +8784,7 @@ function appendAutoDetectedVideoAudio(composition, extracted) {
8706
8784
  const video = composition.videos.find((v) => v.id === ext.videoId);
8707
8785
  if (!video || !video.hasAudio || video.hidden || existingAudioSrcs.has(video.src)) continue;
8708
8786
  composition.audios.push({
8709
- id: `${video.id}-audio`,
8787
+ id: videoAudioId2(video.id),
8710
8788
  src: video.src,
8711
8789
  start: video.start,
8712
8790
  end: video.end,
@@ -11732,13 +11810,36 @@ function colorGradingValueHasLut(rawAttributeValue) {
11732
11810
  return false;
11733
11811
  }
11734
11812
  }
11735
- async function resolveCompositionElementCount(probeSession, html) {
11813
+ var PROBE_READ_TIMEOUT_MS = 5e3;
11814
+ async function evaluateWithinBound(page, fn, what, log) {
11815
+ let timer;
11816
+ const timedOut = new Promise((_, reject) => {
11817
+ timer = setTimeout(
11818
+ () => reject(new Error(`no answer within ${PROBE_READ_TIMEOUT_MS} ms (page busy)`)),
11819
+ PROBE_READ_TIMEOUT_MS
11820
+ );
11821
+ });
11822
+ try {
11823
+ return await Promise.race([page.evaluate(fn), timedOut]);
11824
+ } catch (err) {
11825
+ log.warn(`[Render] live ${what} read skipped; using the static answer`, {
11826
+ error: err instanceof Error ? err.message : String(err)
11827
+ });
11828
+ throw err;
11829
+ } finally {
11830
+ clearTimeout(timer);
11831
+ }
11832
+ }
11833
+ async function resolveCompositionElementCount(probeSession, html, log = defaultLogger) {
11736
11834
  if (probeSession?.isInitialized) {
11737
11835
  try {
11738
- const liveCount = await probeSession.page.evaluate(
11836
+ const liveCount = await evaluateWithinBound(
11837
+ probeSession.page,
11739
11838
  // Live HTMLCollection length — avoids materializing a static NodeList
11740
11839
  // on the large-DOM comps this gate exists to catch (review nit).
11741
- () => document.getElementsByTagName("*").length
11840
+ () => document.getElementsByTagName("*").length,
11841
+ "element count",
11842
+ log
11742
11843
  );
11743
11844
  if (typeof liveCount === "number" && Number.isFinite(liveCount)) {
11744
11845
  return { count: liveCount, source: "live" };
@@ -11826,11 +11927,11 @@ function probeAdaptersUsed() {
11826
11927
  }
11827
11928
  return used;
11828
11929
  }
11829
- async function resolveAdaptersUsed(probeSession, html) {
11930
+ async function resolveAdaptersUsed(probeSession, html, log = defaultLogger) {
11830
11931
  const staticAdapters = detectAdaptersStatic(html);
11831
11932
  if (!probeSession?.isInitialized) return staticAdapters;
11832
11933
  try {
11833
- const live = await probeSession.page.evaluate(probeAdaptersUsed);
11934
+ const live = await evaluateWithinBound(probeSession.page, probeAdaptersUsed, "adapters", log);
11834
11935
  if (!Array.isArray(live)) return staticAdapters;
11835
11936
  const detected = /* @__PURE__ */ new Set([...staticAdapters, ...live]);
11836
11937
  return KNOWN_RUNTIME_ADAPTERS.filter((name) => detected.has(name));
@@ -12088,7 +12189,10 @@ async function executeRenderPipeline(input) {
12088
12189
  );
12089
12190
  const artifactTransaction = new ArtifactTransaction(
12090
12191
  outputPath,
12091
- isPngSequence || isHls ? "directory" : "file"
12192
+ isPngSequence || isHls ? "directory" : "file",
12193
+ void 0,
12194
+ void 0,
12195
+ log
12092
12196
  );
12093
12197
  const stagedOutputPath = artifactTransaction.stagingPath;
12094
12198
  const needsAlpha = outputNeedsAlpha(outputFormat);
@@ -12587,8 +12691,8 @@ async function executeRenderPipeline(input) {
12587
12691
  vfxHostCount,
12588
12692
  vfxCapture,
12589
12693
  vfxTypes
12590
- } = await resolveCompositionElementCount(probeSession, compiled.html);
12591
- const adaptersUsed = await resolveAdaptersUsed(probeSession, compiled.html);
12694
+ } = await resolveCompositionElementCount(probeSession, compiled.html, log);
12695
+ const adaptersUsed = await resolveAdaptersUsed(probeSession, compiled.html, log);
12592
12696
  const deShortBandEnabled = deShortBandMaxElements > 0;
12593
12697
  const deShortBandOpen = deShortBandEnabled && deShortBandMinFrames > 0 && compositionElementCountSource === "live" && compositionElementCount <= deShortBandMaxElements;
12594
12698
  const deShortBandRoute = process.env.HF_DE_SHORT_BAND_ROUTE === "true";
@@ -1,4 +1,4 @@
1
- import { type ResolvedDuration, type UnresolvedElement } from "@hyperframes/core";
1
+ import { type RateSpec, type ResolvedDuration, type UnresolvedElement } from "@hyperframes/core";
2
2
  import { type VideoElement, type ImageElement, type AudioElement, type AudioVolumeKeyframe } from "@hyperframes/engine";
3
3
  import type { Page } from "puppeteer-core";
4
4
  import { type ProducerLogger } from "../logger.js";
@@ -216,6 +216,7 @@ export interface BrowserMediaElement {
216
216
  /** True when compilation inferred duration from the fallback source. */
217
217
  durationInferred: boolean;
218
218
  mediaStart: number;
219
+ playbackRate: RateSpec;
219
220
  loop: boolean;
220
221
  hasAudio: boolean;
221
222
  volume: number;
@@ -1,3 +1,4 @@
1
+ import { type ProducerLogger } from "../../logger.js";
1
2
  import type { RenderOutputFormat } from "./renderFormat.js";
2
3
  export type ArtifactKind = "file" | "directory";
3
4
  export interface ArtifactTransactionFileSystem {
@@ -113,13 +114,14 @@ export declare function buildArtifactExpectation(input: {
113
114
  export declare class ArtifactTransaction {
114
115
  private readonly kind;
115
116
  private readonly fileSystem;
117
+ private readonly logger;
116
118
  readonly destinationPath: string;
117
119
  readonly stagingPath: string;
118
120
  private readonly transactionDirectory;
119
121
  private readonly backupPath;
120
122
  private state;
121
123
  private readonly durationProbe;
122
- constructor(destinationPath: string, kind: ArtifactKind, fileSystem?: ArtifactTransactionFileSystem, durationProbe?: ArtifactDurationProbe);
124
+ constructor(destinationPath: string, kind: ArtifactKind, fileSystem?: ArtifactTransactionFileSystem, durationProbe?: ArtifactDurationProbe, logger?: Pick<ProducerLogger, "debug">);
123
125
  validate(expected?: ArtifactValidationExpectation): Promise<void>;
124
126
  private assertReadableNonEmptyDirectory;
125
127
  /**
@@ -706,6 +706,8 @@ export interface ElementTagScan {
706
706
  * live count and uses this only when no such session exists.
707
707
  */
708
708
  export declare function scanElementTags(html: string): ElementTagScan;
709
+ /** Longest a live probe-page read may hold the render; a busy page otherwise waits out the CDP timeout. */
710
+ export declare const PROBE_READ_TIMEOUT_MS = 5000;
709
711
  /**
710
712
  * Element count for the short-comp band's gate, WITH PROVENANCE.
711
713
  *
@@ -728,7 +730,7 @@ export declare function scanElementTags(html: string): ElementTagScan;
728
730
  * the fleet distribution recorded by the baseline release must be measured
729
731
  * by the same resolver that later gates routing, or the baseline is invalid.
730
732
  */
731
- export declare function resolveCompositionElementCount(probeSession: Pick<CaptureSession, "isInitialized" | "page"> | null, html: string): Promise<{
733
+ export declare function resolveCompositionElementCount(probeSession: Pick<CaptureSession, "isInitialized" | "page"> | null, html: string, log?: Pick<ProducerLogger, "warn">): Promise<{
732
734
  count: number;
733
735
  source: "live" | "static";
734
736
  byTag?: Readonly<Record<string, number>>;
@@ -761,7 +763,7 @@ export declare function detectAdaptersStatic(html: string): RuntimeAdapterName[]
761
763
  * Runtime adapters a composition exercises. Unlike `resolveCompositionElementCount`
762
764
  * (one source of truth, for gating), this is observational: unions live + static every render.
763
765
  */
764
- export declare function resolveAdaptersUsed(probeSession: Pick<CaptureSession, "isInitialized" | "page"> | null, html: string): Promise<readonly RuntimeAdapterName[]>;
766
+ export declare function resolveAdaptersUsed(probeSession: Pick<CaptureSession, "isInitialized" | "page"> | null, html: string, log?: Pick<ProducerLogger, "warn">): Promise<readonly RuntimeAdapterName[]>;
765
767
  /**
766
768
  * Max-merge init telemetry across per-worker capture perf summaries — the
767
769
  * success-path channel for PARALLEL renders, whose worker console buffers
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/producer",
3
- "version": "0.8.193",
3
+ "version": "0.8.195",
4
4
  "description": "HTML-to-video rendering engine using Chrome's BeginFrame API",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,11 +35,11 @@
35
35
  "postcss": "^8.4.0",
36
36
  "puppeteer": "^25.2.1",
37
37
  "puppeteer-core": "^25.2.1",
38
- "@hyperframes/engine": "0.8.193",
39
- "@hyperframes/core": "0.8.193",
40
- "@hyperframes/parsers": "0.8.193",
41
- "@hyperframes/lint": "0.8.193",
42
- "@hyperframes/studio-server": "0.8.193"
38
+ "@hyperframes/core": "0.8.195",
39
+ "@hyperframes/lint": "0.8.195",
40
+ "@hyperframes/studio-server": "0.8.195",
41
+ "@hyperframes/parsers": "0.8.195",
42
+ "@hyperframes/engine": "0.8.195"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/node": "^25.0.10",
@@ -48,7 +48,7 @@
48
48
  "tsx": "^4.21.0",
49
49
  "typescript": "^5.7.2",
50
50
  "vitest": "^4.1.11",
51
- "@hyperframes/aws-lambda": "0.8.193"
51
+ "@hyperframes/aws-lambda": "0.8.195"
52
52
  },
53
53
  "engines": {
54
54
  "node": ">=22"