hyperframes 0.7.108 → 0.7.110

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/cli.js CHANGED
@@ -50,7 +50,7 @@ var VERSION;
50
50
  var init_version = __esm({
51
51
  "src/version.ts"() {
52
52
  "use strict";
53
- VERSION = true ? "0.7.108" : "0.0.0-dev";
53
+ VERSION = true ? "0.7.110" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -71028,6 +71028,53 @@ var init_ffprobe = __esm({
71028
71028
  }
71029
71029
  });
71030
71030
 
71031
+ // ../engine/src/utils/renderProvenance.ts
71032
+ import { createRequire } from "module";
71033
+ function readEngineVersion() {
71034
+ try {
71035
+ const version2 = createRequire(import.meta.url)("../../package.json").version;
71036
+ return typeof version2 === "string" && version2.length > 0 ? version2 : UNKNOWN_VERSION;
71037
+ } catch {
71038
+ return UNKNOWN_VERSION;
71039
+ }
71040
+ }
71041
+ function isMovFamilyContainer(outputPath) {
71042
+ const lower3 = outputPath.toLowerCase();
71043
+ return lower3.endsWith(".mp4") || lower3.endsWith(".mov") || lower3.endsWith(".m4v");
71044
+ }
71045
+ function renderProvenanceArgs(outputPath) {
71046
+ const args = [
71047
+ "-metadata",
71048
+ `${PROVENANCE_RENDERER_TAG}=${PROVENANCE_RENDERER_NAME}`,
71049
+ "-metadata",
71050
+ `${PROVENANCE_VERSION_TAG}=${PROVENANCE_VERSION}`
71051
+ ];
71052
+ if (isMovFamilyContainer(outputPath)) {
71053
+ args.push("-movflags", "+use_metadata_tags");
71054
+ }
71055
+ return args;
71056
+ }
71057
+ function appendRenderProvenanceArgs(args, outputPath) {
71058
+ args.push(...renderProvenanceArgs(outputPath));
71059
+ }
71060
+ function readRenderProvenance(tags) {
71061
+ const renderer = readTagCI(tags, PROVENANCE_RENDERER_TAG);
71062
+ if (renderer === "") return null;
71063
+ return { renderer, version: readTagCI(tags, PROVENANCE_VERSION_TAG) };
71064
+ }
71065
+ var PROVENANCE_RENDERER_TAG, PROVENANCE_VERSION_TAG, PROVENANCE_RENDERER_NAME, UNKNOWN_VERSION, PROVENANCE_VERSION;
71066
+ var init_renderProvenance = __esm({
71067
+ "../engine/src/utils/renderProvenance.ts"() {
71068
+ "use strict";
71069
+ init_ffprobe();
71070
+ PROVENANCE_RENDERER_TAG = "hyperframes_renderer";
71071
+ PROVENANCE_VERSION_TAG = "hyperframes_version";
71072
+ PROVENANCE_RENDERER_NAME = "hyperframes";
71073
+ UNKNOWN_VERSION = "0.0.0-dev";
71074
+ PROVENANCE_VERSION = readEngineVersion();
71075
+ }
71076
+ });
71077
+
71031
71078
  // ../engine/src/services/chunkEncoder.ts
71032
71079
  import { copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readdirSync as readdirSync2, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
71033
71080
  import { join as join8, dirname as dirname4, extname } from "path";
@@ -71210,6 +71257,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
71210
71257
  } else if (codec === "prores") {
71211
71258
  args.push("-c:v", "prores_ks", "-profile:v", preset2, "-vendor", "apl0");
71212
71259
  args.push("-pix_fmt", pixelFormat);
71260
+ appendRenderProvenanceArgs(args, outputPath);
71213
71261
  return [...args, "-y", outputPath];
71214
71262
  }
71215
71263
  if (codec === "h264" || codec === "h265") {
@@ -71262,6 +71310,7 @@ function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = null) {
71262
71310
  args.push("-pix_fmt", pixelFormat);
71263
71311
  }
71264
71312
  args.push("-avoid_negative_ts", "make_zero");
71313
+ appendRenderProvenanceArgs(args, outputPath);
71265
71314
  args.push("-y", outputPath);
71266
71315
  return args;
71267
71316
  }
@@ -71395,18 +71444,9 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
71395
71444
  const concatListPath = join8(chunkDir, "concat-list.txt");
71396
71445
  const concatInput = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
71397
71446
  writeFileSync3(concatListPath, concatInput, "utf-8");
71398
- const concatArgs = [
71399
- "-f",
71400
- "concat",
71401
- "-safe",
71402
- "0",
71403
- "-i",
71404
- concatListPath,
71405
- "-c",
71406
- "copy",
71407
- "-y",
71408
- outputPath
71409
- ];
71447
+ const concatArgs = ["-f", "concat", "-safe", "0", "-i", concatListPath, "-c", "copy"];
71448
+ appendRenderProvenanceArgs(concatArgs, outputPath);
71449
+ concatArgs.push("-y", outputPath);
71410
71450
  const encodeTimeout = config?.ffmpegEncodeTimeout ?? DEFAULT_CONFIG2.ffmpegEncodeTimeout;
71411
71451
  const concatProcessResult = await runFfmpeg(concatArgs, { signal, timeout: encodeTimeout });
71412
71452
  const concatResult = {
@@ -71460,6 +71500,7 @@ async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, confi
71460
71500
  }
71461
71501
  const copiesContainerizedAac = !isWebm && shouldCopyAudio && config?.preserveAudioPrimingEditList === true;
71462
71502
  if (!copiesContainerizedAac) args.push("-avoid_negative_ts", "make_zero");
71503
+ appendRenderProvenanceArgs(args, outputPath);
71463
71504
  if (fps !== void 0) {
71464
71505
  args.push("-r", fpsToFfmpegArg(fps));
71465
71506
  }
@@ -71487,6 +71528,7 @@ async function applyFaststart(inputPath, outputPath, signal, config, fps) {
71487
71528
  return { success: true, outputPath, durationMs: 0 };
71488
71529
  }
71489
71530
  const args = ["-i", inputPath, "-c", "copy", "-movflags", "+faststart"];
71531
+ appendRenderProvenanceArgs(args, outputPath);
71490
71532
  if (fps !== void 0) {
71491
71533
  args.push("-r", fpsToFfmpegArg(fps));
71492
71534
  }
@@ -71520,6 +71562,7 @@ var init_chunkEncoder = __esm({
71520
71562
  init_ffprobe();
71521
71563
  init_dist3();
71522
71564
  init_vp9Options();
71565
+ init_renderProvenance();
71523
71566
  init_gpuEncoder();
71524
71567
  ENCODER_PRESETS = {
71525
71568
  draft: { preset: "ultrafast", quality: 28, codec: "h264" },
@@ -71720,6 +71763,7 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
71720
71763
  } else if (codec === "prores") {
71721
71764
  args.push("-c:v", "prores_ks", "-profile:v", preset2, "-vendor", "apl0");
71722
71765
  args.push("-pix_fmt", pixelFormat);
71766
+ appendRenderProvenanceArgs(args, outputPath);
71723
71767
  return [...args, "-y", outputPath];
71724
71768
  }
71725
71769
  if (codec === "h264" || codec === "h265") {
@@ -71772,6 +71816,7 @@ function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
71772
71816
  args.push("-pix_fmt", pixelFormat);
71773
71817
  }
71774
71818
  args.push("-avoid_negative_ts", "make_zero");
71819
+ appendRenderProvenanceArgs(args, outputPath);
71775
71820
  args.push("-y", outputPath);
71776
71821
  return args;
71777
71822
  }
@@ -71900,6 +71945,7 @@ var init_streamingEncoder = __esm({
71900
71945
  init_config2();
71901
71946
  init_dist3();
71902
71947
  init_vp9Options();
71948
+ init_renderProvenance();
71903
71949
  }
71904
71950
  });
71905
71951
 
@@ -91800,6 +91846,10 @@ __export(src_exports, {
91800
91846
  ManagedChildProcess: () => ManagedChildProcess,
91801
91847
  NOT_MEDIA_PAYLOAD: () => NOT_MEDIA_PAYLOAD,
91802
91848
  NotMediaPayloadError: () => NotMediaPayloadError,
91849
+ PROVENANCE_RENDERER_NAME: () => PROVENANCE_RENDERER_NAME,
91850
+ PROVENANCE_RENDERER_TAG: () => PROVENANCE_RENDERER_TAG,
91851
+ PROVENANCE_VERSION: () => PROVENANCE_VERSION,
91852
+ PROVENANCE_VERSION_TAG: () => PROVENANCE_VERSION_TAG,
91803
91853
  SwiftShaderAssertionError: () => SwiftShaderAssertionError,
91804
91854
  TRANSITIONS: () => TRANSITIONS,
91805
91855
  VIDEO_FRAME_FORMATS: () => VIDEO_FRAME_FORMATS,
@@ -91808,6 +91858,7 @@ __export(src_exports, {
91808
91858
  analyzeClipMediaFit: () => analyzeClipMediaFit,
91809
91859
  analyzeCompositionHdr: () => analyzeCompositionHdr,
91810
91860
  analyzeKeyframeIntervals: () => analyzeKeyframeIntervals,
91861
+ appendRenderProvenanceArgs: () => appendRenderProvenanceArgs,
91811
91862
  applyConcreteGpuScreenshotClamp: () => applyConcreteGpuScreenshotClamp,
91812
91863
  applyDomLayerMask: () => applyDomLayerMask,
91813
91864
  applyFaststart: () => applyFaststart,
@@ -91926,11 +91977,13 @@ __export(src_exports, {
91926
91977
  quantizeTimeToFrame: () => quantizeTimeToFrame,
91927
91978
  queryElementStacking: () => queryElementStacking,
91928
91979
  queryVideoElementBounds: () => queryVideoElementBounds,
91980
+ readRenderProvenance: () => readRenderProvenance,
91929
91981
  readWebGlVendorInfo: () => readWebGlVendorInfo,
91930
91982
  readWebGlVendorInfoFromCanvas: () => readWebGlVendorInfoFromCanvas,
91931
91983
  recaptureDrawElementFrameForVerify: () => recaptureDrawElementFrameForVerify,
91932
91984
  releaseBrowser: () => releaseBrowser,
91933
91985
  removeDomLayerMask: () => removeDomLayerMask,
91986
+ renderProvenanceArgs: () => renderProvenanceArgs,
91934
91987
  resampleRgb48leObjectFit: () => resampleRgb48leObjectFit,
91935
91988
  resolveBrowserGpuMode: () => resolveBrowserGpuMode,
91936
91989
  resolveConfig: () => resolveConfig,
@@ -92001,6 +92054,7 @@ var init_src = __esm({
92001
92054
  init_screenshotService();
92002
92055
  init_videoFrameInjector();
92003
92056
  init_hdr();
92057
+ init_renderProvenance();
92004
92058
  }
92005
92059
  });
92006
92060
 
@@ -95395,16 +95449,19 @@ function cachePath(baseUrl, key2) {
95395
95449
  const slug = baseUrl.replace(/[^a-zA-Z0-9]/g, "_");
95396
95450
  return join19(CACHE_DIR, `${slug}__${key2}.json`);
95397
95451
  }
95398
- function readCache(path2) {
95452
+ function readCacheEntry(path2) {
95399
95453
  try {
95400
95454
  const entry = JSON.parse(readFileSync12(path2, "utf-8"));
95401
95455
  if (typeof entry.fetchedAt !== "number") return void 0;
95402
- if (Date.now() - entry.fetchedAt > CACHE_TTL_MS) return void 0;
95403
- return entry.data;
95456
+ if (entry.data === void 0 || entry.data === null) return void 0;
95457
+ return entry;
95404
95458
  } catch {
95405
95459
  return void 0;
95406
95460
  }
95407
95461
  }
95462
+ function isFresh(entry) {
95463
+ return Date.now() - entry.fetchedAt <= CACHE_TTL_MS;
95464
+ }
95408
95465
  function writeCache(path2, data2) {
95409
95466
  try {
95410
95467
  mkdirSync10(dirname10(path2), { recursive: true });
@@ -95422,27 +95479,30 @@ async function fetchJson(url) {
95422
95479
  }
95423
95480
  async function fetchRegistryManifest(baseUrl = DEFAULT_REGISTRY_URL, options) {
95424
95481
  const cacheFile = cachePath(baseUrl, "registry");
95425
- if (!options?.skipCache) {
95426
- const cached2 = readCache(cacheFile);
95427
- if (cached2) return cached2;
95428
- }
95482
+ const cached2 = readCacheEntry(cacheFile);
95483
+ if (!options?.skipCache && cached2 && isFresh(cached2)) return cached2.data;
95429
95484
  try {
95430
95485
  const manifest = await fetchJson(`${baseUrl}/registry.json`);
95431
95486
  writeCache(cacheFile, manifest);
95432
95487
  return manifest;
95433
95488
  } catch {
95434
- return void 0;
95489
+ return cached2?.data;
95435
95490
  }
95436
95491
  }
95437
95492
  async function fetchItemManifest(name, type, baseUrl = DEFAULT_REGISTRY_URL) {
95438
95493
  const dir = ITEM_TYPE_DIRS[type];
95439
95494
  const cacheFile = cachePath(baseUrl, `${dir}__${name}`);
95440
- const cached2 = readCache(cacheFile);
95441
- if (cached2) return cached2;
95495
+ const cached2 = readCacheEntry(cacheFile);
95496
+ if (cached2 && isFresh(cached2)) return cached2.data;
95442
95497
  const url = `${baseUrl}/${dir}/${name}/registry-item.json`;
95443
- const item = await fetchJson(url);
95444
- writeCache(cacheFile, item);
95445
- return item;
95498
+ try {
95499
+ const item = await fetchJson(url);
95500
+ writeCache(cacheFile, item);
95501
+ return item;
95502
+ } catch (err) {
95503
+ if (cached2) return cached2.data;
95504
+ throw err;
95505
+ }
95446
95506
  }
95447
95507
  async function fetchItemFile(item, file, destPath, baseUrl = DEFAULT_REGISTRY_URL) {
95448
95508
  if (/(^|[/\\])\.\.([/\\]|$)/.test(file.path)) {
@@ -100583,7 +100643,7 @@ var init_hfIds = __esm({
100583
100643
  }
100584
100644
  });
100585
100645
 
100586
- // ../studio-server/dist/chunk-Q7LK72M7.js
100646
+ // ../studio-server/dist/chunk-XVPRRS7M.js
100587
100647
  import postcss3 from "postcss";
100588
100648
  function parseStyleDecls(style) {
100589
100649
  const props = /* @__PURE__ */ new Map();
@@ -100873,7 +100933,7 @@ function splitElementInHtml(source, target, splitTime, newId, fallbackTiming) {
100873
100933
  clone2.removeAttribute("data-hf-id");
100874
100934
  for (const node of clone2.querySelectorAll("[data-hf-id]")) node.removeAttribute("data-hf-id");
100875
100935
  setElementDuration(clone2, splitTime, secondDuration);
100876
- const playbackStartAttr = el.hasAttribute("data-playback-start") ? "data-playback-start" : el.hasAttribute("data-media-start") ? "data-media-start" : fallbackTiming?.stampPlaybackStart ? "data-playback-start" : null;
100936
+ const playbackStartAttr = el.hasAttribute("data-playback-start") ? "data-playback-start" : el.hasAttribute("data-media-start") ? "data-media-start" : fallbackTiming?.stampPlaybackStart ? "data-playback-start" : el.matches("audio, video") ? "data-media-start" : null;
100877
100937
  if (playbackStartAttr) {
100878
100938
  const currentTrim = parseFloat(el.getAttribute(playbackStartAttr) ?? "") || fallbackTiming?.playbackStart || 0;
100879
100939
  const rateRaw = parseFloat(el.getAttribute("data-playback-rate") ?? "");
@@ -101025,8 +101085,8 @@ function unwrapElementsFromHtml(source, groupTarget) {
101025
101085
  };
101026
101086
  }
101027
101087
  var import_postcss_selector_parser2;
101028
- var init_chunk_Q7LK72M7 = __esm({
101029
- "../studio-server/dist/chunk-Q7LK72M7.js"() {
101088
+ var init_chunk_XVPRRS7M = __esm({
101089
+ "../studio-server/dist/chunk-XVPRRS7M.js"() {
101030
101090
  "use strict";
101031
101091
  init_esm10();
101032
101092
  import_postcss_selector_parser2 = __toESM(require_dist(), 1);
@@ -112875,7 +112935,7 @@ var init_dist9 = __esm({
112875
112935
  "../studio-server/dist/index.js"() {
112876
112936
  "use strict";
112877
112937
  init_chunk_X62ASOGO();
112878
- init_chunk_Q7LK72M7();
112938
+ init_chunk_XVPRRS7M();
112879
112939
  init_chunk_W2SBTCO2();
112880
112940
  init_chunk_LHYV3WLZ();
112881
112941
  init_chunk_ZPI6QXJH();
@@ -123900,7 +123960,18 @@ var init_extractVideosStage = __esm({
123900
123960
  // ../producer/src/services/render/stages/audioStage.ts
123901
123961
  import { join as join49 } from "path";
123902
123962
  async function runAudioStage(input2) {
123903
- const { projectDir, workDir, compiledDir, duration, audios, abortSignal, assertNotAborted, log: log2 } = input2;
123963
+ const {
123964
+ projectDir,
123965
+ workDir,
123966
+ compiledDir,
123967
+ duration,
123968
+ ffmpegProcessTimeout,
123969
+ audioGain,
123970
+ audios,
123971
+ abortSignal,
123972
+ assertNotAborted,
123973
+ log: log2
123974
+ } = input2;
123904
123975
  const stage3Start = Date.now();
123905
123976
  const audioOutputPath = join49(workDir, MIXED_AUDIO_FILENAME);
123906
123977
  let hasAudio = false;
@@ -123916,7 +123987,7 @@ async function runAudioStage(input2) {
123916
123987
  audioOutputPath,
123917
123988
  duration,
123918
123989
  abortSignal,
123919
- void 0,
123990
+ { ffmpegProcessTimeout, audioGain },
123920
123991
  compiledDir
123921
123992
  );
123922
123993
  } catch (err) {
@@ -125995,7 +126066,7 @@ var init_captureHdrSequentialLoop = __esm({
125995
126066
  import { Worker as Worker2 } from "worker_threads";
125996
126067
  import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL2 } from "url";
125997
126068
  import { dirname as dirname23, join as join55 } from "path";
125998
- import { createRequire } from "module";
126069
+ import { createRequire as createRequire2 } from "module";
125999
126070
  import { existsSync as existsSync53 } from "fs";
126000
126071
  import { cpus as cpus3 } from "os";
126001
126072
  function resolveWorkerEntry(explicit) {
@@ -126021,7 +126092,7 @@ function buildExecArgv(entryIsTs) {
126021
126092
  );
126022
126093
  if (hasLoader) return inherited;
126023
126094
  try {
126024
- const require3 = createRequire(import.meta.url);
126095
+ const require3 = createRequire2(import.meta.url);
126025
126096
  const tsxEsm = require3.resolve("tsx/esm");
126026
126097
  inherited.push("--import", pathToFileURL2(tsxEsm).href);
126027
126098
  } catch {
@@ -128323,6 +128394,8 @@ async function executeRenderPipeline(input2) {
128323
128394
  workDir,
128324
128395
  compiledDir,
128325
128396
  duration: probeResult.duration,
128397
+ ffmpegProcessTimeout: cfg.ffmpegProcessTimeout,
128398
+ audioGain: cfg.audioGain,
128326
128399
  audios: composition.audios,
128327
128400
  abortSignal: executionSignal,
128328
128401
  assertNotAborted,
@@ -131878,6 +131951,8 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
131878
131951
  workDir,
131879
131952
  compiledDir,
131880
131953
  duration: job.duration,
131954
+ ffmpegProcessTimeout: cfg.ffmpegProcessTimeout,
131955
+ audioGain: cfg.audioGain,
131881
131956
  audios: composition.audios,
131882
131957
  abortSignal,
131883
131958
  assertNotAborted
@@ -132963,7 +133038,9 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
132963
133038
  den: plan2.dimensions.fpsDen
132964
133039
  });
132965
133040
  if (chunkPaths.length === 1) {
132966
- const remuxArgs = ["-i", chunkPaths[0], "-c", "copy", "-r", fpsArg, "-y", concatOutputPath];
133041
+ const remuxArgs = ["-i", chunkPaths[0], "-c", "copy", "-r", fpsArg];
133042
+ appendRenderProvenanceArgs(remuxArgs, concatOutputPath);
133043
+ remuxArgs.push("-y", concatOutputPath);
132967
133044
  const remuxResult = await runFfmpeg(remuxArgs, { signal: abortSignal });
132968
133045
  if (!remuxResult.success) {
132969
133046
  throw new Error(
@@ -132985,10 +133062,10 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
132985
133062
  "-i",
132986
133063
  concatListPath,
132987
133064
  "-c",
132988
- "copy",
132989
- "-y",
132990
- concatOutputPath
133065
+ "copy"
132991
133066
  ];
133067
+ appendRenderProvenanceArgs(concatArgs, concatOutputPath);
133068
+ concatArgs.push("-y", concatOutputPath);
132992
133069
  const concatResult = await runFfmpeg(concatArgs, { signal: abortSignal });
132993
133070
  if (!concatResult.success) {
132994
133071
  throw new Error(
@@ -133028,10 +133105,10 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
133028
133105
  "-fps_mode",
133029
133106
  "cfr",
133030
133107
  "-r",
133031
- fpsArg,
133032
- "-y",
133033
- cfrOutputPath
133108
+ fpsArg
133034
133109
  ];
133110
+ appendRenderProvenanceArgs(cfrArgs, cfrOutputPath);
133111
+ cfrArgs.push("-y", cfrOutputPath);
133035
133112
  const cfrResult = await runFfmpeg(cfrArgs, { signal: abortSignal });
133036
133113
  if (!cfrResult.success) {
133037
133114
  throw new Error(
@@ -134258,6 +134335,7 @@ function buildEncoderArgs2(format, width, height, fps, outputPath, quality = DEF
134258
134335
  "-metadata:s:v:0",
134259
134336
  "alpha_mode=1",
134260
134337
  "-an",
134338
+ ...renderProvenanceArgs(outputPath),
134261
134339
  outputPath
134262
134340
  ];
134263
134341
  }
@@ -134273,6 +134351,7 @@ function buildEncoderArgs2(format, width, height, fps, outputPath, quality = DEF
134273
134351
  "-pix_fmt",
134274
134352
  "yuva444p10le",
134275
134353
  "-an",
134354
+ ...renderProvenanceArgs(outputPath),
134276
134355
  outputPath
134277
134356
  ];
134278
134357
  }
@@ -135190,7 +135269,7 @@ import {
135190
135269
  } from "fs";
135191
135270
  import { resolve as resolve39, dirname as dirname33, basename as basename12, join as join79 } from "path";
135192
135271
  import { fileURLToPath as fileURLToPath8 } from "url";
135193
- import { createRequire as createRequire2 } from "module";
135272
+ import { createRequire as createRequire3 } from "module";
135194
135273
  function previewBaseUrl(port, host = "127.0.0.1") {
135195
135274
  return `http://${host}:${port}`;
135196
135275
  }
@@ -135594,7 +135673,7 @@ async function runDevMode(dir, options) {
135594
135673
  }
135595
135674
  function hasLocalStudio(dir) {
135596
135675
  try {
135597
- const req = createRequire2(join79(dir, "package.json"));
135676
+ const req = createRequire3(join79(dir, "package.json"));
135598
135677
  req.resolve("@hyperframes/studio/package.json");
135599
135678
  return true;
135600
135679
  } catch {
@@ -135602,7 +135681,7 @@ function hasLocalStudio(dir) {
135602
135681
  }
135603
135682
  }
135604
135683
  async function runLocalStudioMode(dir, options) {
135605
- const req = createRequire2(join79(dir, "package.json"));
135684
+ const req = createRequire3(join79(dir, "package.json"));
135606
135685
  const studioPkgPath = dirname33(req.resolve("@hyperframes/studio/package.json"));
135607
135686
  const pName = options?.projectName ?? basename12(dir);
135608
135687
  const projectsDir = join79(studioPkgPath, "data", "projects");
@@ -137792,7 +137871,8 @@ __export(catalog_exports, {
137792
137871
  countUnindexed: () => countUnindexed,
137793
137872
  default: () => catalog_default,
137794
137873
  examples: () => examples5,
137795
- pickByName: () => pickByName
137874
+ pickByName: () => pickByName,
137875
+ searchMissCommand: () => searchMissCommand
137796
137876
  });
137797
137877
  import { resolve as resolve43 } from "path";
137798
137878
  async function prepareOnDeviceTier(opts) {
@@ -137903,6 +137983,10 @@ function tierToken(searched) {
137903
137983
  function tierDetail(searched) {
137904
137984
  return searched?.localMode === "local-model" ? "on-device meaning search" : "local word match";
137905
137985
  }
137986
+ function searchMissCommand(query2, tier) {
137987
+ const quoted = query2.replace(/(["\\$`])/g, "\\$1");
137988
+ return `npx hyperframes feedback --search-miss "${quoted}" --wanted "<the move you needed>" --tier ${tier}`;
137989
+ }
137906
137990
  function reportLocalModelOption(json) {
137907
137991
  if (!json && process.stdout.isTTY) return;
137908
137992
  if (localModelStatus().status !== "not-asked") return;
@@ -138049,6 +138133,7 @@ var init_catalog = __esm({
138049
138133
  shown: 0,
138050
138134
  total: tagged.length,
138051
138135
  ...warnings.length ? { warnings } : {},
138136
+ report_gap: searchMissCommand(query2, tierToken(searched)),
138052
138137
  results: []
138053
138138
  },
138054
138139
  null,
@@ -138062,6 +138147,11 @@ var init_catalog = __esm({
138062
138147
  args.tag ? `tag "${args.tag}"` : null
138063
138148
  ].filter(Boolean);
138064
138149
  console.log(`No items match ${criteria.join(" and ")}.`);
138150
+ if (query2) {
138151
+ console.log("");
138152
+ console.log(c.dim(" Nothing in the catalog does this? Report the gap:"));
138153
+ console.log(c.dim(` ${searchMissCommand(query2, tierToken(searched))}`));
138154
+ }
138065
138155
  }
138066
138156
  if (query2) await offerLocalModel(0, json, config.registry, artifactRevision);
138067
138157
  return;
@@ -138092,6 +138182,12 @@ var init_catalog = __esm({
138092
138182
  shown: output.length,
138093
138183
  total: tagged.length,
138094
138184
  ...warnings.length ? { warnings } : {},
138185
+ // Carried on hits too, not just on zero results. The gaps that
138186
+ // actually get reported are the ones where the search returned
138187
+ // plausible items and none of them did the thing — a judgement
138188
+ // only the reader can make, so the command has to already be in
138189
+ // the envelope by the time they make it.
138190
+ report_gap: searchMissCommand(query2, tierToken(searched)),
138095
138191
  results: output
138096
138192
  },
138097
138193
  null,
@@ -138118,6 +138214,11 @@ var init_catalog = __esm({
138118
138214
  await offerLocalModel(matching.length, json, config.registry, artifactRevision);
138119
138215
  }
138120
138216
  }
138217
+ if (query2) {
138218
+ console.log(
138219
+ c.dim(` None of these do it? ${searchMissCommand(query2, tierToken(searched))}`)
138220
+ );
138221
+ }
138121
138222
  }
138122
138223
  if (interactive) {
138123
138224
  const options = matching.map((item) => ({
@@ -147984,7 +148085,7 @@ var init_beats = __esm({
147984
148085
 
147985
148086
  // src/beats/headlessAnalyzer.ts
147986
148087
  import { existsSync as existsSync89, readFileSync as readFileSync61 } from "fs";
147987
- import { createRequire as createRequire3 } from "module";
148088
+ import { createRequire as createRequire4 } from "module";
147988
148089
  import { dirname as dirname44, join as join97 } from "path";
147989
148090
  import { fileURLToPath as fileURLToPath13 } from "url";
147990
148091
  function findPrebuiltBundle() {
@@ -148092,7 +148193,7 @@ var require2, bundlePromise, MAX_AUDIO_BYTES;
148092
148193
  var init_headlessAnalyzer = __esm({
148093
148194
  "src/beats/headlessAnalyzer.ts"() {
148094
148195
  "use strict";
148095
- require2 = createRequire3(import.meta.url);
148196
+ require2 = createRequire4(import.meta.url);
148096
148197
  bundlePromise = null;
148097
148198
  MAX_AUDIO_BYTES = 80 * 1024 * 1024;
148098
148199
  }
@@ -194887,7 +194988,7 @@ ${c.error("\u2717")} Snapshot failed: ${msg}`);
194887
194988
  var init_sourceMutation = __esm({
194888
194989
  "../studio-server/dist/helpers/sourceMutation.js"() {
194889
194990
  "use strict";
194890
- init_chunk_Q7LK72M7();
194991
+ init_chunk_XVPRRS7M();
194891
194992
  }
194892
194993
  });
194893
194994
 
@@ -1,4 +1,4 @@
1
- "use strict";var HyperframesPlayer=(()=>{var J=Object.defineProperty;var Ye=Object.getOwnPropertyDescriptor;var Xe=Object.getOwnPropertyNames;var Ze=Object.prototype.hasOwnProperty;var Qe=(i,e)=>{for(var t in e)J(i,t,{get:e[t],enumerable:!0})},Je=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Xe(e))!Ze.call(i,n)&&n!==t&&J(i,n,{get:()=>e[n],enumerable:!(r=Ye(e,n))||r.enumerable});return i};var Ke=i=>Je(J({},"__esModule",{value:!0}),i);var Lt={};Qe(Lt,{HyperframesPlayer:()=>Q,SPEED_PRESETS:()=>te,formatSpeed:()=>N,formatTime:()=>$});function ye(i){return i.hasRuntime||i.runtimeInjected?!1:!!(i.hasNestedCompositions||i.hasTimelines&&i.attempts>=5)}function I(i){return typeof i=="object"&&i!==null}function Ee(i){return I(i)&&typeof i.getDuration=="function"}function Se(i){return I(i)&&typeof i.duration=="function"&&typeof i.time=="function"&&typeof i.seek=="function"&&typeof i.play=="function"&&typeof i.pause=="function"}var et="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.7.108/dist/hyperframe.runtime.iife.js";function D(i){if(i===null)return null;let e=Number.parseInt(i,10);return Number.isFinite(e)&&e>0?e:null}function tt(i){let e=i?.querySelector("[data-composition-id][data-width][data-height]")??i?.querySelector("[data-width][data-height]");if(!e)return null;let t=D(e.getAttribute("data-width")),r=D(e.getAttribute("data-height"));return t!==null&&r!==null?{width:t,height:r}:null}var j=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 r=!!(t.__hf||t.__player),n=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(ye({hasRuntime:r,hasTimelines:n,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!r)return;let s=this._resolvePlaybackDurationAdapter(t);if(s&&s.getDuration()>0){this.stop();let l=tt(this._iframe.contentDocument);this._callbacks.onReady({duration:s.getDuration(),adapter:s,compositionSize:l});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||I(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=et,(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(!I(t))return null;let r=Object.keys(t);if(r.length===0)return null;let n=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=n&&n in t?n:r[r.length-1],s=t[o];return Se(s)?s:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(Ee(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let r=this._resolveDirectTimelineAdapterFromWindow(e);return r?{kind:"direct-timeline",timeline:r,getDuration:()=>r.duration()}:null}};var Te=`
1
+ "use strict";var HyperframesPlayer=(()=>{var J=Object.defineProperty;var Ye=Object.getOwnPropertyDescriptor;var Xe=Object.getOwnPropertyNames;var Ze=Object.prototype.hasOwnProperty;var Qe=(i,e)=>{for(var t in e)J(i,t,{get:e[t],enumerable:!0})},Je=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Xe(e))!Ze.call(i,n)&&n!==t&&J(i,n,{get:()=>e[n],enumerable:!(r=Ye(e,n))||r.enumerable});return i};var Ke=i=>Je(J({},"__esModule",{value:!0}),i);var Lt={};Qe(Lt,{HyperframesPlayer:()=>Q,SPEED_PRESETS:()=>te,formatSpeed:()=>N,formatTime:()=>$});function ye(i){return i.hasRuntime||i.runtimeInjected?!1:!!(i.hasNestedCompositions||i.hasTimelines&&i.attempts>=5)}function I(i){return typeof i=="object"&&i!==null}function Ee(i){return I(i)&&typeof i.getDuration=="function"}function Se(i){return I(i)&&typeof i.duration=="function"&&typeof i.time=="function"&&typeof i.seek=="function"&&typeof i.play=="function"&&typeof i.pause=="function"}var et="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.7.110/dist/hyperframe.runtime.iife.js";function D(i){if(i===null)return null;let e=Number.parseInt(i,10);return Number.isFinite(e)&&e>0?e:null}function tt(i){let e=i?.querySelector("[data-composition-id][data-width][data-height]")??i?.querySelector("[data-width][data-height]");if(!e)return null;let t=D(e.getAttribute("data-width")),r=D(e.getAttribute("data-height"));return t!==null&&r!==null?{width:t,height:r}:null}var j=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 r=!!(t.__hf||t.__player),n=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(ye({hasRuntime:r,hasTimelines:n,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!r)return;let s=this._resolvePlaybackDurationAdapter(t);if(s&&s.getDuration()>0){this.stop();let l=tt(this._iframe.contentDocument);this._callbacks.onReady({duration:s.getDuration(),adapter:s,compositionSize:l});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||I(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=et,(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(!I(t))return null;let r=Object.keys(t);if(r.length===0)return null;let n=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=n&&n in t?n:r[r.length-1],s=t[o];return Se(s)?s:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(Ee(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let r=this._resolveDirectTimelineAdapterFromWindow(e);return r?{kind:"direct-timeline",timeline:r,getDuration:()=>r.duration()}:null}};var Te=`
2
2
  :host {
3
3
  display: block;
4
4
  position: relative;
@@ -65,7 +65,7 @@ Treat tiny unstyled content, canvas-sized icons, missing hero elements, or timel
65
65
  - **Search the catalog before writing motion by hand.** `npx hyperframes catalog --query "<the beat, in plain language>"`. Search is entirely local: there is no hosted tier, no account, and the query text is never sent anywhere. By default it ranks on vocabulary shared with the item's name, title and description, which misses any phrasing that does not reuse the catalog's own wording. Add `--on-device` to rank by meaning instead (see the offline tier below).
66
66
  - **Read which tier answered; never infer it from results appearing.** With `--json` the envelope carries `query`, `tier` (`on-device` or `words`), `tier_detail`, `dropped`, `unindexed`, `shown`, `total` and `results`, plus `top_score` when the answering tier produces one and `warnings` when a tier was asked for and could not run. A weak result on `words` is expected; the same result on `on-device` is a bug. `top_score` is on-device only and has no threshold behind it: the ranker returns the whole catalog in some order for every query, so read it as evidence rather than as a pass or fail.
67
67
  - **`dropped` and `unindexed` are opposite skews between the registry and the on-device index, and rewording the query fixes neither.** `dropped` counts ranked names this registry cannot install, so the strongest matches are the ones being lost. `unindexed` counts registry moves the index cannot see at all, which no query can ever return. Refreshing the registry is not the answer to either: its manifest carries a 24h TTL and heals itself, while the vectors are a separately published artifact fetched into `~/.hyperframes/catalog/`. Re-running with `--on-device` refetches that index when `unindexed` is above zero, so that is the remedy to hand the user. A pure over-coverage skew (`dropped` above zero while `unindexed` is zero) does not trigger the refetch; clearing `~/.hyperframes/catalog/` is the only way out of that one. Both counts are of names rather than of results, so either can exceed `total`.
68
- - **When meaning search comes back with nothing worth installing, say so.** `npx hyperframes feedback --search-miss "<the query you ran>" --wanted "<the move you needed>" --tier on-device`. This is the only path that sends a query anywhere, and it is a separate deliberate command precisely so plain `catalog --query` keeps its promise of sending nothing. Report the miss when the on-device tier answered and the top hits still do not do the thing; a weak result on the `words` tier is expected and is not worth reporting. What comes back is a list of moves the catalog does not have yet, read directly rather than guessed from install counts, so the phrasing that matters is the effect you wanted, not the item name you imagined. It carries no rating and never lands in the rating metric.
68
+ - **When a search comes back with nothing worth installing, say so.** `npx hyperframes feedback --search-miss "<the query you ran>" --wanted "<the move you needed>" --tier <the tier that answered>`. You do not have to assemble that line: `catalog --query` prints it pre-filled, and every `--json` search envelope carries it as `report_gap` with the query and tier already correct — fill in `--wanted` and send. This is the only path that sends a query anywhere, and it is a separate deliberate command precisely so plain `catalog --query` keeps its promise of sending nothing. **Report on either tier**, whenever the results do not do the thing; do not hold out for the on-device tier, which needs a consented 33 MB download and is therefore off in most agent runs — waiting for it means never reporting at all. The tier rides along in the report, so a vocabulary miss stays distinguishable from a meaning miss without you having to judge which one you hit. What comes back is a list of moves the catalog does not have yet, read directly rather than guessed from install counts, so the phrasing that matters is the effect you wanted, not the item name you imagined. It carries no rating and never lands in the rating metric.
69
69
  - **Offer the offline tier; never enable it silently.** A one-time ~33 MB download (a quantized ONNX build of `bge-small-en-v1.5` plus its tokenizer, pinned to a fixed revision) and the catalog vectors from the registry, both cached under `~/.hyperframes/`, neither added to the project or any package. Once cached it ranks by meaning with nothing sent. Say the size out loud and let the person decide, then pass `--on-device` (with `-y` to skip the prompt) once they agree. The interactive offer only fires on a TTY, and under `--json` nothing about it is printed at all, so in an agent run you have to raise it with the user yourself.
70
70
 
71
71
  - Prefer `--json` for agent and CI calls. Server-mode `render`, `preview`, and `play` do not provide ordinary JSON output; `preview --selection --json` and `preview --context --json` are query-mode exceptions.
@@ -141,6 +141,15 @@ The specialized commands are deliberately documented by their owning workflows:
141
141
  npx hyperframes present <project-dir> --port 3004 --no-open
142
142
  npx hyperframes beats <project-dir> --json
143
143
  npx hyperframes keyframes <project-dir> --json
144
+ npx hyperframes media-treatment --capabilities
145
+ npx hyperframes figma asset KEY:10-20
144
146
  ```
145
147
 
146
- `present` serves a navigable deck with presenter and audience synchronization. `beats` is the standalone Studio beat-grid utility defined in `references/beats.md`. `keyframes` surfaces seek-safe animation and motion-path diagnostics.
148
+ `present` serves a navigable deck with presenter and audience synchronization. `beats` is the standalone Studio beat-grid utility defined in `references/beats.md`. `keyframes` surfaces seek-safe animation and motion-path diagnostics. `media-treatment` discovers, applies, and clears deterministic looks on local footage — start with `--capabilities` for the overview and `--capability <name>` for one family; `/media-use` owns which treatment a brief is asking for. `figma` imports over the REST API with the `asset`, `tokens`, and `component` subcommands and needs `FIGMA_TOKEN`; motion and shader import have no REST endpoint and are agent-only, so `/figma` owns those.
149
+
150
+ ## Commands you should not run
151
+
152
+ Two entries in `hyperframes --help` are not part of the authoring loop, and reaching for them wastes a turn:
153
+
154
+ - `events` is the telemetry endpoint skills use to report their **own** invocation, ideally from a bundled script. It emits an anonymous event and exits 0 no matter what you pass it. It is not a way to read telemetry back, and an agent has no reason to call it by hand.
155
+ - `validate`, `inspect`, and `layout` are deprecated aliases kept for old scripts. `check` is the one that is maintained, and it is what every reference in this skill assumes.
@@ -1,4 +1,4 @@
1
- var me=Object.defineProperty;var fe=(r,t,e)=>t in r?me(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var c=(r,t,e)=>fe(r,typeof t!="symbol"?t+"":t,e);import{r as ne,i as _e,a as ge}from"./index-GqONLcOl.js";function ye(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function F(r){return typeof r=="object"&&r!==null}function ve(r){return F(r)&&typeof r.getDuration=="function"}function be(r){return F(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}function we(r){if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(r))throw new Error(`Invalid HyperFrames runtime version: ${r}`);return`https://cdn.jsdelivr.net/npm/@hyperframes/core@${r}/dist/hyperframe.runtime.iife.js`}const Ae=typeof __HYPERFRAMES_RUNTIME_CDN_URL__=="string"?__HYPERFRAMES_RUNTIME_CDN_URL__:we("0.0.0-dev");function H(r){if(r===null)return null;const t=Number.parseInt(r,10);return Number.isFinite(t)&&t>0?t:null}function Ee(r){const t=(r==null?void 0:r.querySelector("[data-composition-id][data-width][data-height]"))??(r==null?void 0:r.querySelector("[data-width][data-height]"));if(!t)return null;const e=H(t.getAttribute("data-width")),i=H(t.getAttribute("data-height"));return e!==null&&i!==null?{width:e,height:i}:null}class Ce{constructor(t,e){c(this,"_interval",null);c(this,"_runtimeInjected",!1);this._iframe=t,this._callbacks=e}get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let t=0;this._interval=setInterval(()=>{var e;t++;try{const i=this._iframe.contentWindow;if(!i)return;const s=!!(i.__hf||i.__player),o=!!(i.__timelines&&Object.keys(i.__timelines).length>0),d=!!((e=this._iframe.contentDocument)!=null&&e.querySelector("[data-composition-src]"));if(ye({hasRuntime:s,hasTimelines:o,hasNestedCompositions:d,runtimeInjected:this._runtimeInjected,attempts:t})){this._injectRuntime();return}if(this._runtimeInjected&&!s)return;const a=this._resolvePlaybackDurationAdapter(i);if(a&&a.getDuration()>0){this.stop();const h=Ee(this._iframe.contentDocument);this._callbacks.onReady({duration:a.getDuration(),adapter:a,compositionSize:h});return}}catch{}t>=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 t=this._iframe.contentWindow;return t?this._resolveDirectTimelineAdapterFromWindow(t):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(t){return this._resolveDirectTimelineAdapterFromWindow(t)}hasRuntimeBridge(t){return Reflect.get(t,"__hf")!==void 0||F(Reflect.get(t,"__player"))}_injectRuntime(){var t,e;this._runtimeInjected=!0;try{const i=this._iframe.contentDocument;if(!i)return;const s=i.createElement("script");s.src=Ae,(i.head||i.documentElement).appendChild(s),(e=(t=this._callbacks).onRuntimeInjected)==null||e.call(t)}catch{}}_resolveDirectTimelineAdapterFromWindow(t){var a,h;if(this.hasRuntimeBridge(t))return null;const e=Reflect.get(t,"__timelines");if(!F(e))return null;const i=Object.keys(e);if(i.length===0)return null;const s=(h=(a=this._iframe.contentDocument)==null?void 0:a.querySelector("[data-composition-id]"))==null?void 0:h.getAttribute("data-composition-id"),o=s&&s in e?s:i[i.length-1],d=e[o];return be(d)?d:null}_resolvePlaybackDurationAdapter(t){const e=Reflect.get(t,"__player");if(ve(e))return{kind:"runtime",getDuration:()=>e.getDuration()};const i=this._resolveDirectTimelineAdapterFromWindow(t);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}}const Te=`
1
+ var me=Object.defineProperty;var fe=(r,t,e)=>t in r?me(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var c=(r,t,e)=>fe(r,typeof t!="symbol"?t+"":t,e);import{r as ne,i as _e,a as ge}from"./index-f54_Hm8v.js";function ye(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function F(r){return typeof r=="object"&&r!==null}function ve(r){return F(r)&&typeof r.getDuration=="function"}function be(r){return F(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}function we(r){if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(r))throw new Error(`Invalid HyperFrames runtime version: ${r}`);return`https://cdn.jsdelivr.net/npm/@hyperframes/core@${r}/dist/hyperframe.runtime.iife.js`}const Ae=typeof __HYPERFRAMES_RUNTIME_CDN_URL__=="string"?__HYPERFRAMES_RUNTIME_CDN_URL__:we("0.0.0-dev");function H(r){if(r===null)return null;const t=Number.parseInt(r,10);return Number.isFinite(t)&&t>0?t:null}function Ee(r){const t=(r==null?void 0:r.querySelector("[data-composition-id][data-width][data-height]"))??(r==null?void 0:r.querySelector("[data-width][data-height]"));if(!t)return null;const e=H(t.getAttribute("data-width")),i=H(t.getAttribute("data-height"));return e!==null&&i!==null?{width:e,height:i}:null}class Ce{constructor(t,e){c(this,"_interval",null);c(this,"_runtimeInjected",!1);this._iframe=t,this._callbacks=e}get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let t=0;this._interval=setInterval(()=>{var e;t++;try{const i=this._iframe.contentWindow;if(!i)return;const s=!!(i.__hf||i.__player),o=!!(i.__timelines&&Object.keys(i.__timelines).length>0),d=!!((e=this._iframe.contentDocument)!=null&&e.querySelector("[data-composition-src]"));if(ye({hasRuntime:s,hasTimelines:o,hasNestedCompositions:d,runtimeInjected:this._runtimeInjected,attempts:t})){this._injectRuntime();return}if(this._runtimeInjected&&!s)return;const a=this._resolvePlaybackDurationAdapter(i);if(a&&a.getDuration()>0){this.stop();const h=Ee(this._iframe.contentDocument);this._callbacks.onReady({duration:a.getDuration(),adapter:a,compositionSize:h});return}}catch{}t>=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 t=this._iframe.contentWindow;return t?this._resolveDirectTimelineAdapterFromWindow(t):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(t){return this._resolveDirectTimelineAdapterFromWindow(t)}hasRuntimeBridge(t){return Reflect.get(t,"__hf")!==void 0||F(Reflect.get(t,"__player"))}_injectRuntime(){var t,e;this._runtimeInjected=!0;try{const i=this._iframe.contentDocument;if(!i)return;const s=i.createElement("script");s.src=Ae,(i.head||i.documentElement).appendChild(s),(e=(t=this._callbacks).onRuntimeInjected)==null||e.call(t)}catch{}}_resolveDirectTimelineAdapterFromWindow(t){var a,h;if(this.hasRuntimeBridge(t))return null;const e=Reflect.get(t,"__timelines");if(!F(e))return null;const i=Object.keys(e);if(i.length===0)return null;const s=(h=(a=this._iframe.contentDocument)==null?void 0:a.querySelector("[data-composition-id]"))==null?void 0:h.getAttribute("data-composition-id"),o=s&&s in e?s:i[i.length-1],d=e[o];return be(d)?d:null}_resolvePlaybackDurationAdapter(t){const e=Reflect.get(t,"__player");if(ve(e))return{kind:"runtime",getDuration:()=>e.getDuration()};const i=this._resolveDirectTimelineAdapterFromWindow(t);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}}const Te=`
2
2
  :host {
3
3
  display: block;
4
4
  position: relative;