hyperframes 0.8.22 → 0.8.24

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.
@@ -62903,7 +62903,22 @@ async function downloadWithRetry(url, localPath, timeoutMs, signal, onTransientR
62903
62903
  return await runDownloadAttempt(url, localPath, timeoutMs, attempt + 1, options, signal);
62904
62904
  } catch (error) {
62905
62905
  const classified = classifyDownloadFailure(error);
62906
- if (!classified.locallyRetryable || attempt >= maxTransientRetries) throw classified;
62906
+ if (!classified.locallyRetryable || attempt >= maxTransientRetries) {
62907
+ const identity2 = safeDownloadUrlIdentity(url);
62908
+ throw new UrlDownloadError(
62909
+ classified.kind,
62910
+ classified.retryable,
62911
+ classified.message,
62912
+ classified.status,
62913
+ {
62914
+ ...classified.telemetry,
62915
+ urlFingerprint: identity2.urlFingerprint,
62916
+ initialHost: identity2.host,
62917
+ attempt: attempt + 1
62918
+ },
62919
+ classified.locallyRetryable
62920
+ );
62921
+ }
62907
62922
  if (classified.retryable) onTransientRetry?.(classified);
62908
62923
  const identity = safeDownloadUrlIdentity(url);
62909
62924
  emitDownloadTelemetry(options, {
@@ -72753,6 +72768,47 @@ ${other.raw}`)
72753
72768
  }
72754
72769
  return findings;
72755
72770
  },
72771
+ // gsap_timeline_return_used_as_tween — `tl.to()` returns the TIMELINE, not the tween it just
72772
+ // created. `gsap.to()` returns a Tween, so the two read identically and behave nothing alike.
72773
+ // Capturing the timeline's return and later treating it as an individual animation aims a
72774
+ // tween-scoped call at the whole composition: `.kill()` on it interrupts the master timeline
72775
+ // and detaches it from its parent, which stops a parent-driven seek dead while leaving an
72776
+ // explicit `tl.progress()` still working -- so a render of the packaged defaults looks fine
72777
+ // and only live playback breaks. A rebuild that collected these to discard them also leaves
72778
+ // every previous keyframe in place and stacks the new ones on top.
72779
+ ({ scripts }) => {
72780
+ const findings = [];
72781
+ for (const script of scripts) {
72782
+ const source = stripJsComments(script.content);
72783
+ const timelineVars = collectTimelineVarNames(source);
72784
+ if (timelineVars.length === 0) continue;
72785
+ const receivers = timelineVars.map(escapeRegExp22).join("|");
72786
+ const pattern = new RegExp(
72787
+ String.raw`(?:\.push\s*\(\s*|(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*)(?:${receivers})\s*\.\s*(to|from|fromTo|set|call|add)\s*\(`,
72788
+ "g"
72789
+ );
72790
+ let match;
72791
+ while ((match = pattern.exec(source)) !== null) {
72792
+ const boundName = match[1];
72793
+ const method = match[2];
72794
+ if (boundName) {
72795
+ const treatedAsTween = new RegExp(
72796
+ String.raw`\b${escapeRegExp22(boundName)}\s*\.\s*(?:kill|revert|invalidate|pause|resume|restart|seek|progress|timeScale)\s*\(`
72797
+ );
72798
+ if (!treatedAsTween.test(source)) continue;
72799
+ }
72800
+ const contextStart = Math.max(0, match.index - 40);
72801
+ findings.push({
72802
+ code: "gsap_timeline_return_used_as_tween",
72803
+ severity: "error",
72804
+ message: `\`${match[0].includes(".push") ? "push" : boundName}\` captures the return of \`.${method}()\` on timeline \`${timelineVars[0]}\`, but a timeline's \`.to()\`/\`.from()\`/\`.set()\` returns THE TIMELINE ITSELF, not the tween it created. Every captured value is the same master timeline, so a tween-scoped call on it \u2014 \`.kill()\` above all \u2014 hits the whole composition: it interrupts the timeline and detaches it from its parent, which freezes a parent-driven seek while an explicit \`tl.progress()\` keeps working. Only \`gsap.to()\` returns a tween.`,
72805
+ fixHint: "To build a group of keyframes you can later discard, put them in a nested timeline: `const nested = gsap.timeline(); nested.to(...); tl.add(nested, 0);` \u2014 then `nested.kill()` replaces exactly those keyframes and cannot reach `tl`. Children keep their absolute times when the nest is added at 0. To hold a single real tween, create it with `gsap.to(...)` and place it with `tl.add(tween, at)`.",
72806
+ snippet: truncateSnippet(source.slice(contextStart, match.index + match[0].length + 60))
72807
+ });
72808
+ }
72809
+ }
72810
+ return findings;
72811
+ },
72756
72812
  // gsap_group_selector_keyframes
72757
72813
  ({ scripts }) => {
72758
72814
  const findings = [];
@@ -74940,6 +74996,37 @@ function extractionFrameCountForDuration(durationSeconds, fps, isVFR) {
74940
74996
  function sdrToHdrTransformKey(transfer) {
74941
74997
  return `sdr2hdr-${transfer}`;
74942
74998
  }
74999
+ function safeVideoExtractionSourceIdentity(source) {
75000
+ if (!isHttpUrl(source)) return null;
75001
+ const identity = safeDownloadUrlIdentity(source);
75002
+ return {
75003
+ sourceFingerprint: `sha256:${identity.urlFingerprint}`,
75004
+ host: identity.host ?? "other"
75005
+ };
75006
+ }
75007
+ function downloadStatusClass(error) {
75008
+ const status = error.status ?? error.telemetry?.status;
75009
+ if (typeof status === "number" && status >= 400 && status < 500) return "http_4xx";
75010
+ if (typeof status === "number" && status >= 500 && status < 600) return "http_5xx";
75011
+ if (error.kind === "timeout") return "timeout";
75012
+ if (error.kind === "network") return "network";
75013
+ return "other";
75014
+ }
75015
+ function downloadFailureGroup(source, error) {
75016
+ const sourceIdentity = safeVideoExtractionSourceIdentity(source);
75017
+ const failureHost = error.telemetry?.finalHost ?? error.telemetry?.initialHost;
75018
+ const attempt = error.telemetry?.attempt;
75019
+ return {
75020
+ ...sourceIdentity ? { sourceFingerprint: sourceIdentity.sourceFingerprint } : {},
75021
+ ...failureHost ?? sourceIdentity?.host ? { host: failureHost ?? sourceIdentity?.host } : {},
75022
+ statusClass: downloadStatusClass(error),
75023
+ retry: {
75024
+ phase: "download",
75025
+ used: typeof attempt === "number" && attempt >= 2 ? 1 : 0,
75026
+ budget: 1
75027
+ }
75028
+ };
75029
+ }
74943
75030
  function isVideoSourceExtractionError(error) {
74944
75031
  return typeof error === "object" && error !== null && "hyperframesVideoSourceExtractionError" in error && error.hyperframesVideoSourceExtractionError === true;
74945
75032
  }
@@ -75731,6 +75818,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
75731
75818
  videoId: video.id,
75732
75819
  kind: classified.kind,
75733
75820
  retryable: classified.retryable,
75821
+ ...err instanceof UrlDownloadError ? { group: downloadFailureGroup(video.src, err) } : {},
75734
75822
  error: classified.diagnostic
75735
75823
  });
75736
75824
  }
@@ -80828,6 +80916,7 @@ __export(src_exports, {
80828
80916
  runFfmpeg: () => runFfmpeg,
80829
80917
  runVideoExtractionWithRetry: () => runVideoExtractionWithRetry,
80830
80918
  safeDownloadUrlIdentity: () => safeDownloadUrlIdentity,
80919
+ safeVideoExtractionSourceIdentity: () => safeVideoExtractionSourceIdentity,
80831
80920
  sampleRgb48le: () => sampleRgb48le,
80832
80921
  scaleProtocolTimeoutForComposition: () => scaleProtocolTimeoutForComposition,
80833
80922
  selectVerifySampleIndicesForTask: () => selectVerifySampleIndicesForTask,
@@ -90767,9 +90856,83 @@ function validateRenderDuration(input) {
90767
90856
  init_src();
90768
90857
  import { existsSync as existsSync26 } from "fs";
90769
90858
  import { join as join30 } from "path";
90859
+
90860
+ // ../producer/src/services/render/extractionFailureMetadata.ts
90861
+ function stringOrEmpty(value) {
90862
+ return value === void 0 ? "" : value;
90863
+ }
90864
+ function retrySortTuple(retry) {
90865
+ return retry === void 0 ? ["", -1, -1] : [retry.phase, retry.used, retry.budget];
90866
+ }
90867
+ function extractionFailureGroupSortTuple(group) {
90868
+ const retry = retrySortTuple(group.retry);
90869
+ return [
90870
+ group.kind,
90871
+ stringOrEmpty(group.sourceFingerprint),
90872
+ stringOrEmpty(group.host),
90873
+ stringOrEmpty(group.statusClass),
90874
+ retry[0],
90875
+ retry[1],
90876
+ retry[2]
90877
+ ];
90878
+ }
90879
+ function compareExtractionFailureGroups(left, right) {
90880
+ const leftTuple = extractionFailureGroupSortTuple(left);
90881
+ const rightTuple = extractionFailureGroupSortTuple(right);
90882
+ for (let index = 0; index < leftTuple.length; index += 1) {
90883
+ const leftValue = leftTuple[index];
90884
+ const rightValue = rightTuple[index];
90885
+ if (leftValue < rightValue) return -1;
90886
+ if (leftValue > rightValue) return 1;
90887
+ }
90888
+ return 0;
90889
+ }
90890
+ function extractionFailureGroupIdentityKey(group) {
90891
+ return JSON.stringify(extractionFailureGroupSortTuple(group));
90892
+ }
90893
+
90894
+ // ../producer/src/services/render/stages/extractVideosStage.ts
90770
90895
  function shouldCopyExtractedFrames(platform3) {
90771
90896
  return platform3 === "win32";
90772
90897
  }
90898
+ var MAX_EXTRACTION_FAILURE_GROUPS = 8;
90899
+ function buildExtractionFailureMetadata(inputs) {
90900
+ const kindCounts = /* @__PURE__ */ new Map();
90901
+ const grouped = /* @__PURE__ */ new Map();
90902
+ for (const input of inputs) {
90903
+ kindCounts.set(input.kind, (kindCounts.get(input.kind) ?? 0) + input.affectedElementCount);
90904
+ const key2 = extractionFailureGroupIdentityKey(input);
90905
+ const existing = grouped.get(key2);
90906
+ if (existing) {
90907
+ existing.affectedElementCount += input.affectedElementCount;
90908
+ } else {
90909
+ grouped.set(key2, { ...input });
90910
+ }
90911
+ }
90912
+ const allGroups = [...grouped.values()].sort(compareExtractionFailureGroups);
90913
+ return {
90914
+ schemaVersion: 1,
90915
+ kindCounts: [...kindCounts].map(([kind, affectedElementCount]) => ({
90916
+ kind,
90917
+ affectedElementCount
90918
+ })).sort((a, b) => a.kind < b.kind ? -1 : a.kind > b.kind ? 1 : 0),
90919
+ groups: allGroups.slice(0, MAX_EXTRACTION_FAILURE_GROUPS),
90920
+ omittedGroupCount: Math.max(0, allGroups.length - MAX_EXTRACTION_FAILURE_GROUPS)
90921
+ };
90922
+ }
90923
+ function extractionFailureMetadataFromResult(result) {
90924
+ return buildExtractionFailureMetadata(
90925
+ result.errors.map((failure) => ({
90926
+ kind: failure.kind ?? "internal",
90927
+ affectedElementCount: 1,
90928
+ ...failure.group
90929
+ }))
90930
+ );
90931
+ }
90932
+ function safeVideoExtractionSourceLogMetadata(source) {
90933
+ const identity = safeVideoExtractionSourceIdentity(source);
90934
+ return identity ? { sourceType: "remote", ...identity } : { sourceType: "local" };
90935
+ }
90773
90936
  function resolveVideoExtractionPolicy(env = process.env) {
90774
90937
  const rawMode = env.HF_VIDEO_EXTRACTION_FAILURE_MODE?.trim().toLowerCase();
90775
90938
  const failureMode = rawMode === "observe" || rawMode === "off" ? rawMode : "enforce";
@@ -90777,18 +90940,32 @@ function resolveVideoExtractionPolicy(env = process.env) {
90777
90940
  return { failureMode, maxTransientRetries };
90778
90941
  }
90779
90942
  var VideoExtractionStageError = class extends Error {
90780
- constructor(code, retryable, failures) {
90943
+ constructor(code, retryable, failures, extractionFailure = buildExtractionFailureMetadata(
90944
+ failures.map((failure) => ({
90945
+ kind: failure.kind,
90946
+ affectedElementCount: failure.count
90947
+ }))
90948
+ )) {
90781
90949
  const total = failures.reduce((sum, failure) => sum + failure.count, 0);
90782
90950
  const breakdown = failures.map((failure) => `${failure.kind}=${failure.count}`).join(",");
90783
90951
  super(`Video extraction failed for ${total} source(s) [${code}; ${breakdown}]`);
90784
90952
  this.code = code;
90785
90953
  this.retryable = retryable;
90786
90954
  this.failures = failures;
90955
+ this.extractionFailure = extractionFailure;
90787
90956
  this.name = "VideoExtractionStageError";
90957
+ this.publicMetadata = { extractionFailure };
90788
90958
  }
90789
90959
  code;
90790
90960
  retryable;
90791
90961
  failures;
90962
+ extractionFailure;
90963
+ /**
90964
+ * Producer servers may expose this explicitly public, JSON-compatible data
90965
+ * without knowing its schema. Boundary adapters remain responsible for
90966
+ * validating and applying policy to it.
90967
+ */
90968
+ publicMetadata;
90792
90969
  };
90793
90970
  function throwIfEncoderInterrupted(result) {
90794
90971
  const interrupted = result.errors.find((failure) => failure.kind === "external_interruption");
@@ -90812,7 +90989,8 @@ function buildVideoExtractionStageError(result) {
90812
90989
  return new VideoExtractionStageError(
90813
90990
  retryable ? "VIDEO_EXTRACTION_FAILED" : "VIDEO_SOURCE_UNRENDERABLE",
90814
90991
  retryable,
90815
- failures
90992
+ failures,
90993
+ extractionFailureMetadataFromResult(result)
90816
90994
  );
90817
90995
  }
90818
90996
  function buildHdrProbeStageError(failures) {
@@ -90827,7 +91005,13 @@ function buildHdrProbeStageError(failures) {
90827
91005
  return new VideoExtractionStageError(
90828
91006
  retryable ? "VIDEO_EXTRACTION_FAILED" : "VIDEO_SOURCE_UNRENDERABLE",
90829
91007
  retryable,
90830
- summary
91008
+ summary,
91009
+ buildExtractionFailureMetadata(
91010
+ failures.map((failure) => ({
91011
+ kind: failure.kind,
91012
+ affectedElementCount: 1
91013
+ }))
91014
+ )
90831
91015
  );
90832
91016
  }
90833
91017
  function isHdrProbeFailure(failure) {
@@ -90954,7 +91138,10 @@ async function runExtractVideosStage(input) {
90954
91138
  const totalVideos = composition.videos.length;
90955
91139
  for (let i = 0; i < totalVideos; i++) {
90956
91140
  const v = composition.videos[i];
90957
- log?.info(`Extracting frames from video ${i + 1}/${totalVideos}: ${v.src}`);
91141
+ log?.info(
91142
+ `Extracting frames from video ${i + 1}/${totalVideos}`,
91143
+ safeVideoExtractionSourceLogMetadata(v.src)
91144
+ );
90958
91145
  }
90959
91146
  extractionResult = await extractAllVideoFrames(
90960
91147
  composition.videos,
@@ -96900,10 +97087,12 @@ function extractSafeRenderErrorMetadata(error) {
96900
97087
  if (!errorCode || typeof error !== "object" || error === null) return void 0;
96901
97088
  const owner = "owner" in error ? error.owner : void 0;
96902
97089
  const retryable = "retryable" in error ? error.retryable : void 0;
97090
+ const publicMetadata = "publicMetadata" in error ? error.publicMetadata : void 0;
96903
97091
  return {
96904
97092
  errorCode,
96905
97093
  errorOwner: owner === "user" || owner === "system" ? owner : void 0,
96906
- retryable: typeof retryable === "boolean" ? retryable : void 0
97094
+ retryable: typeof retryable === "boolean" ? retryable : void 0,
97095
+ ...isPlainObject3(publicMetadata) ? { errorMetadata: publicMetadata } : {}
96907
97096
  };
96908
97097
  }
96909
97098
  function parseServerFps(value) {
@@ -97225,6 +97414,7 @@ async function writeRenderStreamFailure(input) {
97225
97414
  errorCode: safeError?.errorCode,
97226
97415
  errorOwner: safeError?.errorOwner,
97227
97416
  retryable: safeError?.retryable,
97417
+ errorMetadata: safeError?.errorMetadata,
97228
97418
  stage: job.currentStage,
97229
97419
  elapsedMs,
97230
97420
  errorDetails: job.errorDetails ?? null,
@@ -97350,6 +97540,7 @@ function createRenderHandlers(options = {}) {
97350
97540
  errorCode: safeError?.errorCode,
97351
97541
  errorOwner: safeError?.errorOwner,
97352
97542
  retryable: safeError?.retryable,
97543
+ errorMetadata: safeError?.errorMetadata,
97353
97544
  stage: job.currentStage,
97354
97545
  durationMs,
97355
97546
  errorDetails: job.errorDetails ?? null
@@ -97707,8 +97898,8 @@ async function runFontLocalize(io, localize) {
97707
97898
  }
97708
97899
 
97709
97900
  // src/version.ts
97710
- var VERSION = true ? "0.8.22" : "0.0.0-dev";
97711
- var PRODUCER_VERSION = true ? "0.8.22" : "0.0.0-dev";
97901
+ var VERSION = true ? "0.8.24" : "0.0.0-dev";
97902
+ var PRODUCER_VERSION = true ? "0.8.24" : "0.0.0-dev";
97712
97903
 
97713
97904
  // src/fontLocalizeCli.ts
97714
97905
  async function readStdin() {
@@ -1,4 +1,4 @@
1
- "use strict";var HyperframesPlayer=(()=>{var ee=Object.defineProperty;var et=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var rt=(r,e)=>{for(var t in e)ee(r,t,{get:e[t],enumerable:!0})},nt=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of tt(e))!it.call(r,n)&&n!==t&&ee(r,n,{get:()=>e[n],enumerable:!(i=et(e,n))||i.enumerable});return r};var ot=r=>nt(ee({},"__esModule",{value:!0}),r);var Ht={};rt(Ht,{HyperframesPlayer:()=>K,SPEED_PRESETS:()=>re,formatSpeed:()=>O,formatTime:()=>q});function we(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function P(r){return typeof r=="object"&&r!==null}function Ae(r){return P(r)&&typeof r.getDuration=="function"}function Ce(r){return P(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}var k="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.22/dist/hyperframe.runtime.iife.js";function N(r){if(r===null)return null;let e=Number.parseInt(r,10);return Number.isFinite(e)&&e>0?e:null}function at(r){let e=r?.querySelector("[data-composition-id][data-width][data-height]")??r?.querySelector("[data-width][data-height]");if(!e)return null;let t=N(e.getAttribute("data-width")),i=N(e.getAttribute("data-height"));return t!==null&&i!==null?{width:t,height:i}:null}var W=class{constructor(e,t){this._iframe=e;this._callbacks=t}_iframe;_callbacks;_interval=null;_runtimeInjected=!1;get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let e=0;this._interval=setInterval(()=>{e++;try{let t=this._iframe.contentWindow;if(!t)return;let i=!!(t.__hf||t.__player),n=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(we({hasRuntime:i,hasTimelines:n,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!i)return;let d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();let s=at(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:s});return}}catch{}e>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{let e=this._iframe.contentWindow;return e?this._resolveDirectTimelineAdapterFromWindow(e):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(e){return this._resolveDirectTimelineAdapterFromWindow(e)}hasRuntimeBridge(e){return Reflect.get(e,"__hf")!==void 0||P(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=k,(e.head||e.documentElement).appendChild(t),this._callbacks.onRuntimeInjected?.()}catch{}}_resolveDirectTimelineAdapterFromWindow(e){if(this.hasRuntimeBridge(e))return null;let t=Reflect.get(e,"__timelines");if(!P(t))return null;let i=Object.keys(t);if(i.length===0)return null;let n=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=n&&n in t?n:i[i.length-1],d=t[o];return Ce(d)?d:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(Ae(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let i=this._resolveDirectTimelineAdapterFromWindow(e);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}};var Re=`
1
+ "use strict";var HyperframesPlayer=(()=>{var ee=Object.defineProperty;var et=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var rt=(r,e)=>{for(var t in e)ee(r,t,{get:e[t],enumerable:!0})},nt=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of tt(e))!it.call(r,n)&&n!==t&&ee(r,n,{get:()=>e[n],enumerable:!(i=et(e,n))||i.enumerable});return r};var ot=r=>nt(ee({},"__esModule",{value:!0}),r);var Ht={};rt(Ht,{HyperframesPlayer:()=>K,SPEED_PRESETS:()=>re,formatSpeed:()=>O,formatTime:()=>q});function we(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function P(r){return typeof r=="object"&&r!==null}function Ae(r){return P(r)&&typeof r.getDuration=="function"}function Ce(r){return P(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}var k="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.24/dist/hyperframe.runtime.iife.js";function N(r){if(r===null)return null;let e=Number.parseInt(r,10);return Number.isFinite(e)&&e>0?e:null}function at(r){let e=r?.querySelector("[data-composition-id][data-width][data-height]")??r?.querySelector("[data-width][data-height]");if(!e)return null;let t=N(e.getAttribute("data-width")),i=N(e.getAttribute("data-height"));return t!==null&&i!==null?{width:t,height:i}:null}var W=class{constructor(e,t){this._iframe=e;this._callbacks=t}_iframe;_callbacks;_interval=null;_runtimeInjected=!1;get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let e=0;this._interval=setInterval(()=>{e++;try{let t=this._iframe.contentWindow;if(!t)return;let i=!!(t.__hf||t.__player),n=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(we({hasRuntime:i,hasTimelines:n,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!i)return;let d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();let s=at(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:s});return}}catch{}e>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{let e=this._iframe.contentWindow;return e?this._resolveDirectTimelineAdapterFromWindow(e):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(e){return this._resolveDirectTimelineAdapterFromWindow(e)}hasRuntimeBridge(e){return Reflect.get(e,"__hf")!==void 0||P(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=k,(e.head||e.documentElement).appendChild(t),this._callbacks.onRuntimeInjected?.()}catch{}}_resolveDirectTimelineAdapterFromWindow(e){if(this.hasRuntimeBridge(e))return null;let t=Reflect.get(e,"__timelines");if(!P(t))return null;let i=Object.keys(t);if(i.length===0)return null;let n=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=n&&n in t?n:i[i.length-1],d=t[o];return Ce(d)?d:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(Ae(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let i=this._resolveDirectTimelineAdapterFromWindow(e);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}};var Re=`
2
2
  :host {
3
3
  display: block;
4
4
  position: relative;
@@ -67,7 +67,7 @@ npx hyperframes check --caption-zone "x0=0;y0=.82;x1=1;y1=1;severity=error;seek=
67
67
  npx hyperframes check --frame-check # media (img/svg/video/canvas) out-of-frame detection
68
68
  ```
69
69
 
70
- `--caption-zone` takes fractional band geometry (`x0/y0/x1/y1` required, 0-1 fractions of the composition's own canvas, portrait included) with optional `severity` and comma-separated `seek` fractions; it flags content whose center sits inside the band. Waive intentional lower-third copy with `data-layout-allow-caption-zone` on the element or its nearest wrapper (see Escape hatches). `--frame-check` reports media elements breaching the canvas beyond `max(120px, 6% of the min canvas dimension)`.
70
+ `--caption-zone` takes fractional band geometry (`x0/y0/x1/y1` required, 0-1 fractions of the composition's own canvas, portrait included) with optional `severity` and comma-separated `seek` fractions; it flags a text element's DOM box (`getBoundingClientRect`) that overlaps the band. Waive intentional lower-third copy with `data-layout-allow-caption-zone` on the element or its nearest wrapper (see Escape hatches). `--frame-check` reports media elements breaching the canvas beyond `max(120px, 6% of the min canvas dimension)`.
71
71
 
72
72
  **Fixing contrast errors** — thresholds are 4.5:1 for normal text, 3:1 for large text (24px+, or 19px+ bold). The finding's `suggestedColor` already picks the nearest compliant color in the right direction (brighten on dark backgrounds, darken on light); apply it or adjust within the palette family, then re-run `check`.
73
73
 
@@ -1,4 +1,4 @@
1
- var ve=Object.defineProperty;var be=(n,i,e)=>i in n?ve(n,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[i]=e;var u=(n,i,e)=>be(n,typeof i!="symbol"?i+"":i,e);import{r as le,i as we,a as Ae}from"./index-BIf0zQNt.js";function Ee(n){return n.hasRuntime||n.runtimeInjected?!1:!!(n.hasNestedCompositions||n.hasTimelines&&n.attempts>=5)}function V(n){return typeof n=="object"&&n!==null}function Ce(n){return V(n)&&typeof n.getDuration=="function"}function Te(n){return V(n)&&typeof n.duration=="function"&&typeof n.time=="function"&&typeof n.seek=="function"&&typeof n.play=="function"&&typeof n.pause=="function"}function Se(n){if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(n))throw new Error(`Invalid HyperFrames runtime version: ${n}`);return`https://cdn.jsdelivr.net/npm/@hyperframes/core@${n}/dist/hyperframe.runtime.iife.js`}const H=typeof __HYPERFRAMES_RUNTIME_CDN_URL__=="string"?__HYPERFRAMES_RUNTIME_CDN_URL__:Se("0.0.0-dev");function $(n){if(n===null)return null;const i=Number.parseInt(n,10);return Number.isFinite(i)&&i>0?i:null}function Re(n){const i=(n==null?void 0:n.querySelector("[data-composition-id][data-width][data-height]"))??(n==null?void 0:n.querySelector("[data-width][data-height]"));if(!i)return null;const e=$(i.getAttribute("data-width")),t=$(i.getAttribute("data-height"));return e!==null&&t!==null?{width:e,height:t}:null}class xe{constructor(i,e){u(this,"_interval",null);u(this,"_runtimeInjected",!1);this._iframe=i,this._callbacks=e}get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let i=0;this._interval=setInterval(()=>{var e;i++;try{const t=this._iframe.contentWindow;if(!t)return;const r=!!(t.__hf||t.__player),s=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!((e=this._iframe.contentDocument)!=null&&e.querySelector("[data-composition-src]"));if(Ee({hasRuntime:r,hasTimelines:s,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:i})){this._injectRuntime();return}if(this._runtimeInjected&&!r)return;const d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();const p=Re(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:p});return}}catch{}i>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{const i=this._iframe.contentWindow;return i?this._resolveDirectTimelineAdapterFromWindow(i):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(i){return this._resolveDirectTimelineAdapterFromWindow(i)}hasRuntimeBridge(i){return Reflect.get(i,"__hf")!==void 0||V(Reflect.get(i,"__player"))}_injectRuntime(){var i,e;this._runtimeInjected=!0;try{const t=this._iframe.contentDocument;if(!t)return;const r=t.createElement("script");r.src=H,(t.head||t.documentElement).appendChild(r),(e=(i=this._callbacks).onRuntimeInjected)==null||e.call(i)}catch{}}_resolveDirectTimelineAdapterFromWindow(i){var d,p;if(this.hasRuntimeBridge(i))return null;const e=Reflect.get(i,"__timelines");if(!V(e))return null;const t=Object.keys(e);if(t.length===0)return null;const r=(p=(d=this._iframe.contentDocument)==null?void 0:d.querySelector("[data-composition-id]"))==null?void 0:p.getAttribute("data-composition-id"),s=r&&r in e?r:t[t.length-1],o=e[s];return Te(o)?o:null}_resolvePlaybackDurationAdapter(i){const e=Reflect.get(i,"__player");if(Ce(e))return{kind:"runtime",getDuration:()=>e.getDuration()};const t=this._resolveDirectTimelineAdapterFromWindow(i);return t?{kind:"direct-timeline",timeline:t,getDuration:()=>t.duration()}:null}}const Me=`
1
+ var ve=Object.defineProperty;var be=(n,i,e)=>i in n?ve(n,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[i]=e;var u=(n,i,e)=>be(n,typeof i!="symbol"?i+"":i,e);import{r as le,i as we,a as Ae}from"./index-Bq3M0sjr.js";function Ee(n){return n.hasRuntime||n.runtimeInjected?!1:!!(n.hasNestedCompositions||n.hasTimelines&&n.attempts>=5)}function V(n){return typeof n=="object"&&n!==null}function Ce(n){return V(n)&&typeof n.getDuration=="function"}function Te(n){return V(n)&&typeof n.duration=="function"&&typeof n.time=="function"&&typeof n.seek=="function"&&typeof n.play=="function"&&typeof n.pause=="function"}function Se(n){if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(n))throw new Error(`Invalid HyperFrames runtime version: ${n}`);return`https://cdn.jsdelivr.net/npm/@hyperframes/core@${n}/dist/hyperframe.runtime.iife.js`}const H=typeof __HYPERFRAMES_RUNTIME_CDN_URL__=="string"?__HYPERFRAMES_RUNTIME_CDN_URL__:Se("0.0.0-dev");function $(n){if(n===null)return null;const i=Number.parseInt(n,10);return Number.isFinite(i)&&i>0?i:null}function Re(n){const i=(n==null?void 0:n.querySelector("[data-composition-id][data-width][data-height]"))??(n==null?void 0:n.querySelector("[data-width][data-height]"));if(!i)return null;const e=$(i.getAttribute("data-width")),t=$(i.getAttribute("data-height"));return e!==null&&t!==null?{width:e,height:t}:null}class xe{constructor(i,e){u(this,"_interval",null);u(this,"_runtimeInjected",!1);this._iframe=i,this._callbacks=e}get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let i=0;this._interval=setInterval(()=>{var e;i++;try{const t=this._iframe.contentWindow;if(!t)return;const r=!!(t.__hf||t.__player),s=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!((e=this._iframe.contentDocument)!=null&&e.querySelector("[data-composition-src]"));if(Ee({hasRuntime:r,hasTimelines:s,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:i})){this._injectRuntime();return}if(this._runtimeInjected&&!r)return;const d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();const p=Re(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:p});return}}catch{}i>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{const i=this._iframe.contentWindow;return i?this._resolveDirectTimelineAdapterFromWindow(i):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(i){return this._resolveDirectTimelineAdapterFromWindow(i)}hasRuntimeBridge(i){return Reflect.get(i,"__hf")!==void 0||V(Reflect.get(i,"__player"))}_injectRuntime(){var i,e;this._runtimeInjected=!0;try{const t=this._iframe.contentDocument;if(!t)return;const r=t.createElement("script");r.src=H,(t.head||t.documentElement).appendChild(r),(e=(i=this._callbacks).onRuntimeInjected)==null||e.call(i)}catch{}}_resolveDirectTimelineAdapterFromWindow(i){var d,p;if(this.hasRuntimeBridge(i))return null;const e=Reflect.get(i,"__timelines");if(!V(e))return null;const t=Object.keys(e);if(t.length===0)return null;const r=(p=(d=this._iframe.contentDocument)==null?void 0:d.querySelector("[data-composition-id]"))==null?void 0:p.getAttribute("data-composition-id"),s=r&&r in e?r:t[t.length-1],o=e[s];return Te(o)?o:null}_resolvePlaybackDurationAdapter(i){const e=Reflect.get(i,"__player");if(Ce(e))return{kind:"runtime",getDuration:()=>e.getDuration()};const t=this._resolveDirectTimelineAdapterFromWindow(i);return t?{kind:"direct-timeline",timeline:t,getDuration:()=>t.duration()}:null}}const Me=`
2
2
  :host {
3
3
  display: block;
4
4
  position: relative;
@@ -1 +1 @@
1
- import{g as P}from"./index-BIf0zQNt.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};
1
+ import{g as P}from"./index-Bq3M0sjr.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};