hyperframes 0.6.7 → 0.6.8

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
@@ -54,7 +54,7 @@ var VERSION;
54
54
  var init_version = __esm({
55
55
  "src/version.ts"() {
56
56
  "use strict";
57
- VERSION = true ? "0.6.7" : "0.0.0-dev";
57
+ VERSION = true ? "0.6.8" : "0.0.0-dev";
58
58
  }
59
59
  });
60
60
 
@@ -4563,8 +4563,13 @@ function compileTag(tag, isVideo2, generateId) {
4563
4563
  id = `${isVideo2 ? "hf-video" : "hf-audio"}-${generateId()}`;
4564
4564
  result = injectAttr(result, "id", id);
4565
4565
  }
4566
- const startStr = getAttr(result, "data-start");
4567
- const start = startStr !== null ? parseFloat(startStr) : 0;
4566
+ let startStr = getAttr(result, "data-start");
4567
+ if (startStr === null) {
4568
+ result = injectAttr(result, "data-start", "0");
4569
+ result = injectAttr(result, "data-hf-auto-start", "");
4570
+ startStr = "0";
4571
+ }
4572
+ const start = parseFloat(startStr);
4568
4573
  const mediaStartStr = getAttr(result, "data-media-start");
4569
4574
  const mediaStart = mediaStartStr ? parseFloat(mediaStartStr) : 0;
4570
4575
  if (!hasAttr(result, "data-end")) {
@@ -11433,7 +11438,7 @@ import { get as httpsGet } from "https";
11433
11438
  import { pipeline } from "stream/promises";
11434
11439
  function downloadFile(url, dest) {
11435
11440
  const tmp = `${dest}.tmp`;
11436
- return new Promise((resolve42, reject) => {
11441
+ return new Promise((resolve43, reject) => {
11437
11442
  const follow = (u) => {
11438
11443
  httpsGet(u, (res) => {
11439
11444
  if (res.statusCode === 301 || res.statusCode === 302) {
@@ -11450,7 +11455,7 @@ function downloadFile(url, dest) {
11450
11455
  const file = createWriteStream(tmp);
11451
11456
  pipeline(res, file).then(() => {
11452
11457
  renameSync(tmp, dest);
11453
- resolve42();
11458
+ resolve43();
11454
11459
  }).catch((err) => {
11455
11460
  try {
11456
11461
  unlinkSync(tmp);
@@ -12175,7 +12180,7 @@ function hasNpx() {
12175
12180
  }
12176
12181
  }
12177
12182
  function runSkillsAdd(repo) {
12178
- return new Promise((resolve42, reject) => {
12183
+ return new Promise((resolve43, reject) => {
12179
12184
  const child = spawn("npx", ["skills", "add", repo, "--all"], {
12180
12185
  stdio: "inherit",
12181
12186
  timeout: 12e4,
@@ -12189,7 +12194,7 @@ function runSkillsAdd(repo) {
12189
12194
  env: { ...process.env, GIT_CLONE_PROTECTION_ACTIVE: "0" }
12190
12195
  });
12191
12196
  child.on("close", (code, signal) => {
12192
- if (code === 0) resolve42();
12197
+ if (code === 0) resolve43();
12193
12198
  else if (signal === "SIGINT" || code === 130) process.exit(0);
12194
12199
  else reject(new Error(`npx skills add exited with code ${code}`));
12195
12200
  });
@@ -13073,7 +13078,7 @@ function computePeaks(floats, count) {
13073
13078
  return peaks.map((p2) => p2 / maxPeak);
13074
13079
  }
13075
13080
  function decodeAudioPeaks(audioPath) {
13076
- return new Promise((resolve42, reject) => {
13081
+ return new Promise((resolve43, reject) => {
13077
13082
  const proc = spawn2(
13078
13083
  "ffmpeg",
13079
13084
  [
@@ -13106,7 +13111,7 @@ function decodeAudioPeaks(audioPath) {
13106
13111
  return;
13107
13112
  }
13108
13113
  const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + numSamples * 4);
13109
- resolve42(computePeaks(new Float32Array(ab), PEAK_COUNT));
13114
+ resolve43(computePeaks(new Float32Array(ab), PEAK_COUNT));
13110
13115
  });
13111
13116
  proc.on("error", reject);
13112
13117
  });
@@ -17046,8 +17051,8 @@ var init_custom_element_registry = __esm({
17046
17051
  } : (element) => element.localName === localName;
17047
17052
  registry.set(localName, { Class, check });
17048
17053
  if (waiting.has(localName)) {
17049
- for (const resolve42 of waiting.get(localName))
17050
- resolve42(Class);
17054
+ for (const resolve43 of waiting.get(localName))
17055
+ resolve43(Class);
17051
17056
  waiting.delete(localName);
17052
17057
  }
17053
17058
  ownerDocument.querySelectorAll(
@@ -17087,13 +17092,13 @@ var init_custom_element_registry = __esm({
17087
17092
  */
17088
17093
  whenDefined(localName) {
17089
17094
  const { registry, waiting } = this;
17090
- return new Promise((resolve42) => {
17095
+ return new Promise((resolve43) => {
17091
17096
  if (registry.has(localName))
17092
- resolve42(registry.get(localName).Class);
17097
+ resolve43(registry.get(localName).Class);
17093
17098
  else {
17094
17099
  if (!waiting.has(localName))
17095
17100
  waiting.set(localName, []);
17096
- waiting.get(localName).push(resolve42);
17101
+ waiting.get(localName).push(resolve43);
17097
17102
  }
17098
17103
  });
17099
17104
  }
@@ -22799,12 +22804,12 @@ var require_CSSValueExpression = __commonJS({
22799
22804
  return false;
22800
22805
  }
22801
22806
  };
22802
- CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep6) {
22803
- var endIdx = this._findMatchedIdx(token, idx, sep6), text;
22807
+ CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep7) {
22808
+ var endIdx = this._findMatchedIdx(token, idx, sep7), text;
22804
22809
  if (endIdx === -1) {
22805
22810
  return false;
22806
22811
  } else {
22807
- text = token.substring(idx, endIdx + sep6.length);
22812
+ text = token.substring(idx, endIdx + sep7.length);
22808
22813
  return {
22809
22814
  idx: endIdx,
22810
22815
  text
@@ -22844,15 +22849,15 @@ var require_CSSValueExpression = __commonJS({
22844
22849
  if (!isLegal) {
22845
22850
  return false;
22846
22851
  } else {
22847
- var sep6 = "/";
22848
- return this._parseJSString(token, idx, sep6);
22852
+ var sep7 = "/";
22853
+ return this._parseJSString(token, idx, sep7);
22849
22854
  }
22850
22855
  };
22851
- CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep6) {
22856
+ CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep7) {
22852
22857
  var startIdx = idx, endIdx;
22853
22858
  var NOT_FOUND = -1;
22854
22859
  while (true) {
22855
- endIdx = token.indexOf(sep6, startIdx + 1);
22860
+ endIdx = token.indexOf(sep7, startIdx + 1);
22856
22861
  if (endIdx === -1) {
22857
22862
  endIdx = NOT_FOUND;
22858
22863
  break;
@@ -26987,7 +26992,7 @@ var init_lint2 = __esm({
26987
26992
  // ../core/src/studio-api/routes/render.ts
26988
26993
  import { streamSSE } from "hono/streaming";
26989
26994
  import { existsSync as existsSync13, readFileSync as readFileSync15, mkdirSync as mkdirSync7, unlinkSync as unlinkSync4, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
26990
- import { join as join17 } from "path";
26995
+ import { join as join17, resolve as resolve12, sep as sep2 } from "path";
26991
26996
  function registerRenderRoutes(api, adapter2) {
26992
26997
  const renderJobs = /* @__PURE__ */ new Map();
26993
26998
  const TTL_MS = 3e5;
@@ -27025,6 +27030,14 @@ function registerRenderRoutes(api, adapter2) {
27025
27030
  const fps = fpsParse && fpsParse.ok ? fpsParse.value : { num: 30, den: 1 };
27026
27031
  const quality = ["draft", "standard", "high"].includes(body.quality ?? "") ? body.quality : "standard";
27027
27032
  const outputResolution = VALID_RESOLUTIONS.has(body.resolution ?? "") ? body.resolution : void 0;
27033
+ let composition;
27034
+ if (typeof body.composition === "string" && body.composition.length > 0) {
27035
+ const resolved = resolve12(project.dir, body.composition);
27036
+ if (!resolved.startsWith(resolve12(project.dir) + sep2)) {
27037
+ return c3.json({ error: "composition path must be within the project directory" }, 400);
27038
+ }
27039
+ composition = body.composition;
27040
+ }
27028
27041
  const now = /* @__PURE__ */ new Date();
27029
27042
  const datePart = now.toISOString().slice(0, 10);
27030
27043
  const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
@@ -27040,7 +27053,8 @@ function registerRenderRoutes(api, adapter2) {
27040
27053
  fps,
27041
27054
  quality,
27042
27055
  jobId,
27043
- outputResolution
27056
+ outputResolution,
27057
+ composition
27044
27058
  });
27045
27059
  jobState.createdAt = Date.now();
27046
27060
  renderJobs.set(jobId, jobState);
@@ -27215,8 +27229,10 @@ function studioPositionSeekReapplyRuntime() {
27215
27229
  const ROTATION_ATTR = "data-hf-studio-rotation";
27216
27230
  const ORIGINAL_TRANSLATE_ATTR = "data-hf-studio-original-translate";
27217
27231
  const ORIGINAL_ROTATE_ATTR = "data-hf-studio-original-rotate";
27232
+ const MOTION_ATTR = "data-hf-studio-motion";
27233
+ const MOTION_TL_KEY = "studio-motion";
27218
27234
  const WRAPPED_PROP = "__hfStudioPositionSeekReapplyWrapped";
27219
- if (!document.querySelector("[" + PATH_OFFSET_ATTR + '="true"]') && !document.querySelector("[" + ROTATION_ATTR + '="true"]'))
27235
+ if (!document.querySelector("[" + PATH_OFFSET_ATTR + '="true"]') && !document.querySelector("[" + ROTATION_ATTR + '="true"]') && !document.querySelector("[" + MOTION_ATTR + "]"))
27220
27236
  return;
27221
27237
  const splitTopLevelWhitespace = (value) => {
27222
27238
  const parts = [];
@@ -27252,6 +27268,84 @@ function studioPositionSeekReapplyRuntime() {
27252
27268
  if (!original || original === "none" || !isSimpleRotateAngle(original)) return rotationValue;
27253
27269
  return "calc(" + original + " + " + rotationValue + ")";
27254
27270
  };
27271
+ let lastSeekTime = 0;
27272
+ let cachedMotionKey = "";
27273
+ const finiteNum = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? v2 : null;
27274
+ const computeMotionKey = (motionEls) => {
27275
+ let key2 = "";
27276
+ for (let i2 = 0; i2 < motionEls.length; i2++) {
27277
+ const json = motionEls[i2].getAttribute?.(MOTION_ATTR);
27278
+ if (json) key2 += (key2 ? "\n" : "") + json;
27279
+ }
27280
+ return key2;
27281
+ };
27282
+ const reapplyMotionTimeline = () => {
27283
+ const motionEls = document.querySelectorAll("[" + MOTION_ATTR + "]");
27284
+ if (motionEls.length === 0) {
27285
+ cachedMotionKey = "";
27286
+ return;
27287
+ }
27288
+ const win = window;
27289
+ const gsap = win.gsap;
27290
+ if (!gsap || typeof gsap.timeline !== "function") return;
27291
+ win.__timelines = win.__timelines || {};
27292
+ const motionKey = computeMotionKey(motionEls);
27293
+ const existing = win.__timelines[MOTION_TL_KEY];
27294
+ if (motionKey && motionKey === cachedMotionKey && existing && typeof existing.totalTime === "function") {
27295
+ existing.totalTime(lastSeekTime, false);
27296
+ return;
27297
+ }
27298
+ if (existing && typeof existing.kill === "function") existing.kill();
27299
+ const tl = gsap.timeline({ paused: true, defaults: { overwrite: "auto" } });
27300
+ const fromTo = tl.fromTo;
27301
+ if (typeof fromTo !== "function") return;
27302
+ let applied = 0;
27303
+ for (let i2 = 0; i2 < motionEls.length; i2++) {
27304
+ const el = motionEls[i2];
27305
+ if (!(el instanceof HTMLElement)) continue;
27306
+ const json = el.getAttribute(MOTION_ATTR);
27307
+ if (!json) continue;
27308
+ try {
27309
+ const m2 = JSON.parse(json);
27310
+ const start = finiteNum(m2.start);
27311
+ const duration = finiteNum(m2.duration);
27312
+ if (start == null || duration == null || duration <= 0) continue;
27313
+ const ease = typeof m2.ease === "string" ? m2.ease : "none";
27314
+ const from = m2.from && typeof m2.from === "object" ? m2.from : {};
27315
+ const to = m2.to && typeof m2.to === "object" ? m2.to : {};
27316
+ const customEase = m2.customEase;
27317
+ let resolvedEase = ease;
27318
+ if (customEase?.id && customEase?.data && win.CustomEase?.create) {
27319
+ try {
27320
+ gsap.registerPlugin?.(win.CustomEase);
27321
+ win.CustomEase.create(customEase.id, customEase.data);
27322
+ resolvedEase = customEase.id;
27323
+ } catch {
27324
+ }
27325
+ }
27326
+ fromTo.call(
27327
+ tl,
27328
+ el,
27329
+ { ...from },
27330
+ { ...to, duration, ease: resolvedEase, overwrite: "auto", immediateRender: false },
27331
+ start
27332
+ );
27333
+ applied += 1;
27334
+ } catch {
27335
+ }
27336
+ }
27337
+ if (applied === 0) {
27338
+ cachedMotionKey = "";
27339
+ if (typeof tl.kill === "function")
27340
+ tl.kill();
27341
+ return;
27342
+ }
27343
+ cachedMotionKey = motionKey;
27344
+ win.__timelines[MOTION_TL_KEY] = tl;
27345
+ if (typeof tl.pause === "function") tl.pause();
27346
+ if (typeof tl.totalTime === "function")
27347
+ tl.totalTime(lastSeekTime, false);
27348
+ };
27255
27349
  const reapplyAll = () => {
27256
27350
  const offsetEls = document.querySelectorAll("[" + PATH_OFFSET_ATTR + '="true"]');
27257
27351
  for (let i2 = 0; i2 < offsetEls.length; i2++) {
@@ -27279,6 +27373,7 @@ function studioPositionSeekReapplyRuntime() {
27279
27373
  el.style.setProperty("rotate", composeRotation(el, "var(" + ROTATION_PROP + ", 0deg)"));
27280
27374
  }
27281
27375
  }
27376
+ reapplyMotionTimeline();
27282
27377
  };
27283
27378
  const runtimeWindow = window;
27284
27379
  const isWrapped = (fn) => Boolean(fn[WRAPPED_PROP]);
@@ -27305,6 +27400,7 @@ function studioPositionSeekReapplyRuntime() {
27305
27400
  return true;
27306
27401
  }
27307
27402
  const wrapped = function(time) {
27403
+ lastSeekTime = typeof time === "number" && Number.isFinite(time) ? Math.max(0, time) : 0;
27308
27404
  const result = seek.call(this, time);
27309
27405
  reapplyAll();
27310
27406
  return result;
@@ -28159,6 +28255,10 @@ function findFromEnv2() {
28159
28255
  return void 0;
28160
28256
  }
28161
28257
  async function findFromCache() {
28258
+ const fromPuppeteer = findFromPuppeteerCache();
28259
+ if (fromPuppeteer) {
28260
+ return fromPuppeteer;
28261
+ }
28162
28262
  if (existsSync17(CACHE_DIR2)) {
28163
28263
  const installed = await getInstalledBrowsers({ cacheDir: CACHE_DIR2 });
28164
28264
  const match = installed.find((b2) => b2.browser === Browser.CHROMEHEADLESSSHELL);
@@ -28166,17 +28266,41 @@ async function findFromCache() {
28166
28266
  return { executablePath: match.executablePath, source: "cache" };
28167
28267
  }
28168
28268
  }
28169
- const fromPuppeteer = findFromPuppeteerCache();
28170
- if (fromPuppeteer) {
28171
- return fromPuppeteer;
28172
- }
28173
28269
  return void 0;
28174
28270
  }
28271
+ function parseVersionSegments(versionDir) {
28272
+ const dashIdx = versionDir.indexOf("-");
28273
+ const versionPart = dashIdx >= 0 ? versionDir.slice(dashIdx + 1) : versionDir;
28274
+ const segments = versionPart.split(".");
28275
+ const parsed = [];
28276
+ for (const seg of segments) {
28277
+ const n = parseInt(seg, 10);
28278
+ if (!Number.isFinite(n)) {
28279
+ break;
28280
+ }
28281
+ parsed.push(n);
28282
+ }
28283
+ return parsed.length > 0 ? parsed : void 0;
28284
+ }
28285
+ function compareVersionDirsDescending(a, b2) {
28286
+ const pa = parseVersionSegments(a);
28287
+ const pb = parseVersionSegments(b2);
28288
+ if (!pa && !pb) return 0;
28289
+ if (!pa) return 1;
28290
+ if (!pb) return -1;
28291
+ const len = Math.max(pa.length, pb.length);
28292
+ for (let i2 = 0; i2 < len; i2 += 1) {
28293
+ const av = pa[i2] ?? 0;
28294
+ const bv = pb[i2] ?? 0;
28295
+ if (av !== bv) return bv - av;
28296
+ }
28297
+ return 0;
28298
+ }
28175
28299
  function findFromPuppeteerCache() {
28176
28300
  if (!existsSync17(PUPPETEER_CACHE_DIR)) return void 0;
28177
28301
  let versions;
28178
28302
  try {
28179
- versions = readdirSync8(PUPPETEER_CACHE_DIR).sort().reverse();
28303
+ versions = [...readdirSync8(PUPPETEER_CACHE_DIR)].sort(compareVersionDirsDescending);
28180
28304
  } catch {
28181
28305
  return void 0;
28182
28306
  }
@@ -28216,7 +28340,8 @@ function warnSystemFallbackOnce(executablePath) {
28216
28340
  _warnedSystemFallback = true;
28217
28341
  console.warn(
28218
28342
  `[hyperframes] Using system Chrome at ${executablePath}; HeadlessExperimental.beginFrame is unavailable in regular Chrome builds, so the perf-optimized capture path falls back to screenshot mode. Install chrome-headless-shell for the optimized path:
28219
- npx @puppeteer/browsers install chrome-headless-shell`
28343
+ npx @puppeteer/browsers install chrome-headless-shell
28344
+ (Or set HYPERFRAMES_BROWSER_PATH to point at an existing chrome-headless-shell binary.)`
28220
28345
  );
28221
28346
  }
28222
28347
  function _resetSystemFallbackWarnForTests() {
@@ -28368,6 +28493,10 @@ function resolveConfig(overrides) {
28368
28493
  ),
28369
28494
  expectedChromiumMajor: env("PRODUCER_EXPECTED_CHROMIUM_MAJOR") ? Number(env("PRODUCER_EXPECTED_CHROMIUM_MAJOR")) : void 0,
28370
28495
  forceScreenshot: envBool("PRODUCER_FORCE_SCREENSHOT", DEFAULT_CONFIG2.forceScreenshot),
28496
+ enablePageSideCompositing: envBool(
28497
+ "HF_PAGE_SIDE_COMPOSITING",
28498
+ DEFAULT_CONFIG2.enablePageSideCompositing
28499
+ ),
28371
28500
  enableChunkedEncode: envBool(
28372
28501
  "PRODUCER_ENABLE_CHUNKED_ENCODE",
28373
28502
  DEFAULT_CONFIG2.enableChunkedEncode
@@ -28449,6 +28578,7 @@ var init_config2 = __esm({
28449
28578
  browserTimeout: 12e4,
28450
28579
  protocolTimeout: 3e5,
28451
28580
  forceScreenshot: false,
28581
+ enablePageSideCompositing: true,
28452
28582
  enableChunkedEncode: false,
28453
28583
  chunkSizeFrames: 360,
28454
28584
  enableStreamingEncode: true,
@@ -28854,14 +28984,14 @@ async function pageScreenshotCapture(page, options) {
28854
28984
  const client = await getCdpSession(page);
28855
28985
  const isPng = options.format === "png";
28856
28986
  const dpr = options.deviceScaleFactor ?? 1;
28857
- const clip = dpr > 1 ? { x: 0, y: 0, width: options.width, height: options.height, scale: dpr } : void 0;
28987
+ const clip = { x: 0, y: 0, width: options.width, height: options.height, scale: dpr };
28858
28988
  const result = await client.send("Page.captureScreenshot", {
28859
28989
  format: isPng ? "png" : "jpeg",
28860
28990
  quality: isPng ? void 0 : options.quality ?? 80,
28861
28991
  fromSurface: true,
28862
28992
  captureBeyondViewport: false,
28863
28993
  optimizeForSpeed: !isPng,
28864
- ...clip ? { clip } : {}
28994
+ clip
28865
28995
  });
28866
28996
  return Buffer.from(result.data, "base64");
28867
28997
  }
@@ -28965,6 +29095,15 @@ async function injectVideoFramesBatch(page, updates) {
28965
29095
  await page.evaluate(
28966
29096
  async (items, visualProperties) => {
28967
29097
  const pendingDecodes = [];
29098
+ const replacementLayoutProperties = /* @__PURE__ */ new Set([
29099
+ "width",
29100
+ "height",
29101
+ "top",
29102
+ "left",
29103
+ "right",
29104
+ "bottom",
29105
+ "inset"
29106
+ ]);
28968
29107
  for (const item of items) {
28969
29108
  const video = document.getElementById(item.videoId);
28970
29109
  if (!video) continue;
@@ -28973,7 +29112,6 @@ async function injectVideoFramesBatch(page, updates) {
28973
29112
  const computedStyle = window.getComputedStyle(video);
28974
29113
  const opacityParsed = parseFloat(computedStyle.opacity);
28975
29114
  const computedOpacity = Number.isNaN(opacityParsed) ? 1 : opacityParsed;
28976
- const sourceIsStatic = !computedStyle.position || computedStyle.position === "static";
28977
29115
  if (isNewImage) {
28978
29116
  img = document.createElement("img");
28979
29117
  img.classList.add("__render_frame__");
@@ -28982,6 +29120,16 @@ async function injectVideoFramesBatch(page, updates) {
28982
29120
  video.parentNode?.insertBefore(img, video.nextSibling);
28983
29121
  }
28984
29122
  if (!img) continue;
29123
+ for (const property of visualProperties) {
29124
+ if (property === "opacity") continue;
29125
+ if (replacementLayoutProperties.has(property)) {
29126
+ continue;
29127
+ }
29128
+ const value = computedStyle.getPropertyValue(property);
29129
+ if (value) {
29130
+ img.style.setProperty(property, value);
29131
+ }
29132
+ }
28985
29133
  {
28986
29134
  const videoRect = video.getBoundingClientRect();
28987
29135
  const offsetLeft = Number.isFinite(video.offsetLeft) ? video.offsetLeft : 0;
@@ -29000,16 +29148,6 @@ async function injectVideoFramesBatch(page, updates) {
29000
29148
  img.style.objectFit = computedStyle.objectFit;
29001
29149
  img.style.objectPosition = computedStyle.objectPosition;
29002
29150
  img.style.zIndex = computedStyle.zIndex;
29003
- for (const property of visualProperties) {
29004
- if (property === "opacity") continue;
29005
- if (sourceIsStatic && (property === "top" || property === "left" || property === "right" || property === "bottom" || property === "inset")) {
29006
- continue;
29007
- }
29008
- const value = computedStyle.getPropertyValue(property);
29009
- if (value) {
29010
- img.style.setProperty(property, value);
29011
- }
29012
- }
29013
29151
  img.decoding = "sync";
29014
29152
  if (img.getAttribute("src") !== item.dataUri) {
29015
29153
  img.src = item.dataUri;
@@ -29094,10 +29232,10 @@ async function waitForCloseWithTimeout(promise) {
29094
29232
  () => void 0,
29095
29233
  () => void 0
29096
29234
  ),
29097
- new Promise((resolve42) => {
29235
+ new Promise((resolve43) => {
29098
29236
  timer = setTimeout(() => {
29099
29237
  timedOut = true;
29100
- resolve42();
29238
+ resolve43();
29101
29239
  }, CAPTURE_SESSION_CLOSE_TIMEOUT_MS);
29102
29240
  })
29103
29241
  ]);
@@ -29195,10 +29333,27 @@ async function pollPageExpression(page, expression, timeoutMs, intervalMs = 100)
29195
29333
  while (Date.now() < deadline) {
29196
29334
  const ready = Boolean(await page.evaluate(expression));
29197
29335
  if (ready) return true;
29198
- await new Promise((resolve42) => setTimeout(resolve42, intervalMs));
29336
+ await new Promise((resolve43) => setTimeout(resolve43, intervalMs));
29199
29337
  }
29200
29338
  return Boolean(await page.evaluate(expression));
29201
29339
  }
29340
+ async function pollVideosReady(page, skipIds, timeoutMs, intervalMs = 100) {
29341
+ const check = async () => {
29342
+ return Boolean(
29343
+ await page.evaluate((skipIdList) => {
29344
+ const skip = new Set(skipIdList);
29345
+ const vids = Array.from(document.querySelectorAll("video")).filter((v2) => !skip.has(v2.id));
29346
+ return vids.length === 0 || vids.every((v2) => v2.readyState >= 2);
29347
+ }, skipIds)
29348
+ );
29349
+ };
29350
+ const deadline = Date.now() + timeoutMs;
29351
+ while (Date.now() < deadline) {
29352
+ if (await check()) return true;
29353
+ await new Promise((resolve43) => setTimeout(resolve43, intervalMs));
29354
+ }
29355
+ return check();
29356
+ }
29202
29357
  async function applyVideoMetadataHints(page, hints) {
29203
29358
  if (!hints || hints.length === 0) return;
29204
29359
  await page.evaluate(
@@ -29229,7 +29384,7 @@ async function waitForOptionalTailwindReady(page, timeoutMs) {
29229
29384
  page.evaluate(
29230
29385
  `Promise.resolve(window.__tailwindReady).then(() => true, () => false)`
29231
29386
  ),
29232
- new Promise((resolve42) => setTimeout(() => resolve42(false), timeoutMs))
29387
+ new Promise((resolve43) => setTimeout(() => resolve43(false), timeoutMs))
29233
29388
  ]);
29234
29389
  if (!ready) {
29235
29390
  throw new Error(
@@ -29281,10 +29436,9 @@ async function initializeSession(session) {
29281
29436
  );
29282
29437
  }
29283
29438
  await applyVideoMetadataHints(page, session.options.videoMetadataHints);
29284
- const skipIdsLiteral = JSON.stringify(session.options.skipReadinessVideoIds ?? []);
29285
- const videosReady = await pollPageExpression(
29439
+ const videosReady = await pollVideosReady(
29286
29440
  page,
29287
- `(() => { const skip = new Set(${skipIdsLiteral}); const vids = Array.from(document.querySelectorAll("video")).filter(v => !skip.has(v.id)); return vids.length === 0 || vids.every(v => v.readyState >= 2); })()`,
29441
+ session.options.skipReadinessVideoIds ?? [],
29288
29442
  pageReadyTimeout2
29289
29443
  );
29290
29444
  if (!videosReady) {
@@ -29356,15 +29510,11 @@ async function initializeSession(session) {
29356
29510
  );
29357
29511
  }
29358
29512
  await applyVideoMetadataHints(page, session.options.videoMetadataHints);
29359
- const beginframeSkipIdsLiteral = JSON.stringify(session.options.skipReadinessVideoIds ?? []);
29360
- const videoDeadline = Date.now() + (session.config?.playerReadyTimeout ?? DEFAULT_CONFIG2.playerReadyTimeout);
29361
- while (Date.now() < videoDeadline) {
29362
- const videosReady = await page.evaluate(
29363
- `(() => { const skip = new Set(${beginframeSkipIdsLiteral}); const vids = Array.from(document.querySelectorAll("video")).filter(v => !skip.has(v.id)); return vids.length === 0 || vids.every(v => v.readyState >= 2); })()`
29364
- );
29365
- if (videosReady) break;
29366
- await new Promise((r2) => setTimeout(r2, 100));
29367
- }
29513
+ await pollVideosReady(
29514
+ page,
29515
+ session.options.skipReadinessVideoIds ?? [],
29516
+ session.config?.playerReadyTimeout ?? DEFAULT_CONFIG2.playerReadyTimeout
29517
+ );
29368
29518
  await page.evaluate(`document.fonts?.ready`);
29369
29519
  await waitForOptionalTailwindReady(page, pageReadyTimeout);
29370
29520
  warmupState.running = false;
@@ -29414,10 +29564,11 @@ async function prepareFrameForCapture(session, frameIndex, time) {
29414
29564
  }
29415
29565
  const quantizedTime = quantizeTimeToFrame(time, fpsToNumber(options.fps));
29416
29566
  const seekStart = Date.now();
29417
- await page.evaluate((t2) => {
29567
+ const hasPendingComposite = await page.evaluate((t2) => {
29418
29568
  if (window.__hf && typeof window.__hf.seek === "function") {
29419
29569
  window.__hf.seek(t2);
29420
29570
  }
29571
+ return !!window.__hf_page_composite_pending;
29421
29572
  }, quantizedTime);
29422
29573
  const seekMs = Date.now() - seekStart;
29423
29574
  const beforeCaptureStart = Date.now();
@@ -29425,6 +29576,26 @@ async function prepareFrameForCapture(session, frameIndex, time) {
29425
29576
  await session.onBeforeCapture(page, quantizedTime);
29426
29577
  }
29427
29578
  const beforeCaptureMs = Date.now() - beforeCaptureStart;
29579
+ if (hasPendingComposite && session.captureMode !== "beginframe") {
29580
+ await page.evaluate(async () => {
29581
+ const w3 = window;
29582
+ if (typeof w3.__hf_page_composite_prepare === "function") {
29583
+ await w3.__hf_page_composite_prepare();
29584
+ }
29585
+ });
29586
+ const cdp = await getCdpSession(page);
29587
+ await cdp.send("Page.captureScreenshot", {
29588
+ format: "jpeg",
29589
+ quality: 1,
29590
+ clip: { x: 0, y: 0, width: 1, height: 1, scale: 1 }
29591
+ });
29592
+ await page.evaluate(() => {
29593
+ const w3 = window;
29594
+ if (typeof w3.__hf_page_composite_resolve === "function") {
29595
+ w3.__hf_page_composite_resolve();
29596
+ }
29597
+ });
29598
+ }
29428
29599
  return { quantizedTime, seekMs, beforeCaptureMs };
29429
29600
  }
29430
29601
  async function captureFrameCore(session, frameIndex, time) {
@@ -29566,14 +29737,14 @@ var init_frameCapture = __esm({
29566
29737
  BROWSER_CONSOLE_BUFFER_SIZE = 200;
29567
29738
  CAPTURE_SESSION_CLOSE_TIMEOUT_MS = 5e3;
29568
29739
  LOCKED_WARMUP_TICKS = 60;
29569
- realSleep = (ms) => new Promise((resolve42) => setTimeout(resolve42, ms));
29740
+ realSleep = (ms) => new Promise((resolve43) => setTimeout(resolve43, ms));
29570
29741
  }
29571
29742
  });
29572
29743
 
29573
29744
  // ../engine/src/utils/gpuEncoder.ts
29574
29745
  import { spawn as spawn3 } from "child_process";
29575
29746
  async function detectGpuEncoder() {
29576
- return new Promise((resolve42) => {
29747
+ return new Promise((resolve43) => {
29577
29748
  const ffmpeg = spawn3("ffmpeg", ["-encoders"], {
29578
29749
  stdio: ["pipe", "pipe", "pipe"]
29579
29750
  });
@@ -29582,13 +29753,13 @@ async function detectGpuEncoder() {
29582
29753
  stdout2 += data.toString();
29583
29754
  });
29584
29755
  ffmpeg.on("close", () => {
29585
- if (stdout2.includes("h264_nvenc")) resolve42("nvenc");
29586
- else if (stdout2.includes("h264_videotoolbox")) resolve42("videotoolbox");
29587
- else if (stdout2.includes("h264_vaapi")) resolve42("vaapi");
29588
- else if (stdout2.includes("h264_qsv")) resolve42("qsv");
29589
- else resolve42(null);
29756
+ if (stdout2.includes("h264_nvenc")) resolve43("nvenc");
29757
+ else if (stdout2.includes("h264_videotoolbox")) resolve43("videotoolbox");
29758
+ else if (stdout2.includes("h264_vaapi")) resolve43("vaapi");
29759
+ else if (stdout2.includes("h264_qsv")) resolve43("qsv");
29760
+ else resolve43(null);
29590
29761
  });
29591
- ffmpeg.on("error", () => resolve42(null));
29762
+ ffmpeg.on("error", () => resolve43(null));
29592
29763
  });
29593
29764
  }
29594
29765
  async function getCachedGpuEncoder() {
@@ -29709,7 +29880,7 @@ async function runFfmpeg(args, opts) {
29709
29880
  const signal = opts?.signal;
29710
29881
  const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;
29711
29882
  const onStderr = opts?.onStderr;
29712
- return new Promise((resolve42) => {
29883
+ return new Promise((resolve43) => {
29713
29884
  const ffmpeg = spawn4("ffmpeg", args);
29714
29885
  let stderr = "";
29715
29886
  const onAbort = () => {
@@ -29735,7 +29906,7 @@ async function runFfmpeg(args, opts) {
29735
29906
  ffmpeg.on("close", (code) => {
29736
29907
  clearTimeout(timer);
29737
29908
  if (signal) signal.removeEventListener("abort", onAbort);
29738
- resolve42({
29909
+ resolve43({
29739
29910
  success: !signal?.aborted && code === 0,
29740
29911
  exitCode: code,
29741
29912
  stderr,
@@ -29745,7 +29916,7 @@ async function runFfmpeg(args, opts) {
29745
29916
  ffmpeg.on("error", (err) => {
29746
29917
  clearTimeout(timer);
29747
29918
  if (signal) signal.removeEventListener("abort", onAbort);
29748
- resolve42({
29919
+ resolve43({
29749
29920
  success: false,
29750
29921
  exitCode: null,
29751
29922
  stderr: err.message,
@@ -29976,7 +30147,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
29976
30147
  const inputPath = join24(framesDir, framePattern);
29977
30148
  const inputArgs = ["-framerate", fpsToFfmpegArg(options.fps), "-i", inputPath];
29978
30149
  const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
29979
- return new Promise((resolve42) => {
30150
+ return new Promise((resolve43) => {
29980
30151
  const ffmpeg = spawn5("ffmpeg", args);
29981
30152
  let stderr = "";
29982
30153
  const onAbort = () => {
@@ -30001,7 +30172,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
30001
30172
  if (signal) signal.removeEventListener("abort", onAbort);
30002
30173
  const durationMs = Date.now() - startTime;
30003
30174
  if (signal?.aborted) {
30004
- resolve42({
30175
+ resolve43({
30005
30176
  success: false,
30006
30177
  outputPath,
30007
30178
  durationMs,
@@ -30012,7 +30183,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
30012
30183
  return;
30013
30184
  }
30014
30185
  if (code !== 0) {
30015
- resolve42({
30186
+ resolve43({
30016
30187
  success: false,
30017
30188
  outputPath,
30018
30189
  durationMs,
@@ -30023,12 +30194,12 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
30023
30194
  return;
30024
30195
  }
30025
30196
  const fileSize = existsSync20(outputPath) ? statSync6(outputPath).size : 0;
30026
- resolve42({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
30197
+ resolve43({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
30027
30198
  });
30028
30199
  ffmpeg.on("error", (err) => {
30029
30200
  clearTimeout(timer);
30030
30201
  if (signal) signal.removeEventListener("abort", onAbort);
30031
- resolve42({
30202
+ resolve43({
30032
30203
  success: false,
30033
30204
  outputPath,
30034
30205
  durationMs: Date.now() - startTime,
@@ -30086,18 +30257,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
30086
30257
  let gpuEncoder = null;
30087
30258
  if (options.useGpu) gpuEncoder = await getCachedGpuEncoder();
30088
30259
  const args = buildEncoderArgs(options, inputArgs, chunkPath, gpuEncoder);
30089
- const chunkResult = await new Promise((resolve42) => {
30260
+ const chunkResult = await new Promise((resolve43) => {
30090
30261
  const ffmpeg = spawn5("ffmpeg", args);
30091
30262
  let stderr = "";
30092
30263
  ffmpeg.stderr.on("data", (d2) => {
30093
30264
  stderr += d2.toString();
30094
30265
  });
30095
30266
  ffmpeg.on("close", (code) => {
30096
- if (code === 0) resolve42({ success: true });
30097
- else resolve42({ success: false, error: `Chunk ${i2} encode failed: ${stderr.slice(-400)}` });
30267
+ if (code === 0) resolve43({ success: true });
30268
+ else resolve43({ success: false, error: `Chunk ${i2} encode failed: ${stderr.slice(-400)}` });
30098
30269
  });
30099
30270
  ffmpeg.on("error", (err) => {
30100
- resolve42({ success: false, error: `Chunk ${i2} encode error: ${err.message}` });
30271
+ resolve43({ success: false, error: `Chunk ${i2} encode error: ${err.message}` });
30101
30272
  });
30102
30273
  });
30103
30274
  if (!chunkResult.success) {
@@ -30127,18 +30298,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
30127
30298
  "-y",
30128
30299
  outputPath
30129
30300
  ];
30130
- const concatResult = await new Promise((resolve42) => {
30301
+ const concatResult = await new Promise((resolve43) => {
30131
30302
  const ffmpeg = spawn5("ffmpeg", concatArgs);
30132
30303
  let stderr = "";
30133
30304
  ffmpeg.stderr.on("data", (d2) => {
30134
30305
  stderr += d2.toString();
30135
30306
  });
30136
30307
  ffmpeg.on("close", (code) => {
30137
- if (code === 0) resolve42({ success: true });
30138
- else resolve42({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
30308
+ if (code === 0) resolve43({ success: true });
30309
+ else resolve43({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
30139
30310
  });
30140
30311
  ffmpeg.on("error", (err) => {
30141
- resolve42({ success: false, error: `Chunk concat error: ${err.message}` });
30312
+ resolve43({ success: false, error: `Chunk concat error: ${err.message}` });
30142
30313
  });
30143
30314
  });
30144
30315
  if (!concatResult.success) {
@@ -30240,37 +30411,37 @@ import { dirname as dirname8 } from "path";
30240
30411
  function createFrameReorderBuffer(startFrame, endFrame) {
30241
30412
  let cursor = startFrame;
30242
30413
  const pending = /* @__PURE__ */ new Map();
30243
- const enqueueAt = (frame, resolve42) => {
30414
+ const enqueueAt = (frame, resolve43) => {
30244
30415
  const list = pending.get(frame);
30245
30416
  if (list === void 0) {
30246
- pending.set(frame, [resolve42]);
30417
+ pending.set(frame, [resolve43]);
30247
30418
  } else {
30248
- list.push(resolve42);
30419
+ list.push(resolve43);
30249
30420
  }
30250
30421
  };
30251
30422
  const flushAt = (frame) => {
30252
30423
  const list = pending.get(frame);
30253
30424
  if (list === void 0) return;
30254
30425
  pending.delete(frame);
30255
- for (const resolve42 of list) resolve42();
30426
+ for (const resolve43 of list) resolve43();
30256
30427
  };
30257
- const waitForFrame = (frame) => new Promise((resolve42) => {
30428
+ const waitForFrame = (frame) => new Promise((resolve43) => {
30258
30429
  if (frame === cursor) {
30259
- resolve42();
30430
+ resolve43();
30260
30431
  return;
30261
30432
  }
30262
- enqueueAt(frame, resolve42);
30433
+ enqueueAt(frame, resolve43);
30263
30434
  });
30264
30435
  const advanceTo = (frame) => {
30265
30436
  cursor = frame;
30266
30437
  flushAt(frame);
30267
30438
  };
30268
- const waitForAllDone = () => new Promise((resolve42) => {
30439
+ const waitForAllDone = () => new Promise((resolve43) => {
30269
30440
  if (cursor >= endFrame) {
30270
- resolve42();
30441
+ resolve43();
30271
30442
  return;
30272
30443
  }
30273
- enqueueAt(endFrame, resolve42);
30444
+ enqueueAt(endFrame, resolve43);
30274
30445
  });
30275
30446
  return { waitForFrame, advanceTo, waitForAllDone };
30276
30447
  }
@@ -30451,7 +30622,7 @@ async function spawnStreamingEncoder(outputPath, options, signal, config) {
30451
30622
  let stderr = "";
30452
30623
  let exitCode = null;
30453
30624
  let exitPromiseResolve = null;
30454
- const exitPromise = new Promise((resolve42) => exitPromiseResolve = resolve42);
30625
+ const exitPromise = new Promise((resolve43) => exitPromiseResolve = resolve43);
30455
30626
  ffmpeg.stderr?.on("data", (data) => {
30456
30627
  stderr += data.toString();
30457
30628
  });
@@ -30501,8 +30672,8 @@ Process error: ${err.message}`;
30501
30672
  if (signal) signal.removeEventListener("abort", onAbort);
30502
30673
  const stdin = ffmpeg.stdin;
30503
30674
  if (stdin && !stdin.destroyed) {
30504
- await new Promise((resolve42) => {
30505
- stdin.end(() => resolve42());
30675
+ await new Promise((resolve43) => {
30676
+ stdin.end(() => resolve43());
30506
30677
  });
30507
30678
  }
30508
30679
  await exitPromise;
@@ -30546,7 +30717,7 @@ import { spawn as spawn7 } from "child_process";
30546
30717
  import { readFileSync as readFileSync18 } from "fs";
30547
30718
  import { extname as extname5 } from "path";
30548
30719
  function runFfprobe(args) {
30549
- return new Promise((resolve42, reject) => {
30720
+ return new Promise((resolve43, reject) => {
30550
30721
  const proc = spawn7("ffprobe", args);
30551
30722
  let stdout2 = "";
30552
30723
  let stderr = "";
@@ -30560,7 +30731,7 @@ function runFfprobe(args) {
30560
30731
  if (code !== 0) {
30561
30732
  reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
30562
30733
  } else {
30563
- resolve42(stdout2);
30734
+ resolve43(stdout2);
30564
30735
  }
30565
30736
  });
30566
30737
  proc.on("error", (err) => {
@@ -30896,9 +31067,9 @@ var init_urlDownloader = __esm({
30896
31067
  });
30897
31068
 
30898
31069
  // ../core/src/compiler/htmlCompiler.ts
30899
- import { resolve as resolve12 } from "path";
31070
+ import { resolve as resolve13 } from "path";
30900
31071
  function resolveMediaSrc(src, projectDir) {
30901
- return src.startsWith("http://") || src.startsWith("https://") ? src : resolve12(projectDir, src);
31072
+ return src.startsWith("http://") || src.startsWith("https://") ? src : resolve13(projectDir, src);
30902
31073
  }
30903
31074
  async function compileHtml(rawHtml, projectDir, probeMediaDuration) {
30904
31075
  const { html: staticCompiled, unresolved } = compileTimingAttrs(rawHtml);
@@ -31260,12 +31431,12 @@ var init_staticGuard = __esm({
31260
31431
 
31261
31432
  // ../core/src/compiler/htmlBundler.ts
31262
31433
  import { readFileSync as readFileSync19, existsSync as existsSync23 } from "fs";
31263
- import { join as join26, resolve as resolve13, isAbsolute as isAbsolute3, sep as sep2 } from "path";
31434
+ import { join as join26, resolve as resolve14, isAbsolute as isAbsolute3, sep as sep3 } from "path";
31264
31435
  import { transformSync } from "esbuild";
31265
31436
  function safePath(projectDir, relativePath) {
31266
- const resolved = resolve13(projectDir, relativePath);
31267
- const normalizedBase = resolve13(projectDir) + sep2;
31268
- if (!resolved.startsWith(normalizedBase) && resolved !== resolve13(projectDir)) return null;
31437
+ const resolved = resolve14(projectDir, relativePath);
31438
+ const normalizedBase = resolve14(projectDir) + sep3;
31439
+ if (!resolved.startsWith(normalizedBase) && resolved !== resolve14(projectDir)) return null;
31269
31440
  return resolved;
31270
31441
  }
31271
31442
  function getRuntimeScriptUrl() {
@@ -31965,7 +32136,7 @@ var init_extractionCache = __esm({
31965
32136
  // ../engine/src/services/videoFrameExtractor.ts
31966
32137
  import { spawn as spawn8 } from "child_process";
31967
32138
  import { existsSync as existsSync25, mkdirSync as mkdirSync15, readdirSync as readdirSync12, rmSync as rmSync5 } from "fs";
31968
- import { isAbsolute as isAbsolute4, join as join28, posix as posix2, resolve as resolve14, sep as sep3 } from "path";
32139
+ import { isAbsolute as isAbsolute4, join as join28, posix as posix2, resolve as resolve15, sep as sep4 } from "path";
31969
32140
  function parseVideoElements(html) {
31970
32141
  const videos = [];
31971
32142
  const { document: document2 } = parseHTML(unwrapTemplate(html));
@@ -32060,7 +32231,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
32060
32231
  args.push("-q:v", format === "jpg" ? String(Math.ceil((100 - quality) / 3)) : "0");
32061
32232
  if (format === "png") args.push("-compression_level", "6");
32062
32233
  args.push("-y", outputPattern);
32063
- return new Promise((resolve42, reject) => {
32234
+ return new Promise((resolve43, reject) => {
32064
32235
  const ffmpeg = spawn8("ffmpeg", args);
32065
32236
  let stderr = "";
32066
32237
  const onAbort = () => {
@@ -32095,7 +32266,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
32095
32266
  files.forEach((file, index) => {
32096
32267
  framePaths.set(index, join28(videoOutputDir, file));
32097
32268
  });
32098
- resolve42({
32269
+ resolve43({
32099
32270
  videoId,
32100
32271
  srcPath: videoPath,
32101
32272
  outputDir: videoOutputDir,
@@ -32212,9 +32383,9 @@ function resolveProjectRelativeSrc(src, baseDir, compiledDir) {
32212
32383
  const candidates = [];
32213
32384
  if (fromCompiled) candidates.push(fromCompiled);
32214
32385
  candidates.push(fromBase);
32215
- const baseAbs = resolve14(baseDir);
32216
- const fromBaseAbs = resolve14(fromBase);
32217
- if (!fromBaseAbs.startsWith(baseAbs + sep3) && fromBaseAbs !== baseAbs) {
32386
+ const baseAbs = resolve15(baseDir);
32387
+ const fromBaseAbs = resolve15(fromBase);
32388
+ if (!fromBaseAbs.startsWith(baseAbs + sep4) && fromBaseAbs !== baseAbs) {
32218
32389
  const normalized = posix2.normalize(src.replace(/\\/g, "/"));
32219
32390
  const stripped = normalized.replace(/^(\.\.\/)+/, "");
32220
32391
  if (stripped && stripped !== src && !stripped.startsWith("..")) {
@@ -33584,11 +33755,11 @@ function createFileServer(options) {
33584
33755
  headers: { "Content-Type": contentType }
33585
33756
  });
33586
33757
  });
33587
- return new Promise((resolve42) => {
33758
+ return new Promise((resolve43) => {
33588
33759
  const server = serve({ fetch: app.fetch, port }, (info) => {
33589
33760
  const actualPort = info.port;
33590
33761
  const url = `http://localhost:${actualPort}`;
33591
- resolve42({
33762
+ resolve43({
33592
33763
  url,
33593
33764
  port: actualPort,
33594
33765
  close: () => server.close()
@@ -35720,7 +35891,7 @@ var init_deterministicFonts = __esm({
35720
35891
  // ../producer/src/services/hyperframeRuntimeLoader.ts
35721
35892
  import { createHash as createHash5 } from "crypto";
35722
35893
  import { existsSync as existsSync31, readFileSync as readFileSync22 } from "fs";
35723
- import { dirname as dirname10, resolve as resolve15 } from "path";
35894
+ import { dirname as dirname10, resolve as resolve16 } from "path";
35724
35895
  import { fileURLToPath as fileURLToPath2 } from "url";
35725
35896
  function resolveHyperframeManifestPath() {
35726
35897
  if (process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH) {
@@ -35756,7 +35927,7 @@ function resolveVerifiedHyperframeRuntime() {
35756
35927
  `[HyperframeRuntimeLoader] Invalid manifest at ${manifestPath}; missing iife artifact or sha256.`
35757
35928
  );
35758
35929
  }
35759
- const runtimePath = resolve15(dirname10(manifestPath), runtimeFileName);
35930
+ const runtimePath = resolve16(dirname10(manifestPath), runtimeFileName);
35760
35931
  if (!existsSync31(runtimePath)) {
35761
35932
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
35762
35933
  }
@@ -35780,18 +35951,18 @@ var init_hyperframeRuntimeLoader = __esm({
35780
35951
  "../producer/src/services/hyperframeRuntimeLoader.ts"() {
35781
35952
  "use strict";
35782
35953
  PRODUCER_DIR = dirname10(fileURLToPath2(import.meta.url));
35783
- SIBLING_MANIFEST_PATH = resolve15(PRODUCER_DIR, "hyperframe.manifest.json");
35784
- MODULE_RELATIVE_MANIFEST_PATH = resolve15(
35954
+ SIBLING_MANIFEST_PATH = resolve16(PRODUCER_DIR, "hyperframe.manifest.json");
35955
+ MODULE_RELATIVE_MANIFEST_PATH = resolve16(
35785
35956
  PRODUCER_DIR,
35786
35957
  "../../../core/dist/hyperframe.manifest.json"
35787
35958
  );
35788
35959
  CWD_RELATIVE_MANIFEST_PATHS = [
35789
35960
  // When bundled to a single file (dist/public-server.js), the manifest
35790
35961
  // is copied as a sibling by build.mjs
35791
- resolve15(PRODUCER_DIR, "hyperframe.manifest.json"),
35792
- resolve15(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
35793
- resolve15(process.cwd(), "../core/dist/hyperframe.manifest.json"),
35794
- resolve15(process.cwd(), "core/dist/hyperframe.manifest.json")
35962
+ resolve16(PRODUCER_DIR, "hyperframe.manifest.json"),
35963
+ resolve16(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
35964
+ resolve16(process.cwd(), "../core/dist/hyperframe.manifest.json"),
35965
+ resolve16(process.cwd(), "core/dist/hyperframe.manifest.json")
35795
35966
  ];
35796
35967
  }
35797
35968
  });
@@ -35800,11 +35971,11 @@ var init_hyperframeRuntimeLoader = __esm({
35800
35971
  import { Hono as Hono3 } from "hono";
35801
35972
  import { serve as serve2 } from "@hono/node-server";
35802
35973
  import { readFileSync as readFileSync23, existsSync as existsSync32, realpathSync, statSync as statSync10 } from "fs";
35803
- import { join as join34, extname as extname8, resolve as resolve16, sep as sep4 } from "path";
35974
+ import { join as join34, extname as extname8, resolve as resolve17, sep as sep5 } from "path";
35804
35975
  function isPathInside(child, parent, options = {}) {
35805
35976
  const { resolveSymlinks = false, pathModule } = options;
35806
- const resolveFn = pathModule?.resolve ?? resolve16;
35807
- const separator = pathModule?.sep ?? sep4;
35977
+ const resolveFn = pathModule?.resolve ?? resolve17;
35978
+ const separator = pathModule?.sep ?? sep5;
35808
35979
  const resolvedChild = resolveFn(child);
35809
35980
  const resolvedParent = resolveFn(parent);
35810
35981
  const normalizedChild = resolveSymlinks && existsSync32(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
@@ -36009,12 +36180,15 @@ function createFileServer2(options) {
36009
36180
  headers: { "Content-Type": contentType }
36010
36181
  });
36011
36182
  });
36012
- return new Promise((resolve42) => {
36183
+ return new Promise((resolve43) => {
36013
36184
  const connections = /* @__PURE__ */ new Set();
36014
36185
  const server = serve2({ fetch: app.fetch, port }, (info) => {
36015
- resolve42({
36186
+ resolve43({
36016
36187
  url: `http://localhost:${info.port}`,
36017
36188
  port: info.port,
36189
+ addPreHeadScript: (script) => {
36190
+ preHeadScripts.push(script);
36191
+ },
36018
36192
  close: () => {
36019
36193
  for (const socket of connections) socket.destroy();
36020
36194
  connections.clear();
@@ -36028,7 +36202,7 @@ function createFileServer2(options) {
36028
36202
  });
36029
36203
  });
36030
36204
  }
36031
- var MIME_TYPES3, VIRTUAL_TIME_SHIM, RENDER_SEEK_MODE, RENDER_SEEK_DIAGNOSTICS, RENDER_SEEK_STEP, RENDER_SEEK_OFFSET_FRACTION, RENDER_MODE_SCRIPT, HF_EARLY_STUB, HF_BRIDGE_SCRIPT;
36205
+ var MIME_TYPES3, VIRTUAL_TIME_SHIM, RENDER_SEEK_MODE, RENDER_SEEK_DIAGNOSTICS, RENDER_SEEK_STEP, RENDER_SEEK_OFFSET_FRACTION, RENDER_MODE_SCRIPT, HF_EARLY_STUB, HF_PAGE_SIDE_COMPOSITING_STUB, HF_BRIDGE_SCRIPT;
36032
36206
  var init_fileServer2 = __esm({
36033
36207
  "../producer/src/services/fileServer.ts"() {
36034
36208
  "use strict";
@@ -36178,6 +36352,10 @@ var init_fileServer2 = __esm({
36178
36352
  HF_EARLY_STUB = `(function() {
36179
36353
  if (typeof window === "undefined") return;
36180
36354
  if (!window.__hf) window.__hf = {};
36355
+ })();`;
36356
+ HF_PAGE_SIDE_COMPOSITING_STUB = `(function() {
36357
+ if (typeof window === "undefined") return;
36358
+ window.__HF_PAGE_SIDE_COMPOSITING__ = true;
36181
36359
  })();`;
36182
36360
  HF_BRIDGE_SCRIPT = `(function() {
36183
36361
  var __realSetInterval =
@@ -36342,7 +36520,7 @@ var init_paths = __esm({
36342
36520
 
36343
36521
  // ../producer/src/services/render/shared.ts
36344
36522
  import { copyFileSync as copyFileSync2, cpSync, existsSync as existsSync33, mkdirSync as mkdirSync19, symlinkSync, writeFileSync as writeFileSync15 } from "fs";
36345
- import { basename as basename4, dirname as dirname11, isAbsolute as isAbsolute6, join as join36, relative as relative3, resolve as resolve17 } from "path";
36523
+ import { basename as basename4, dirname as dirname11, isAbsolute as isAbsolute6, join as join36, relative as relative3, resolve as resolve18 } from "path";
36346
36524
  function projectBrowserEndToCompositionTimeline(existingStart, browserStart, browserEnd) {
36347
36525
  return browserEnd + (existingStart - browserStart);
36348
36526
  }
@@ -36387,7 +36565,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
36387
36565
  writeFileSync15(outPath, html, "utf-8");
36388
36566
  }
36389
36567
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
36390
- const outPath = resolve17(join36(compileDir, relativePath));
36568
+ const outPath = resolve18(join36(compileDir, relativePath));
36391
36569
  if (!isPathInside2(outPath, compileDir)) {
36392
36570
  console.warn(`[Render] Skipping external asset with unsafe path: ${relativePath}`);
36393
36571
  continue;
@@ -36439,9 +36617,9 @@ function updateJobStatus(job, status, stage, progress, onProgress) {
36439
36617
  if (onProgress) onProgress(job, stage);
36440
36618
  }
36441
36619
  function createCompiledFrameSrcResolver(compiledDir) {
36442
- const compiledRoot = resolve17(compiledDir);
36620
+ const compiledRoot = resolve18(compiledDir);
36443
36621
  return (framePath) => {
36444
- const resolvedFramePath = resolve17(framePath);
36622
+ const resolvedFramePath = resolve18(framePath);
36445
36623
  if (!isPathInside2(resolvedFramePath, compiledRoot)) return null;
36446
36624
  const relativePath = relative3(compiledRoot, resolvedFramePath);
36447
36625
  if (!relativePath || relativePath.startsWith("..") || isAbsolute6(relativePath)) {
@@ -36520,7 +36698,7 @@ var init_shared = __esm({
36520
36698
  init_paths();
36521
36699
  BROWSER_MEDIA_EPSILON = 1e-4;
36522
36700
  materializePathModule = {
36523
- resolve: resolve17,
36701
+ resolve: resolve18,
36524
36702
  join: join36,
36525
36703
  dirname: dirname11,
36526
36704
  basename: basename4,
@@ -37065,7 +37243,7 @@ var init_urlDownloader2 = __esm({
37065
37243
 
37066
37244
  // ../producer/src/services/htmlCompiler.ts
37067
37245
  import { readFileSync as readFileSync24, existsSync as existsSync34, mkdirSync as mkdirSync20 } from "fs";
37068
- import { join as join38, dirname as dirname12, resolve as resolve18 } from "path";
37246
+ import { join as join38, dirname as dirname12, resolve as resolve19 } from "path";
37069
37247
  function dedupeElementsById(elements) {
37070
37248
  const deduped = /* @__PURE__ */ new Map();
37071
37249
  for (const element of elements) {
@@ -37209,7 +37387,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
37209
37387
  const elEnd = elEndRaw ? parseFloat(elEndRaw) : Infinity;
37210
37388
  const absoluteStart = parentOffset + elStart;
37211
37389
  const absoluteEnd = Math.min(parentEnd, isFinite(elEnd) ? parentOffset + elEnd : Infinity);
37212
- const filePath = resolve18(projectDir, srcPath);
37390
+ const filePath = resolve19(projectDir, srcPath);
37213
37391
  if (visited.has(filePath)) {
37214
37392
  continue;
37215
37393
  }
@@ -37401,7 +37579,7 @@ function inlineSubCompositions(html, subCompositions, projectDir) {
37401
37579
  if (!srcPath) continue;
37402
37580
  let compHtml = subCompositions.get(srcPath) || null;
37403
37581
  if (!compHtml) {
37404
- const filePath = resolve18(projectDir, srcPath);
37582
+ const filePath = resolve19(projectDir, srcPath);
37405
37583
  if (existsSync34(filePath)) {
37406
37584
  compHtml = readFileSync24(filePath, "utf-8");
37407
37585
  }
@@ -37592,7 +37770,7 @@ ${safeText}
37592
37770
  return wrappedFragment ? document2.body.innerHTML || "" : document2.toString();
37593
37771
  }
37594
37772
  function collectExternalAssets(html, projectDir) {
37595
- const absProjectDir = resolve18(projectDir);
37773
+ const absProjectDir = resolve19(projectDir);
37596
37774
  const externalAssets = /* @__PURE__ */ new Map();
37597
37775
  const CSS_URL_RE2 = /\burl\(\s*(["']?)([^)"']+)\1\s*\)/g;
37598
37776
  function processPath(rawPath) {
@@ -37600,7 +37778,7 @@ function collectExternalAssets(html, projectDir) {
37600
37778
  if (!trimmed || trimmed.startsWith("/") || trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("//") || trimmed.startsWith("data:") || trimmed.startsWith("#")) {
37601
37779
  return null;
37602
37780
  }
37603
- const absPath = resolve18(absProjectDir, trimmed);
37781
+ const absPath = resolve19(absProjectDir, trimmed);
37604
37782
  if (isPathInside2(absPath, absProjectDir)) {
37605
37783
  return null;
37606
37784
  }
@@ -37675,7 +37853,11 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
37675
37853
  );
37676
37854
  const assembledHtml = await inlineExternalScripts(coalescedHtml);
37677
37855
  const { html: htmlWithAssets, externalAssets } = collectExternalAssets(assembledHtml, projectDir);
37678
- const HF_POSITION_ATTRS = ['data-hf-studio-path-offset="true"', 'data-hf-studio-rotation="true"'];
37856
+ const HF_POSITION_ATTRS = [
37857
+ 'data-hf-studio-path-offset="true"',
37858
+ 'data-hf-studio-rotation="true"',
37859
+ 'data-hf-studio-motion="'
37860
+ ];
37679
37861
  const hasPositionEdits = HF_POSITION_ATTRS.some((attr) => htmlWithAssets.includes(attr));
37680
37862
  const html = hasPositionEdits ? htmlWithAssets.replace(
37681
37863
  /<\/body>/i,
@@ -37689,7 +37871,7 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
37689
37871
  const images = dedupeElementsById([...mainImages, ...subImages]);
37690
37872
  for (const video of videos) {
37691
37873
  if (isHttpUrl(video.src)) continue;
37692
- const videoPath = resolve18(projectDir, video.src);
37874
+ const videoPath = resolve19(projectDir, video.src);
37693
37875
  const reencode = `ffmpeg -i "${video.src}" -c:v libx264 -r 30 -g 30 -keyint_min 30 -movflags +faststart -c:a copy output.mp4`;
37694
37876
  Promise.all([analyzeKeyframeIntervals(videoPath), extractMediaMetadata(videoPath)]).then(([analysis, metadata]) => {
37695
37877
  if (analysis.isProblematic) {
@@ -37760,6 +37942,73 @@ async function discoverMediaFromBrowser(page) {
37760
37942
  });
37761
37943
  return elements;
37762
37944
  }
37945
+ async function discoverVideoVisibilityFromTimeline(page, compositionDuration) {
37946
+ if (compositionDuration <= 0) return [];
37947
+ return page.evaluate((duration) => {
37948
+ const results = [];
37949
+ const videos = document.querySelectorAll("video[data-hf-auto-start]");
37950
+ if (videos.length === 0) return results;
37951
+ const timelines = window.__timelines;
37952
+ if (!timelines) return results;
37953
+ const rootEl = document.querySelector("[data-composition-id]");
37954
+ const compId = rootEl?.getAttribute("data-composition-id");
37955
+ if (!compId) return results;
37956
+ const tl = timelines[compId];
37957
+ if (!tl) return results;
37958
+ const seekTl = (t2) => {
37959
+ if (typeof tl.totalTime === "function") {
37960
+ tl.totalTime(t2, true);
37961
+ } else if (typeof tl.seek === "function") {
37962
+ tl.seek(t2, true);
37963
+ }
37964
+ };
37965
+ const SAMPLE_STEP = 0.1;
37966
+ const BINARY_PRECISION = 1 / 60;
37967
+ for (const videoEl of videos) {
37968
+ const id = videoEl.id;
37969
+ if (!id) continue;
37970
+ const sceneEl = videoEl.closest(".scene") || videoEl;
37971
+ let firstVisible = null;
37972
+ let lastVisible = null;
37973
+ for (let t2 = 0; t2 <= duration; t2 += SAMPLE_STEP) {
37974
+ seekTl(t2);
37975
+ const opacity = parseFloat(window.getComputedStyle(sceneEl).opacity);
37976
+ if (opacity > 0) {
37977
+ if (firstVisible === null) firstVisible = t2;
37978
+ lastVisible = t2;
37979
+ }
37980
+ }
37981
+ if (firstVisible === null || lastVisible === null) continue;
37982
+ let lo = Math.max(0, firstVisible - SAMPLE_STEP);
37983
+ let hi = firstVisible;
37984
+ while (hi - lo > BINARY_PRECISION) {
37985
+ const mid = (lo + hi) / 2;
37986
+ seekTl(mid);
37987
+ const opacity = parseFloat(window.getComputedStyle(sceneEl).opacity);
37988
+ if (opacity > 0) hi = mid;
37989
+ else lo = mid;
37990
+ }
37991
+ const exactStart = hi;
37992
+ lo = lastVisible;
37993
+ hi = Math.min(duration, lastVisible + SAMPLE_STEP);
37994
+ while (hi - lo > BINARY_PRECISION) {
37995
+ const mid = (lo + hi) / 2;
37996
+ seekTl(mid);
37997
+ const opacity = parseFloat(window.getComputedStyle(sceneEl).opacity);
37998
+ if (opacity > 0) lo = mid;
37999
+ else hi = mid;
38000
+ }
38001
+ const exactEnd = lo;
38002
+ results.push({
38003
+ videoId: id,
38004
+ visibleStart: Math.max(0, exactStart),
38005
+ visibleEnd: Math.min(duration, exactEnd)
38006
+ });
38007
+ }
38008
+ seekTl(0);
38009
+ return results;
38010
+ }, compositionDuration);
38011
+ }
37763
38012
  async function resolveCompositionDurations(page, unresolved) {
37764
38013
  if (unresolved.length === 0) return [];
37765
38014
  const ids = unresolved.map((el) => el.id);
@@ -37951,7 +38200,8 @@ async function runProbeStage(input) {
37951
38200
  let probeSession = null;
37952
38201
  let lastBrowserConsole = [];
37953
38202
  const probeStart = Date.now();
37954
- const needsBrowser = composition.duration <= 0 || compiled.unresolvedCompositions.length > 0;
38203
+ const hasAutoStartVideos = compiled.html.includes("data-hf-auto-start");
38204
+ const needsBrowser = composition.duration <= 0 || compiled.unresolvedCompositions.length > 0 || hasAutoStartVideos;
37955
38205
  if (needsBrowser) {
37956
38206
  const reasons = [];
37957
38207
  if (composition.duration <= 0) reasons.push("root duration unknown");
@@ -38101,6 +38351,24 @@ async function runProbeStage(input) {
38101
38351
  }
38102
38352
  }
38103
38353
  }
38354
+ if (composition.videos.length > 0) {
38355
+ const visibilityWindows = await discoverVideoVisibilityFromTimeline(
38356
+ probeSession.page,
38357
+ composition.duration
38358
+ );
38359
+ assertNotAborted();
38360
+ for (const win of visibilityWindows) {
38361
+ const video = composition.videos.find((v2) => v2.id === win.videoId);
38362
+ if (!video) continue;
38363
+ if (win.visibleStart >= 0 && win.visibleEnd > win.visibleStart) {
38364
+ video.start = win.visibleStart;
38365
+ video.end = win.visibleEnd;
38366
+ log2.info(
38367
+ `[Probe] Runtime video discovery: ${video.id} visible ${win.visibleStart.toFixed(2)}s\u2013${win.visibleEnd.toFixed(2)}s`
38368
+ );
38369
+ }
38370
+ }
38371
+ }
38104
38372
  }
38105
38373
  const browserProbeMs = Date.now() - probeStart;
38106
38374
  const duration = composition.duration;
@@ -39423,8 +39691,8 @@ async function createShaderTransitionWorkerPool(opts) {
39423
39691
  if (terminated) {
39424
39692
  throw new Error("shader-blend pool already terminated");
39425
39693
  }
39426
- return new Promise((resolve42, reject) => {
39427
- const task = traceEnabled ? { req, resolve: resolve42, reject, enqueuedAtMs: Date.now(), traceId: ++nextTaskId } : { req, resolve: resolve42, reject };
39694
+ return new Promise((resolve43, reject) => {
39695
+ const task = traceEnabled ? { req, resolve: resolve43, reject, enqueuedAtMs: Date.now(), traceId: ++nextTaskId } : { req, resolve: resolve43, reject };
39428
39696
  const idle = slots.find((s2) => !s2.busy);
39429
39697
  if (idle) {
39430
39698
  queue.unshift(task);
@@ -40157,7 +40425,7 @@ import {
40157
40425
  copyFileSync as copyFileSync4,
40158
40426
  appendFileSync
40159
40427
  } from "fs";
40160
- import { join as join49, dirname as dirname14, resolve as resolve19 } from "path";
40428
+ import { join as join49, dirname as dirname14, resolve as resolve20 } from "path";
40161
40429
  import { randomUUID as randomUUID2 } from "crypto";
40162
40430
  import { fileURLToPath as fileURLToPath4 } from "url";
40163
40431
  function sampleDirectoryBytes(dir) {
@@ -40831,7 +41099,7 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
40831
41099
  }
40832
41100
  async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSignal) {
40833
41101
  const moduleDir = dirname14(fileURLToPath4(import.meta.url));
40834
- const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve19(process.env.PRODUCER_RENDERS_DIR, "..") : resolve19(moduleDir, "../..");
41102
+ const producerRoot = process.env.PRODUCER_RENDERS_DIR ? resolve20(process.env.PRODUCER_RENDERS_DIR, "..") : resolve20(moduleDir, "../..");
40835
41103
  const debugDir = join49(producerRoot, ".debug");
40836
41104
  const workDir = job.config.debug ? join49(debugDir, job.id) : join49(dirname14(outputPath), `work-${job.id}`);
40837
41105
  const pipelineStart = Date.now();
@@ -41073,7 +41341,14 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
41073
41341
  const videoOnlyPath = join49(workDir, `video-only${videoExt}`);
41074
41342
  const nativeHdrIds = /* @__PURE__ */ new Set([...nativeHdrVideoIds, ...nativeHdrImageIds]);
41075
41343
  const hasHdrContent = Boolean(effectiveHdr && nativeHdrIds.size > 0);
41076
- const useLayeredComposite = shouldUseLayeredComposite({
41344
+ const usePageSideCompositingForTransitions = cfg.enablePageSideCompositing && compiled.hasShaderTransitions && !hasHdrContent && !isPngSequence && !needsAlpha;
41345
+ if (usePageSideCompositingForTransitions) {
41346
+ fileServer.addPreHeadScript(HF_PAGE_SIDE_COMPOSITING_STUB);
41347
+ log2.info(
41348
+ "[Render] Page-side compositing enabled \u2014 bypassing Node-side layered shader-blend path. Engine will capture one opaque RGB frame per output frame."
41349
+ );
41350
+ }
41351
+ const useLayeredComposite = !usePageSideCompositingForTransitions && shouldUseLayeredComposite({
41077
41352
  hasHdrContent,
41078
41353
  hasShaderTransitions: compiled.hasShaderTransitions,
41079
41354
  isPngSequence
@@ -41407,7 +41682,7 @@ var init_config3 = __esm({
41407
41682
 
41408
41683
  // ../producer/src/services/hyperframeLint.ts
41409
41684
  import { existsSync as existsSync40, readFileSync as readFileSync27, statSync as statSync13 } from "fs";
41410
- import { resolve as resolve20, join as join50 } from "path";
41685
+ import { resolve as resolve21, join as join50 } from "path";
41411
41686
  function isStringRecord(value) {
41412
41687
  if (!value || typeof value !== "object" || Array.isArray(value)) {
41413
41688
  return false;
@@ -41434,7 +41709,7 @@ function pickEntryFile(files, preferredEntryFile) {
41434
41709
  return null;
41435
41710
  }
41436
41711
  function readProjectEntryFile(projectDir, preferredEntryFile) {
41437
- const absProjectDir = resolve20(projectDir);
41712
+ const absProjectDir = resolve21(projectDir);
41438
41713
  if (!existsSync40(absProjectDir) || !statSync13(absProjectDir).isDirectory()) {
41439
41714
  return { error: `Project directory not found: ${absProjectDir}` };
41440
41715
  }
@@ -41442,7 +41717,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
41442
41717
  (value) => typeof value === "string" && value.trim().length > 0
41443
41718
  );
41444
41719
  for (const entryFile of entryCandidates) {
41445
- const absoluteEntryPath = resolve20(absProjectDir, entryFile);
41720
+ const absoluteEntryPath = resolve21(absProjectDir, entryFile);
41446
41721
  if (!absoluteEntryPath.startsWith(absProjectDir)) {
41447
41722
  return { error: `Entry file must stay inside project directory: ${entryFile}` };
41448
41723
  }
@@ -41518,10 +41793,10 @@ var init_semaphore = __esm({
41518
41793
  this.active++;
41519
41794
  return () => this.release();
41520
41795
  }
41521
- return new Promise((resolve42) => {
41796
+ return new Promise((resolve43) => {
41522
41797
  this.queue.push(() => {
41523
41798
  this.active++;
41524
- resolve42(() => this.release());
41799
+ resolve43(() => this.release());
41525
41800
  });
41526
41801
  });
41527
41802
  }
@@ -41552,7 +41827,7 @@ import {
41552
41827
  rmSync as rmSync10,
41553
41828
  createReadStream
41554
41829
  } from "fs";
41555
- import { resolve as resolve21, dirname as dirname15, join as join51 } from "path";
41830
+ import { resolve as resolve22, dirname as dirname15, join as join51 } from "path";
41556
41831
  import { tmpdir as tmpdir3 } from "os";
41557
41832
  import { parseArgs as parseArgs2 } from "util";
41558
41833
  import crypto2 from "crypto";
@@ -41576,12 +41851,12 @@ async function prepareRenderBody(body) {
41576
41851
  const options = parseRenderOptions(body);
41577
41852
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : void 0;
41578
41853
  if (projectDir) {
41579
- const absProjectDir = resolve21(projectDir);
41854
+ const absProjectDir = resolve22(projectDir);
41580
41855
  if (!existsSync41(absProjectDir) || !statSync14(absProjectDir).isDirectory()) {
41581
41856
  return { error: `Project directory not found: ${absProjectDir}` };
41582
41857
  }
41583
41858
  const entry = options.entryFile || "index.html";
41584
- if (!existsSync41(resolve21(absProjectDir, entry))) {
41859
+ if (!existsSync41(resolve22(absProjectDir, entry))) {
41585
41860
  return { error: `Entry file "${entry}" not found in project directory: ${absProjectDir}` };
41586
41861
  }
41587
41862
  return { prepared: { input: { projectDir: absProjectDir, ...options } } };
@@ -41622,7 +41897,7 @@ function resolveOutputPath(projectDir, outputCandidate, rendersDir, log2) {
41622
41897
  try {
41623
41898
  return resolveRenderPaths(projectDir, outputCandidate, rendersDir).absoluteOutputPath;
41624
41899
  } catch (error) {
41625
- const fallbackPath = resolve21(rendersDir, `producer-fallback-${Date.now()}.mp4`);
41900
+ const fallbackPath = resolve22(rendersDir, `producer-fallback-${Date.now()}.mp4`);
41626
41901
  log2.warn("Failed to resolve output path, using fallback", {
41627
41902
  fallback: fallbackPath,
41628
41903
  error: error instanceof Error ? error.message : String(error)
@@ -42011,7 +42286,7 @@ var init_server = __esm({
42011
42286
  init_logger();
42012
42287
  init_semaphore();
42013
42288
  init_src();
42014
- entryScript = process.argv[1] ? resolve21(process.argv[1]) : "";
42289
+ entryScript = process.argv[1] ? resolve22(process.argv[1]) : "";
42015
42290
  isPublicServerEntry = entryScript.endsWith("/public-server.js") || entryScript.endsWith("/src/server.ts");
42016
42291
  if (isPublicServerEntry) {
42017
42292
  const { values } = parseArgs2({
@@ -42138,7 +42413,7 @@ var init_runtimeEnvSnapshot = __esm({
42138
42413
 
42139
42414
  // ../producer/src/services/render/stages/freezePlan.ts
42140
42415
  import { existsSync as existsSync42, mkdirSync as mkdirSync26, readFileSync as readFileSync28, readdirSync as readdirSync17, writeFileSync as writeFileSync20 } from "fs";
42141
- import { join as join52, relative as relative4, resolve as resolve22 } from "path";
42416
+ import { join as join52, relative as relative4, resolve as resolve23 } from "path";
42142
42417
  function stripUndefined(value) {
42143
42418
  if (Array.isArray(value)) return value.map(stripUndefined);
42144
42419
  if (value !== null && typeof value === "object") {
@@ -42155,7 +42430,7 @@ function stripUndefined(value) {
42155
42430
  }
42156
42431
  function listPlanFiles(planDir) {
42157
42432
  const results = [];
42158
- const rootResolved = resolve22(planDir);
42433
+ const rootResolved = resolve23(planDir);
42159
42434
  function walk(dir) {
42160
42435
  const entries2 = readdirSync17(dir, { withFileTypes: true });
42161
42436
  for (const entry of entries2) {
@@ -42414,7 +42689,7 @@ import {
42414
42689
  statSync as statSync15,
42415
42690
  writeFileSync as writeFileSync21
42416
42691
  } from "fs";
42417
- import { join as join54, relative as relative5, sep as sep5 } from "path";
42692
+ import { join as join54, relative as relative5, sep as sep6 } from "path";
42418
42693
  function formatBytes(bytes) {
42419
42694
  if (bytes < 1024) return `${bytes} B`;
42420
42695
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
@@ -42601,7 +42876,7 @@ async function plan(projectDir, config, planDir) {
42601
42876
  filter: (src) => {
42602
42877
  const rel = relative5(projectDir, src);
42603
42878
  if (rel === "" || rel.startsWith("..")) return true;
42604
- const firstSegment = rel.split(sep5, 1)[0];
42879
+ const firstSegment = rel.split(sep6, 1)[0];
42605
42880
  return firstSegment === void 0 || !PLAN_PROJECT_DIR_SKIP_SEGMENTS.has(firstSegment);
42606
42881
  }
42607
42882
  });
@@ -43368,7 +43643,7 @@ async function defaultRunFfmpeg(args) {
43368
43643
  };
43369
43644
  }
43370
43645
  function runFfprobeJson(args) {
43371
- return new Promise((resolve42, reject) => {
43646
+ return new Promise((resolve43, reject) => {
43372
43647
  const proc = spawn9("ffprobe", args);
43373
43648
  let stdout2 = "";
43374
43649
  let stderr = "";
@@ -43391,7 +43666,7 @@ function runFfprobeJson(args) {
43391
43666
  return;
43392
43667
  }
43393
43668
  try {
43394
- resolve42(JSON.parse(stdout2));
43669
+ resolve43(JSON.parse(stdout2));
43395
43670
  } catch (err) {
43396
43671
  reject(new Error(`Failed to parse ffprobe output: ${err.message}`));
43397
43672
  }
@@ -43647,18 +43922,18 @@ __export(studioServer_exports, {
43647
43922
  import { Hono as Hono5 } from "hono";
43648
43923
  import { streamSSE as streamSSE3 } from "hono/streaming";
43649
43924
  import { existsSync as existsSync47, readFileSync as readFileSync32, writeFileSync as writeFileSync24, statSync as statSync17 } from "fs";
43650
- import { resolve as resolve23, join as join57, basename as basename5 } from "path";
43925
+ import { resolve as resolve24, join as join57, basename as basename5 } from "path";
43651
43926
  function resolveDistDir() {
43652
43927
  return resolveStudioBundle().dir;
43653
43928
  }
43654
43929
  function resolveStudioBundle() {
43655
- const builtPath = resolve23(__dirname, "studio");
43656
- const builtIndex = resolve23(builtPath, "index.html");
43930
+ const builtPath = resolve24(__dirname, "studio");
43931
+ const builtIndex = resolve24(builtPath, "index.html");
43657
43932
  if (existsSync47(builtIndex)) {
43658
43933
  return { dir: builtPath, indexPath: builtIndex, available: true, checkedPaths: [builtIndex] };
43659
43934
  }
43660
- const devPath = resolve23(__dirname, "..", "..", "..", "studio", "dist");
43661
- const devIndex = resolve23(devPath, "index.html");
43935
+ const devPath = resolve24(__dirname, "..", "..", "..", "studio", "dist");
43936
+ const devIndex = resolve24(devPath, "index.html");
43662
43937
  if (existsSync47(devIndex)) {
43663
43938
  return {
43664
43939
  dir: devPath,
@@ -43675,11 +43950,11 @@ function resolveStudioBundle() {
43675
43950
  };
43676
43951
  }
43677
43952
  function resolveRuntimePath() {
43678
- const builtPath = resolve23(__dirname, "hyperframe-runtime.js");
43953
+ const builtPath = resolve24(__dirname, "hyperframe-runtime.js");
43679
43954
  if (existsSync47(builtPath)) return builtPath;
43680
- const iifePath = resolve23(__dirname, "hyperframe.runtime.iife.js");
43955
+ const iifePath = resolve24(__dirname, "hyperframe.runtime.iife.js");
43681
43956
  if (existsSync47(iifePath)) return iifePath;
43682
- const devPath = resolve23(
43957
+ const devPath = resolve24(
43683
43958
  __dirname,
43684
43959
  "..",
43685
43960
  "..",
@@ -43776,7 +44051,7 @@ function createStudioServer(options) {
43776
44051
  return injectDeterministicFontFaces2(html);
43777
44052
  },
43778
44053
  getProjectSignature(dir) {
43779
- if (resolve23(dir) !== resolve23(projectDir)) return createProjectSignature(dir);
44054
+ if (resolve24(dir) !== resolve24(projectDir)) return createProjectSignature(dir);
43780
44055
  cachedProjectSignature ??= createProjectSignature(projectDir);
43781
44056
  return cachedProjectSignature;
43782
44057
  },
@@ -43813,7 +44088,8 @@ function createStudioServer(options) {
43813
44088
  quality: opts.quality,
43814
44089
  format: opts.format,
43815
44090
  outputResolution: opts.outputResolution,
43816
- ...manualEditsRenderScript ? { renderBodyScripts: [manualEditsRenderScript] } : {}
44091
+ ...manualEditsRenderScript ? { renderBodyScripts: [manualEditsRenderScript] } : {},
44092
+ ...opts.composition ? { entryFile: opts.composition } : {}
43817
44093
  });
43818
44094
  const startTime = Date.now();
43819
44095
  const onProgress = (j3) => {
@@ -43933,7 +44209,7 @@ function createStudioServer(options) {
43933
44209
  return api.fetch(forwardReq);
43934
44210
  });
43935
44211
  const serveStudioStaticFile = (c3) => {
43936
- const filePath = resolve23(studioDir, c3.req.path.slice(1));
44212
+ const filePath = resolve24(studioDir, c3.req.path.slice(1));
43937
44213
  if (!existsSync47(filePath) || !statSync17(filePath).isFile()) return c3.text("not found", 404);
43938
44214
  const content = readFileSync32(filePath);
43939
44215
  return new Response(content, {
@@ -43944,7 +44220,7 @@ function createStudioServer(options) {
43944
44220
  app.get("/icons/*", serveStudioStaticFile);
43945
44221
  app.get("/favicon.svg", serveStudioStaticFile);
43946
44222
  app.get("*", (c3) => {
43947
- const indexPath = resolve23(studioDir, "index.html");
44223
+ const indexPath = resolve24(studioDir, "index.html");
43948
44224
  if (!existsSync47(indexPath)) {
43949
44225
  return c3.html(
43950
44226
  `<!doctype html>
@@ -44028,14 +44304,14 @@ __export(preview_exports, {
44028
44304
  });
44029
44305
  import { spawn as spawn10 } from "child_process";
44030
44306
  import { existsSync as existsSync48, lstatSync as lstatSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync30 } from "fs";
44031
- import { resolve as resolve24, dirname as dirname18, basename as basename6, join as join58 } from "path";
44307
+ import { resolve as resolve25, dirname as dirname18, basename as basename6, join as join58 } from "path";
44032
44308
  import { fileURLToPath as fileURLToPath6 } from "url";
44033
44309
  import { createRequire as createRequire2 } from "module";
44034
- async function runDevMode(dir, projectName) {
44310
+ async function runDevMode(dir, options) {
44035
44311
  const thisFile = fileURLToPath6(import.meta.url);
44036
- const repoRoot = resolve24(dirname18(thisFile), "..", "..", "..", "..");
44312
+ const repoRoot = resolve25(dirname18(thisFile), "..", "..", "..", "..");
44037
44313
  const projectsDir = join58(repoRoot, "packages", "studio", "data", "projects");
44038
- const pName = projectName ?? basename6(dir);
44314
+ const pName = options?.projectName ?? basename6(dir);
44039
44315
  const symlinkPath = join58(projectsDir, pName);
44040
44316
  mkdirSync30(projectsDir, { recursive: true });
44041
44317
  let createdSymlink = false;
@@ -44045,7 +44321,7 @@ async function runDevMode(dir, projectName) {
44045
44321
  const stat3 = lstatSync2(symlinkPath);
44046
44322
  if (stat3.isSymbolicLink()) {
44047
44323
  const target = readlinkSync(symlinkPath);
44048
- if (resolve24(target) !== resolve24(dir)) {
44324
+ if (resolve25(target) !== resolve25(dir)) {
44049
44325
  unlinkSync5(symlinkPath);
44050
44326
  }
44051
44327
  }
@@ -44078,9 +44354,11 @@ async function runDevMode(dir, projectName) {
44078
44354
  console.log();
44079
44355
  console.log(` ${c2.dim("Press Ctrl+C to stop")}`);
44080
44356
  console.log();
44081
- const urlToOpen = `${frontendUrl}#project/${pName}`;
44082
- import("open").then((mod) => mod.default(urlToOpen)).catch(() => {
44083
- });
44357
+ if (!options?.noOpen) {
44358
+ const urlToOpen = `${frontendUrl}#project/${pName}`;
44359
+ import("open").then((mod) => mod.default(urlToOpen)).catch(() => {
44360
+ });
44361
+ }
44084
44362
  child.stdout?.removeListener("data", handleOutput);
44085
44363
  child.stderr?.removeListener("data", handleOutput);
44086
44364
  }
@@ -44099,8 +44377,8 @@ async function runDevMode(dir, projectName) {
44099
44377
  }
44100
44378
  });
44101
44379
  }
44102
- return new Promise((resolve42) => {
44103
- child.on("close", () => resolve42());
44380
+ return new Promise((resolve43) => {
44381
+ child.on("close", () => resolve43());
44104
44382
  });
44105
44383
  }
44106
44384
  function hasLocalStudio(dir) {
@@ -44112,17 +44390,17 @@ function hasLocalStudio(dir) {
44112
44390
  return false;
44113
44391
  }
44114
44392
  }
44115
- async function runLocalStudioMode(dir, projectName) {
44393
+ async function runLocalStudioMode(dir, options) {
44116
44394
  const req = createRequire2(join58(dir, "package.json"));
44117
44395
  const studioPkgPath = dirname18(req.resolve("@hyperframes/studio/package.json"));
44118
- const pName = projectName ?? basename6(dir);
44396
+ const pName = options?.projectName ?? basename6(dir);
44119
44397
  const projectsDir = join58(studioPkgPath, "data", "projects");
44120
44398
  const symlinkPath = join58(projectsDir, pName);
44121
44399
  mkdirSync30(projectsDir, { recursive: true });
44122
44400
  let createdSymlink = false;
44123
44401
  if (dir !== symlinkPath) {
44124
44402
  if (existsSync48(symlinkPath) && lstatSync2(symlinkPath).isSymbolicLink()) {
44125
- if (resolve24(readlinkSync(symlinkPath)) !== resolve24(dir)) {
44403
+ if (resolve25(readlinkSync(symlinkPath)) !== resolve25(dir)) {
44126
44404
  unlinkSync5(symlinkPath);
44127
44405
  }
44128
44406
  }
@@ -44152,8 +44430,10 @@ async function runLocalStudioMode(dir, projectName) {
44152
44430
  console.log();
44153
44431
  console.log(` ${c2.dim("Press Ctrl+C to stop")}`);
44154
44432
  console.log();
44155
- import("open").then((mod) => mod.default(`${url}#project/${pName}`)).catch(() => {
44156
- });
44433
+ if (!options?.noOpen) {
44434
+ import("open").then((mod) => mod.default(`${url}#project/${pName}`)).catch(() => {
44435
+ });
44436
+ }
44157
44437
  }
44158
44438
  }
44159
44439
  child.stdout?.on("data", handleOutput);
@@ -44170,13 +44450,13 @@ async function runLocalStudioMode(dir, projectName) {
44170
44450
  }
44171
44451
  });
44172
44452
  }
44173
- return new Promise((resolve42) => {
44174
- child.on("close", () => resolve42());
44453
+ return new Promise((resolve43) => {
44454
+ child.on("close", () => resolve43());
44175
44455
  });
44176
44456
  }
44177
- async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
44457
+ async function runEmbeddedMode(dir, startPort, options) {
44178
44458
  const { createStudioServer: createStudioServer2, resolveStudioBundle: resolveStudioBundle2 } = await Promise.resolve().then(() => (init_studioServer(), studioServer_exports));
44179
- const pName = projectName ?? basename6(dir);
44459
+ const pName = options?.projectName ?? basename6(dir);
44180
44460
  const studioBundle = resolveStudioBundle2();
44181
44461
  ge(c2.bold("hyperframes preview"));
44182
44462
  const s2 = ft();
@@ -44197,7 +44477,7 @@ async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
44197
44477
  const { app } = createStudioServer2({ projectDir: dir, projectName: pName });
44198
44478
  let result;
44199
44479
  try {
44200
- result = await findPortAndServe(app.fetch, startPort, dir, forceNew);
44480
+ result = await findPortAndServe(app.fetch, startPort, dir, !!options?.forceNew);
44201
44481
  } catch (err) {
44202
44482
  s2.stop(c2.error("Failed to start studio"));
44203
44483
  console.error();
@@ -44217,8 +44497,10 @@ async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
44217
44497
  ` ${c2.dim("Reusing existing server. Use --force-new to start a fresh instance.")}`
44218
44498
  );
44219
44499
  console.log();
44220
- import("open").then((mod) => mod.default(`${url2}#project/${pName}`)).catch(() => {
44221
- });
44500
+ if (!options?.noOpen) {
44501
+ import("open").then((mod) => mod.default(`${url2}#project/${pName}`)).catch(() => {
44502
+ });
44503
+ }
44222
44504
  return;
44223
44505
  }
44224
44506
  const url = `http://localhost:${result.port}`;
@@ -44236,8 +44518,10 @@ async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
44236
44518
  console.log();
44237
44519
  console.log(` ${c2.dim("Press Ctrl+C to stop")}`);
44238
44520
  console.log();
44239
- import("open").then((mod) => mod.default(`${url}#project/${pName}`)).catch(() => {
44240
- });
44521
+ if (!options?.noOpen) {
44522
+ import("open").then((mod) => mod.default(`${url}#project/${pName}`)).catch(() => {
44523
+ });
44524
+ }
44241
44525
  let rl;
44242
44526
  if (process.platform === "win32") {
44243
44527
  const readline = await import("readline");
@@ -44279,6 +44563,7 @@ var init_preview2 = __esm({
44279
44563
  ["Preview a specific project directory", "hyperframes preview ./my-video"],
44280
44564
  ["Use a custom port", "hyperframes preview --port 8080"],
44281
44565
  ["Force a new server even if one is already running", "hyperframes preview --force-new"],
44566
+ ["Start without opening the browser", "hyperframes preview --no-open"],
44282
44567
  ["List all active preview servers", "hyperframes preview --list"],
44283
44568
  ["Kill all active preview servers", "hyperframes preview --kill-all"]
44284
44569
  ];
@@ -44301,6 +44586,11 @@ var init_preview2 = __esm({
44301
44586
  type: "boolean",
44302
44587
  description: "Kill all active preview servers and exit",
44303
44588
  default: false
44589
+ },
44590
+ open: {
44591
+ type: "boolean",
44592
+ default: true,
44593
+ description: "Open browser automatically"
44304
44594
  }
44305
44595
  },
44306
44596
  async run({ args }) {
@@ -44338,7 +44628,7 @@ var init_preview2 = __esm({
44338
44628
  return;
44339
44629
  }
44340
44630
  const rawArg = args.dir;
44341
- const dir = resolve24(rawArg ?? ".");
44631
+ const dir = resolve25(rawArg ?? ".");
44342
44632
  const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
44343
44633
  const projectName = isImplicitCwd ? basename6(process.env.PWD ?? dir) : basename6(dir);
44344
44634
  const indexPath = join58(dir, "index.html");
@@ -44351,14 +44641,15 @@ var init_preview2 = __esm({
44351
44641
  console.log();
44352
44642
  }
44353
44643
  }
44644
+ const noOpen = !args.open;
44354
44645
  if (isDevMode()) {
44355
- return runDevMode(dir, projectName);
44646
+ return runDevMode(dir, { projectName, noOpen });
44356
44647
  }
44357
44648
  if (hasLocalStudio(dir)) {
44358
- return runLocalStudioMode(dir, projectName);
44649
+ return runLocalStudioMode(dir, { projectName, noOpen });
44359
44650
  }
44360
44651
  const forceNew = !!args["force-new"];
44361
- return runEmbeddedMode(dir, startPort, projectName, forceNew);
44652
+ return runEmbeddedMode(dir, startPort, { projectName, forceNew, noOpen });
44362
44653
  }
44363
44654
  });
44364
44655
  }
@@ -44381,7 +44672,7 @@ import {
44381
44672
  readFileSync as readFileSync33,
44382
44673
  readdirSync as readdirSync21
44383
44674
  } from "fs";
44384
- import { resolve as resolve25, basename as basename7, join as join59, dirname as dirname19 } from "path";
44675
+ import { resolve as resolve26, basename as basename7, join as join59, dirname as dirname19 } from "path";
44385
44676
  import { fileURLToPath as fileURLToPath7 } from "url";
44386
44677
  import { execFileSync as execFileSync5, spawn as spawn11 } from "child_process";
44387
44678
  function probeVideo(filePath) {
@@ -44451,8 +44742,8 @@ function transcodeToMp4(inputPath, outputPath) {
44451
44742
  }
44452
44743
  function resolveAssetDir(devSegments, builtSegments) {
44453
44744
  const base = dirname19(fileURLToPath7(import.meta.url));
44454
- const devPath = resolve25(base, ...devSegments);
44455
- const builtPath = resolve25(base, ...builtSegments);
44745
+ const devPath = resolve26(base, ...devSegments);
44746
+ const builtPath = resolve26(base, ...builtSegments);
44456
44747
  return existsSync49(devPath) ? devPath : builtPath;
44457
44748
  }
44458
44749
  function getStaticTemplateDir(templateId) {
@@ -44480,7 +44771,7 @@ function buildPackageScripts() {
44480
44771
  };
44481
44772
  }
44482
44773
  function writeDefaultPackageJson(destDir, projectName) {
44483
- const packageJsonPath = resolve25(destDir, "package.json");
44774
+ const packageJsonPath = resolve26(destDir, "package.json");
44484
44775
  if (existsSync49(packageJsonPath)) return;
44485
44776
  writeFileSync25(
44486
44777
  packageJsonPath,
@@ -44623,7 +44914,7 @@ async function handleVideoFile(videoPath, destDir, interactive) {
44623
44914
  }
44624
44915
  if (shouldTranscode) {
44625
44916
  const mp4Name = localVideoName.replace(/\.[^.]+$/, ".mp4");
44626
- const mp4Path = resolve25(destDir, mp4Name);
44917
+ const mp4Path = resolve26(destDir, mp4Name);
44627
44918
  const spin = ft();
44628
44919
  spin.start("Transcoding to H.264 MP4...");
44629
44920
  const ok = await transcodeToMp4(videoPath, mp4Path);
@@ -44632,10 +44923,10 @@ async function handleVideoFile(videoPath, destDir, interactive) {
44632
44923
  localVideoName = mp4Name;
44633
44924
  } else {
44634
44925
  spin.stop(c2.warn("Transcode failed \u2014 copying original file"));
44635
- copyFileSync5(videoPath, resolve25(destDir, localVideoName));
44926
+ copyFileSync5(videoPath, resolve26(destDir, localVideoName));
44636
44927
  }
44637
44928
  } else {
44638
- copyFileSync5(videoPath, resolve25(destDir, localVideoName));
44929
+ copyFileSync5(videoPath, resolve26(destDir, localVideoName));
44639
44930
  }
44640
44931
  } else {
44641
44932
  if (interactive) {
@@ -44645,10 +44936,10 @@ async function handleVideoFile(videoPath, destDir, interactive) {
44645
44936
  console.log(c2.warn("ffmpeg not installed \u2014 cannot transcode. Copying original."));
44646
44937
  console.log(c2.dim("Install: ") + c2.accent("brew install ffmpeg"));
44647
44938
  }
44648
- copyFileSync5(videoPath, resolve25(destDir, localVideoName));
44939
+ copyFileSync5(videoPath, resolve26(destDir, localVideoName));
44649
44940
  }
44650
44941
  } else {
44651
- copyFileSync5(videoPath, resolve25(destDir, localVideoName));
44942
+ copyFileSync5(videoPath, resolve26(destDir, localVideoName));
44652
44943
  }
44653
44944
  return { meta, localVideoName };
44654
44945
  }
@@ -44712,7 +45003,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
44712
45003
  if (tailwind) writeTailwindSupport(destDir);
44713
45004
  if (resolution) applyResolutionPreset(destDir, resolution);
44714
45005
  writeFileSync25(
44715
- resolve25(destDir, "meta.json"),
45006
+ resolve26(destDir, "meta.json"),
44716
45007
  JSON.stringify(
44717
45008
  {
44718
45009
  id: name,
@@ -44724,7 +45015,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
44724
45015
  ),
44725
45016
  "utf-8"
44726
45017
  );
44727
- if (!existsSync49(resolve25(destDir, "hyperframes.json"))) {
45018
+ if (!existsSync49(resolve26(destDir, "hyperframes.json"))) {
44728
45019
  const { writeProjectConfig: writeProjectConfig2, DEFAULT_PROJECT_CONFIG: DEFAULT_PROJECT_CONFIG2 } = await Promise.resolve().then(() => (init_projectConfig(), projectConfig_exports));
44729
45020
  writeProjectConfig2(destDir, DEFAULT_PROJECT_CONFIG2);
44730
45021
  }
@@ -44733,7 +45024,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
44733
45024
  if (existsSync49(sharedDir)) {
44734
45025
  for (const entry of readdirSync21(sharedDir, { withFileTypes: true })) {
44735
45026
  const src = join59(sharedDir, entry.name);
44736
- const dest = resolve25(destDir, entry.name);
45027
+ const dest = resolve26(destDir, entry.name);
44737
45028
  if (entry.isFile() || entry.isSymbolicLink()) {
44738
45029
  copyFileSync5(src, dest);
44739
45030
  }
@@ -44889,7 +45180,7 @@ var init_init = __esm({
44889
45180
  if (!interactive) {
44890
45181
  const templateId2 = exampleFlag ?? "blank";
44891
45182
  const name2 = args.name ?? "my-video";
44892
- const destDir2 = resolve25(name2);
45183
+ const destDir2 = resolve26(name2);
44893
45184
  if (existsSync49(destDir2) && readdirSync21(destDir2).length > 0) {
44894
45185
  console.error(c2.error(`Directory already exists and is not empty: ${name2}`));
44895
45186
  process.exit(1);
@@ -44903,7 +45194,7 @@ var init_init = __esm({
44903
45194
  process.exit(1);
44904
45195
  }
44905
45196
  if (videoFlag) {
44906
- const videoPath = resolve25(videoFlag);
45197
+ const videoPath = resolve26(videoFlag);
44907
45198
  if (!existsSync49(videoPath)) {
44908
45199
  console.error(c2.error(`Video file not found: ${videoFlag}`));
44909
45200
  process.exit(1);
@@ -44917,13 +45208,13 @@ var init_init = __esm({
44917
45208
  );
44918
45209
  }
44919
45210
  if (audioFlag) {
44920
- const audioPath = resolve25(audioFlag);
45211
+ const audioPath = resolve26(audioFlag);
44921
45212
  if (!existsSync49(audioPath)) {
44922
45213
  console.error(c2.error(`Audio file not found: ${audioFlag}`));
44923
45214
  process.exit(1);
44924
45215
  }
44925
45216
  sourceFilePath2 = audioPath;
44926
- copyFileSync5(audioPath, resolve25(destDir2, basename7(audioPath)));
45217
+ copyFileSync5(audioPath, resolve26(destDir2, basename7(audioPath)));
44927
45218
  console.log(`Audio: ${basename7(audioPath)}`);
44928
45219
  }
44929
45220
  if (sourceFilePath2 && !skipTranscribe) {
@@ -44965,7 +45256,7 @@ var init_init = __esm({
44965
45256
  process.exit(1);
44966
45257
  }
44967
45258
  trackInitTemplate(templateId2, { tailwind });
44968
- const transcriptFile2 = resolve25(destDir2, "transcript.json");
45259
+ const transcriptFile2 = resolve26(destDir2, "transcript.json");
44969
45260
  if (existsSync49(transcriptFile2)) {
44970
45261
  await patchTranscript(destDir2, transcriptFile2);
44971
45262
  }
@@ -45020,7 +45311,7 @@ var init_init = __esm({
45020
45311
  }
45021
45312
  name = nameResult;
45022
45313
  }
45023
- const destDir = resolve25(name);
45314
+ const destDir = resolve26(name);
45024
45315
  if (existsSync49(destDir) && readdirSync21(destDir).length > 0) {
45025
45316
  const overwrite = await ue({
45026
45317
  message: `Directory ${c2.accent(name)} already exists and is not empty. Overwrite?`,
@@ -45035,7 +45326,7 @@ var init_init = __esm({
45035
45326
  let sourceFilePath;
45036
45327
  let videoDuration;
45037
45328
  if (videoFlag) {
45038
- const videoPath = resolve25(videoFlag);
45329
+ const videoPath = resolve26(videoFlag);
45039
45330
  if (!existsSync49(videoPath)) {
45040
45331
  R2.error(`File not found: ${videoFlag}`);
45041
45332
  me("Setup cancelled.");
@@ -45047,7 +45338,7 @@ var init_init = __esm({
45047
45338
  localVideoName = result.localVideoName;
45048
45339
  videoDuration = result.meta.durationSeconds;
45049
45340
  } else if (audioFlag) {
45050
- const audioPath = resolve25(audioFlag);
45341
+ const audioPath = resolve26(audioFlag);
45051
45342
  if (!existsSync49(audioPath)) {
45052
45343
  R2.error(`File not found: ${audioFlag}`);
45053
45344
  me("Setup cancelled.");
@@ -45055,7 +45346,7 @@ var init_init = __esm({
45055
45346
  }
45056
45347
  mkdirSync31(destDir, { recursive: true });
45057
45348
  sourceFilePath = audioPath;
45058
- copyFileSync5(audioPath, resolve25(destDir, basename7(audioPath)));
45349
+ copyFileSync5(audioPath, resolve26(destDir, basename7(audioPath)));
45059
45350
  R2.info(`Audio copied to ${c2.accent(basename7(audioPath))}`);
45060
45351
  }
45061
45352
  if (sourceFilePath) {
@@ -45148,7 +45439,7 @@ ${c2.dim("Use --example blank for offline use.")}`
45148
45439
  process.exit(1);
45149
45440
  }
45150
45441
  trackInitTemplate(templateId, { tailwind });
45151
- const transcriptFile = resolve25(destDir, "transcript.json");
45442
+ const transcriptFile = resolve26(destDir, "transcript.json");
45152
45443
  if (existsSync49(transcriptFile)) {
45153
45444
  await patchTranscript(destDir, transcriptFile);
45154
45445
  }
@@ -45236,7 +45527,7 @@ __export(add_exports, {
45236
45527
  runAdd: () => runAdd
45237
45528
  });
45238
45529
  import { existsSync as existsSync50 } from "fs";
45239
- import { resolve as resolve26, relative as relative6 } from "path";
45530
+ import { resolve as resolve27, relative as relative6 } from "path";
45240
45531
  function remapTarget(item, originalTarget, paths) {
45241
45532
  if (item.type === "hyperframes:block") {
45242
45533
  const blocksDir = paths.blocks.replace(/\/+$/, "");
@@ -45259,10 +45550,10 @@ function buildSnippet(item, relativeTarget) {
45259
45550
  return "";
45260
45551
  }
45261
45552
  async function runAdd(opts) {
45262
- const projectDir = resolve26(opts.projectDir);
45553
+ const projectDir = resolve27(opts.projectDir);
45263
45554
  let config = loadProjectConfig(projectDir);
45264
45555
  const hasConfig = existsSync50(projectConfigPath(projectDir));
45265
- if (!hasConfig && existsSync50(resolve26(projectDir, "index.html"))) {
45556
+ if (!hasConfig && existsSync50(resolve27(projectDir, "index.html"))) {
45266
45557
  writeProjectConfig(projectDir, DEFAULT_PROJECT_CONFIG);
45267
45558
  config = DEFAULT_PROJECT_CONFIG;
45268
45559
  }
@@ -45361,7 +45652,7 @@ var init_add = __esm({
45361
45652
  }
45362
45653
  },
45363
45654
  async run({ args }) {
45364
- const projectDir = resolve26(args.dir ?? process.cwd());
45655
+ const projectDir = resolve27(args.dir ?? process.cwd());
45365
45656
  const json = args.json === true;
45366
45657
  const skipClipboard = args["no-clipboard"] === true;
45367
45658
  const hasConfigBefore = existsSync50(projectConfigPath(projectDir));
@@ -45397,7 +45688,7 @@ var init_add = __esm({
45397
45688
  process.exit(1);
45398
45689
  }
45399
45690
  let config = loadProjectConfig(projectDir);
45400
- if (!existsSync50(projectConfigPath(projectDir)) && existsSync50(resolve26(projectDir, "index.html"))) {
45691
+ if (!existsSync50(projectConfigPath(projectDir)) && existsSync50(resolve27(projectDir, "index.html"))) {
45401
45692
  writeProjectConfig(projectDir, DEFAULT_PROJECT_CONFIG);
45402
45693
  config = DEFAULT_PROJECT_CONFIG;
45403
45694
  }
@@ -45449,7 +45740,7 @@ __export(catalog_exports, {
45449
45740
  default: () => catalog_default,
45450
45741
  examples: () => examples4
45451
45742
  });
45452
- import { resolve as resolve27 } from "path";
45743
+ import { resolve as resolve28 } from "path";
45453
45744
  var examples4, catalog_default;
45454
45745
  var init_catalog = __esm({
45455
45746
  "src/commands/catalog.ts"() {
@@ -45493,7 +45784,7 @@ var init_catalog = __esm({
45493
45784
  async run({ args }) {
45494
45785
  const json = args.json === true;
45495
45786
  const interactive = args["human-friendly"] === true;
45496
- const dir = resolve27(process.cwd());
45787
+ const dir = resolve28(process.cwd());
45497
45788
  const config = loadProjectConfig(dir) ?? DEFAULT_PROJECT_CONFIG;
45498
45789
  let typeFilter;
45499
45790
  if (args.type === "block") typeFilter = "hyperframes:block";
@@ -45618,11 +45909,11 @@ var init_format = __esm({
45618
45909
 
45619
45910
  // src/utils/project.ts
45620
45911
  import { existsSync as existsSync51, statSync as statSync18 } from "fs";
45621
- import { resolve as resolve28, basename as basename8 } from "path";
45912
+ import { resolve as resolve29, basename as basename8 } from "path";
45622
45913
  function resolveProject(dirArg) {
45623
- const dir = resolve28(dirArg ?? ".");
45914
+ const dir = resolve29(dirArg ?? ".");
45624
45915
  const name = basename8(dir);
45625
- const indexPath = resolve28(dir, "index.html");
45916
+ const indexPath = resolve29(dir, "index.html");
45626
45917
  if (!existsSync51(dir) || !statSync18(dir).isDirectory()) {
45627
45918
  errorBox("Not a directory: " + dir);
45628
45919
  process.exit(1);
@@ -45651,7 +45942,7 @@ __export(play_exports, {
45651
45942
  examples: () => examples5
45652
45943
  });
45653
45944
  import { existsSync as existsSync52, readFileSync as readFileSync34 } from "fs";
45654
- import { resolve as resolve29, dirname as dirname20 } from "path";
45945
+ import { resolve as resolve30, dirname as dirname20 } from "path";
45655
45946
  function commandDir() {
45656
45947
  return dirname20(new URL(import.meta.url).pathname);
45657
45948
  }
@@ -45659,10 +45950,10 @@ function resolveRuntimePath2() {
45659
45950
  const d2 = commandDir();
45660
45951
  const candidates = [
45661
45952
  // Bundled with CLI dist
45662
- resolve29(d2, "hyperframe-runtime.js"),
45663
- resolve29(d2, "..", "hyperframe-runtime.js"),
45953
+ resolve30(d2, "hyperframe-runtime.js"),
45954
+ resolve30(d2, "..", "hyperframe-runtime.js"),
45664
45955
  // Monorepo dev: commands/ → src/ → cli/ → packages/ then into core/dist/
45665
- resolve29(d2, "..", "..", "..", "core", "dist", "hyperframe.runtime.iife.js")
45956
+ resolve30(d2, "..", "..", "..", "core", "dist", "hyperframe.runtime.iife.js")
45666
45957
  ];
45667
45958
  for (const p2 of candidates) {
45668
45959
  if (existsSync52(p2)) return p2;
@@ -45673,10 +45964,10 @@ function resolvePlayerPath() {
45673
45964
  const d2 = commandDir();
45674
45965
  const candidates = [
45675
45966
  // Monorepo dev: commands/ → src/ → cli/ → packages/ then into player/dist/
45676
- resolve29(d2, "..", "..", "..", "player", "dist", "hyperframes-player.global.js"),
45967
+ resolve30(d2, "..", "..", "..", "player", "dist", "hyperframes-player.global.js"),
45677
45968
  // Bundled with CLI dist
45678
- resolve29(d2, "hyperframes-player.global.js"),
45679
- resolve29(d2, "..", "hyperframes-player.global.js")
45969
+ resolve30(d2, "hyperframes-player.global.js"),
45970
+ resolve30(d2, "..", "hyperframes-player.global.js")
45680
45971
  ];
45681
45972
  for (const p2 of candidates) {
45682
45973
  if (existsSync52(p2)) return p2;
@@ -45739,13 +46030,19 @@ var init_play = __esm({
45739
46030
  examples5 = [
45740
46031
  ["Play the current project", "hyperframes play"],
45741
46032
  ["Play a specific project directory", "hyperframes play ./my-video"],
45742
- ["Use a custom port", "hyperframes play --port 8080"]
46033
+ ["Use a custom port", "hyperframes play --port 8080"],
46034
+ ["Start without opening the browser", "hyperframes play --no-open"]
45743
46035
  ];
45744
46036
  play_default = defineCommand({
45745
46037
  meta: { name: "play", description: "Play a composition in a lightweight browser player" },
45746
46038
  args: {
45747
46039
  dir: { type: "positional", description: "Project directory", required: false },
45748
- port: { type: "string", description: "Port to run the player server on", default: "3003" }
46040
+ port: { type: "string", description: "Port to run the player server on", default: "3003" },
46041
+ open: {
46042
+ type: "boolean",
46043
+ default: true,
46044
+ description: "Open browser automatically"
46045
+ }
45749
46046
  },
45750
46047
  async run({ args }) {
45751
46048
  const project = resolveProject(args.dir);
@@ -45781,7 +46078,7 @@ var init_play = __esm({
45781
46078
  });
45782
46079
  app.get("/composition/*", async (ctx) => {
45783
46080
  const reqPath = ctx.req.path.replace("/composition/", "");
45784
- const filePath = resolve29(project.dir, reqPath);
46081
+ const filePath = resolve30(project.dir, reqPath);
45785
46082
  if (!filePath.startsWith(project.dir)) return ctx.text("Forbidden", 403);
45786
46083
  if (!existsSync52(filePath)) return ctx.text("Not found", 404);
45787
46084
  const content = readFileSync34(filePath, "utf-8");
@@ -45849,8 +46146,10 @@ var init_play = __esm({
45849
46146
  console.log();
45850
46147
  console.log(` ${c2.dim("Press Ctrl+C to stop")}`);
45851
46148
  console.log();
45852
- import("open").then((mod) => mod.default(url)).catch(() => {
45853
- });
46149
+ if (args.open) {
46150
+ import("open").then((mod) => mod.default(url)).catch(() => {
46151
+ });
46152
+ }
45854
46153
  return new Promise(() => {
45855
46154
  });
45856
46155
  }
@@ -46099,7 +46398,7 @@ __export(publish_exports, {
46099
46398
  default: () => publish_default,
46100
46399
  examples: () => examples6
46101
46400
  });
46102
- import { basename as basename10, resolve as resolve30 } from "path";
46401
+ import { basename as basename10, resolve as resolve31 } from "path";
46103
46402
  import { existsSync as existsSync53 } from "fs";
46104
46403
  import { join as join61 } from "path";
46105
46404
  var examples6, publish_default;
@@ -46133,7 +46432,7 @@ var init_publish = __esm({
46133
46432
  },
46134
46433
  async run({ args }) {
46135
46434
  const rawArg = args.dir;
46136
- const dir = resolve30(rawArg ?? ".");
46435
+ const dir = resolve31(rawArg ?? ".");
46137
46436
  const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
46138
46437
  const projectName = isImplicitCwd ? basename10(process.env["PWD"] ?? dir) : basename10(dir);
46139
46438
  const indexPath = join61(dir, "index.html");
@@ -46260,7 +46559,8 @@ function buildDockerRunArgs(input) {
46260
46559
  ...options.hdrMode === "force-sdr" ? ["--sdr"] : [],
46261
46560
  ...options.variables && Object.keys(options.variables).length > 0 ? ["--variables", JSON.stringify(options.variables)] : [],
46262
46561
  ...options.entryFile ? ["--composition", options.entryFile] : [],
46263
- ...options.outputResolution ? ["--resolution", options.outputResolution] : []
46562
+ ...options.outputResolution ? ["--resolution", options.outputResolution] : [],
46563
+ ...options.pageSideCompositing === false ? ["--no-page-side-compositing"] : []
46264
46564
  ];
46265
46565
  }
46266
46566
  var init_dockerRunArgs = __esm({
@@ -46333,7 +46633,7 @@ __export(render_exports, {
46333
46633
  });
46334
46634
  import { mkdirSync as mkdirSync32, readdirSync as readdirSync23, readFileSync as readFileSync36, statSync as statSync20, writeFileSync as writeFileSync26, rmSync as rmSync14 } from "fs";
46335
46635
  import { cpus as cpus4, freemem as freemem3, tmpdir as tmpdir4 } from "os";
46336
- import { resolve as resolve31, dirname as dirname21, join as join62, basename as basename11 } from "path";
46636
+ import { resolve as resolve32, dirname as dirname21, join as join62, basename as basename11 } from "path";
46337
46637
  import { execFileSync as execFileSync6, spawn as spawn12 } from "child_process";
46338
46638
  function formatFpsParseError(input, reason) {
46339
46639
  switch (reason) {
@@ -46351,7 +46651,7 @@ function formatFpsParseError(input, reason) {
46351
46651
  return `Got "${input}". Decimal frame rates are ambiguous \u2014 use the exact rational form instead (e.g. 30000/1001 for 29.97).`;
46352
46652
  }
46353
46653
  }
46354
- function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync36(resolve31(p2), "utf8")) {
46654
+ function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync36(resolve32(p2), "utf8")) {
46355
46655
  if (inline != null && filePath != null) {
46356
46656
  return { ok: false, error: { kind: "conflict" } };
46357
46657
  }
@@ -46450,8 +46750,8 @@ function dockerImageTag(version) {
46450
46750
  return `${DOCKER_IMAGE_PREFIX}:${version}`;
46451
46751
  }
46452
46752
  function resolveDockerfilePath() {
46453
- const builtPath = resolve31(__dirname, "docker", "Dockerfile.render");
46454
- const devPath = resolve31(__dirname, "..", "src", "docker", "Dockerfile.render");
46753
+ const builtPath = resolve32(__dirname, "docker", "Dockerfile.render");
46754
+ const devPath = resolve32(__dirname, "..", "src", "docker", "Dockerfile.render");
46455
46755
  for (const p2 of [builtPath, devPath]) {
46456
46756
  try {
46457
46757
  statSync20(p2);
@@ -46528,8 +46828,8 @@ async function renderDocker(projectDir, outputPath, options) {
46528
46828
  const outputFilename = basename11(outputPath);
46529
46829
  const dockerArgs = buildDockerRunArgs({
46530
46830
  imageTag,
46531
- projectDir: resolve31(projectDir),
46532
- outputDir: resolve31(outputDir),
46831
+ projectDir: resolve32(projectDir),
46832
+ outputDir: resolve32(outputDir),
46533
46833
  outputFilename,
46534
46834
  options: {
46535
46835
  fps: options.fps,
@@ -46544,7 +46844,8 @@ async function renderDocker(projectDir, outputPath, options) {
46544
46844
  quiet: options.quiet,
46545
46845
  variables: options.variables,
46546
46846
  entryFile: options.entryFile,
46547
- outputResolution: options.outputResolution
46847
+ outputResolution: options.outputResolution,
46848
+ pageSideCompositing: options.pageSideCompositing
46548
46849
  }
46549
46850
  });
46550
46851
  if (!options.quiet) {
@@ -46868,6 +47169,11 @@ var init_render2 = __esm({
46868
47169
  resolution: {
46869
47170
  type: "string",
46870
47171
  description: "Output resolution preset: landscape (1920x1080), portrait (1080x1920), landscape-4k (3840x2160), portrait-4k (2160x3840), square (1080x1080), square-4k (2160x2160). Aliases: 1080p, 4k, uhd, 1080p-square, square-1080p, 4k-square. The composition is unchanged \u2014 Chrome renders at higher DPR (deviceScaleFactor) so the captured screenshot lands at the requested dimensions. Aspect ratio must match the composition; the scale must be an integer multiple. Not yet supported with --hdr."
47172
+ },
47173
+ "page-side-compositing": {
47174
+ type: "boolean",
47175
+ description: "Run shader transitions on a page-side WebGL canvas inside Chrome instead of the Node-side layered blend. ~6\xD7 faster for SDR shader-transition renders. HDR/alpha/video content auto-disables. Use --no-page-side-compositing to force the layered path.",
47176
+ default: true
46871
47177
  }
46872
47178
  },
46873
47179
  async run({ args }) {
@@ -46918,6 +47224,9 @@ var init_render2 = __esm({
46918
47224
  }
46919
47225
  workers = parsed;
46920
47226
  }
47227
+ if (args["page-side-compositing"] === false) {
47228
+ process.env.HF_PAGE_SIDE_COMPOSITING = "false";
47229
+ }
46921
47230
  if (args["max-concurrent-renders"] != null) {
46922
47231
  const parsed = parseInt(args["max-concurrent-renders"], 10);
46923
47232
  if (isNaN(parsed) || parsed < 1 || parsed > 10) {
@@ -46929,12 +47238,12 @@ var init_render2 = __esm({
46929
47238
  }
46930
47239
  process.env.PRODUCER_MAX_CONCURRENT_RENDERS = String(parsed);
46931
47240
  }
46932
- const rendersDir = resolve31("renders");
47241
+ const rendersDir = resolve32("renders");
46933
47242
  const ext = FORMAT_EXT[format] ?? ".mp4";
46934
47243
  const now = /* @__PURE__ */ new Date();
46935
47244
  const datePart = now.toISOString().slice(0, 10);
46936
47245
  const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
46937
- const outputPath = args.output ? resolve31(args.output) : join62(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
47246
+ const outputPath = args.output ? resolve32(args.output) : join62(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
46938
47247
  mkdirSync32(dirname21(outputPath), { recursive: true });
46939
47248
  const useDocker = args.docker ?? false;
46940
47249
  const useGpu = args.gpu ?? false;
@@ -46975,8 +47284,8 @@ var init_render2 = __esm({
46975
47284
  }
46976
47285
  const entryFile = args.composition?.trim().replace(/^\.\//, "") || void 0;
46977
47286
  if (entryFile) {
46978
- const absProjectDir = resolve31(project.dir);
46979
- const entryPath = resolve31(absProjectDir, entryFile);
47287
+ const absProjectDir = resolve32(project.dir);
47288
+ const entryPath = resolve32(absProjectDir, entryFile);
46980
47289
  if (!entryPath.startsWith(absProjectDir)) {
46981
47290
  errorBox(
46982
47291
  "Invalid composition path",
@@ -47122,6 +47431,7 @@ var init_render2 = __esm({
47122
47431
  variables,
47123
47432
  entryFile,
47124
47433
  outputResolution,
47434
+ pageSideCompositing: args["page-side-compositing"] !== false,
47125
47435
  exitAfterComplete: true
47126
47436
  });
47127
47437
  } else {
@@ -47350,7 +47660,7 @@ var init_lint3 = __esm({
47350
47660
  // src/utils/staticProjectServer.ts
47351
47661
  import { createServer } from "http";
47352
47662
  import { existsSync as existsSync54, readFileSync as readFileSync37 } from "fs";
47353
- import { isAbsolute as isAbsolute8, relative as relative8, resolve as resolve32 } from "path";
47663
+ import { isAbsolute as isAbsolute8, relative as relative8, resolve as resolve33 } from "path";
47354
47664
  async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Failed to bind local HTTP server") {
47355
47665
  const server = createServer((req, res) => {
47356
47666
  const url = req.url ?? "/";
@@ -47359,7 +47669,7 @@ async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Fail
47359
47669
  res.end(html);
47360
47670
  return;
47361
47671
  }
47362
- const filePath = resolve32(projectDir, decodeURIComponent(url).replace(/^\//, ""));
47672
+ const filePath = resolve33(projectDir, decodeURIComponent(url).replace(/^\//, ""));
47363
47673
  const rel = relative8(projectDir, filePath);
47364
47674
  if (rel.startsWith("..") || isAbsolute8(rel)) {
47365
47675
  res.writeHead(403);
@@ -47597,7 +47907,7 @@ async function seekTo(page, time) {
47597
47907
  if (!fonts?.ready) return Promise.resolve();
47598
47908
  return Promise.race([
47599
47909
  fonts.ready.then(() => void 0),
47600
- new Promise((resolve42) => setTimeout(resolve42, 500))
47910
+ new Promise((resolve43) => setTimeout(resolve43, 500))
47601
47911
  ]);
47602
47912
  }).catch(() => {
47603
47913
  });
@@ -47657,7 +47967,7 @@ async function runLayoutAudit(projectDir, opts) {
47657
47967
  if (!fonts?.ready) return Promise.resolve();
47658
47968
  return Promise.race([
47659
47969
  fonts.ready.then(() => void 0),
47660
- new Promise((resolve42) => setTimeout(resolve42, 750))
47970
+ new Promise((resolve43) => setTimeout(resolve43, 750))
47661
47971
  ]);
47662
47972
  }).catch(() => {
47663
47973
  });
@@ -48000,7 +48310,7 @@ __export(compositions_exports, {
48000
48310
  parseSubComposition: () => parseSubComposition
48001
48311
  });
48002
48312
  import { existsSync as existsSync56, readFileSync as readFileSync40 } from "fs";
48003
- import { resolve as resolve33, dirname as dirname23 } from "path";
48313
+ import { resolve as resolve34, dirname as dirname23 } from "path";
48004
48314
  function countRenderableDescendants(root) {
48005
48315
  return Array.from(root.querySelectorAll("*")).filter(
48006
48316
  (el) => !NON_RENDERED_TAGS.has(el.tagName.toLowerCase())
@@ -48032,7 +48342,7 @@ function parseCompositions(html, baseDir) {
48032
48342
  const height = parseInt(div.getAttribute("data-height") ?? "1080", 10);
48033
48343
  const compositionSrc = div.getAttribute("data-composition-src");
48034
48344
  if (compositionSrc) {
48035
- const subPath = resolve33(baseDir, compositionSrc);
48345
+ const subPath = resolve34(baseDir, compositionSrc);
48036
48346
  if (existsSync56(subPath)) {
48037
48347
  const subHtml = readFileSync40(subPath, "utf-8");
48038
48348
  const subInfo = parseSubComposition(subHtml, id, width, height);
@@ -48176,7 +48486,7 @@ __export(benchmark_exports, {
48176
48486
  examples: () => examples13
48177
48487
  });
48178
48488
  import { existsSync as existsSync57, statSync as statSync22 } from "fs";
48179
- import { resolve as resolve34, join as join65 } from "path";
48489
+ import { resolve as resolve35, join as join65 } from "path";
48180
48490
  var examples13, FPS_30, FPS_60, DEFAULT_CONFIGS, benchmark_default;
48181
48491
  var init_benchmark = __esm({
48182
48492
  "src/commands/benchmark.ts"() {
@@ -48221,7 +48531,7 @@ var init_benchmark = __esm({
48221
48531
  process.exit(1);
48222
48532
  }
48223
48533
  const jsonOutput = args.json ?? false;
48224
- const benchDir = resolve34("renders", ".benchmark");
48534
+ const benchDir = resolve35("renders", ".benchmark");
48225
48535
  let producer = null;
48226
48536
  try {
48227
48537
  producer = await loadProducer();
@@ -48977,12 +49287,12 @@ async function runPipeline(options, session, media, format, bgFormat) {
48977
49287
  const drains = [];
48978
49288
  if (!fgWroteFully) {
48979
49289
  drains.push(
48980
- new Promise((resolve42) => fg.proc.stdin.once("drain", () => resolve42()))
49290
+ new Promise((resolve43) => fg.proc.stdin.once("drain", () => resolve43()))
48981
49291
  );
48982
49292
  }
48983
49293
  if (!bgWroteFully && bg) {
48984
49294
  drains.push(
48985
- new Promise((resolve42) => bg.proc.stdin.once("drain", () => resolve42()))
49295
+ new Promise((resolve43) => bg.proc.stdin.once("drain", () => resolve43()))
48986
49296
  );
48987
49297
  }
48988
49298
  await Promise.all(drains);
@@ -49015,11 +49325,11 @@ ${decoder.getStderr().slice(-400)}`
49015
49325
  return processed;
49016
49326
  }
49017
49327
  function waitForExit(proc, label2, getStderr) {
49018
- return new Promise((resolve42, reject) => {
49328
+ return new Promise((resolve43, reject) => {
49019
49329
  proc.on("error", reject);
49020
49330
  proc.on("exit", (code, signal) => {
49021
49331
  if (code === 0 && !signal) {
49022
- resolve42();
49332
+ resolve43();
49023
49333
  return;
49024
49334
  }
49025
49335
  const cause = signal ? `killed by ${signal}` : `exited with code ${code}`;
@@ -49053,7 +49363,7 @@ __export(remove_background_exports, {
49053
49363
  default: () => remove_background_default,
49054
49364
  examples: () => examples15
49055
49365
  });
49056
- import { resolve as resolve35 } from "path";
49366
+ import { resolve as resolve36 } from "path";
49057
49367
  import { existsSync as existsSync59 } from "fs";
49058
49368
  async function showInfo(json) {
49059
49369
  const { selectProviders: selectProviders2, listAvailableProviders: listAvailableProviders2, DEFAULT_MODEL: DEFAULT_MODEL4, MODEL_MEMORY_MB: MODEL_MEMORY_MB2, modelPath: modelPath2 } = await Promise.resolve().then(() => (init_manager3(), manager_exports3));
@@ -49195,10 +49505,10 @@ var init_remove_background = __esm({
49195
49505
  );
49196
49506
  process.exit(1);
49197
49507
  }
49198
- const inputPath = resolve35(args.input);
49199
- const outputPath = resolve35(args.output);
49508
+ const inputPath = resolve36(args.input);
49509
+ const outputPath = resolve36(args.output);
49200
49510
  const backgroundOutputArg = args["background-output"];
49201
- const backgroundOutputPath = backgroundOutputArg ? resolve35(backgroundOutputArg) : void 0;
49511
+ const backgroundOutputPath = backgroundOutputArg ? resolve36(backgroundOutputArg) : void 0;
49202
49512
  const { render: render3 } = await Promise.resolve().then(() => (init_pipeline(), pipeline_exports));
49203
49513
  const spin = args.json ? null : ft();
49204
49514
  spin?.start("Preparing background-removal pipeline...");
@@ -49267,7 +49577,7 @@ __export(transcribe_exports2, {
49267
49577
  examples: () => examples16
49268
49578
  });
49269
49579
  import { existsSync as existsSync60, writeFileSync as writeFileSync27 } from "fs";
49270
- import { resolve as resolve36, join as join67, extname as extname11 } from "path";
49580
+ import { resolve as resolve37, join as join67, extname as extname11 } from "path";
49271
49581
  async function importTranscript(inputPath, dir, json) {
49272
49582
  const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
49273
49583
  const { words, format } = loadTranscript2(inputPath);
@@ -49391,12 +49701,12 @@ var init_transcribe2 = __esm({
49391
49701
  }
49392
49702
  },
49393
49703
  async run({ args }) {
49394
- const inputPath = resolve36(args.input);
49704
+ const inputPath = resolve37(args.input);
49395
49705
  if (!existsSync60(inputPath)) {
49396
49706
  console.error(c2.error(`File not found: ${args.input}`));
49397
49707
  process.exit(1);
49398
49708
  }
49399
- const dir = resolve36(args.dir ?? ".");
49709
+ const dir = resolve37(args.dir ?? ".");
49400
49710
  const ext = extname11(inputPath).toLowerCase();
49401
49711
  const isImport = ext === ".json" || ext === ".srt" || ext === ".vtt";
49402
49712
  if (isImport) {
@@ -49686,7 +49996,7 @@ __export(tts_exports, {
49686
49996
  examples: () => examples17
49687
49997
  });
49688
49998
  import { existsSync as existsSync63, readFileSync as readFileSync41 } from "fs";
49689
- import { resolve as resolve37, extname as extname12 } from "path";
49999
+ import { resolve as resolve38, extname as extname12 } from "path";
49690
50000
  function listVoices(json) {
49691
50001
  const rows = BUNDLED_VOICES.map((v2) => ({ ...v2, defaultLang: inferLangFromVoiceId(v2.id) }));
49692
50002
  if (json) {
@@ -49794,7 +50104,7 @@ var init_tts = __esm({
49794
50104
  process.exit(1);
49795
50105
  }
49796
50106
  let text;
49797
- const maybeFile = resolve37(args.input);
50107
+ const maybeFile = resolve38(args.input);
49798
50108
  if (existsSync63(maybeFile) && extname12(maybeFile).toLowerCase() === ".txt") {
49799
50109
  text = readFileSync41(maybeFile, "utf-8").trim();
49800
50110
  if (!text) {
@@ -49808,7 +50118,7 @@ var init_tts = __esm({
49808
50118
  console.error(c2.error("No text provided."));
49809
50119
  process.exit(1);
49810
50120
  }
49811
- const output = resolve37(args.output ?? "speech.wav");
50121
+ const output = resolve38(args.output ?? "speech.wav");
49812
50122
  const voice = args.voice ?? DEFAULT_VOICE;
49813
50123
  const speed = args.speed ? parseFloat(args.speed) : 1;
49814
50124
  if (isNaN(speed) || speed <= 0 || speed > 3) {
@@ -49889,13 +50199,13 @@ __export(docs_exports, {
49889
50199
  examples: () => examples18
49890
50200
  });
49891
50201
  import { readFileSync as readFileSync42, existsSync as existsSync64 } from "fs";
49892
- import { resolve as resolve38, dirname as dirname25, join as join70 } from "path";
50202
+ import { resolve as resolve39, dirname as dirname25, join as join70 } from "path";
49893
50203
  import { fileURLToPath as fileURLToPath9 } from "url";
49894
50204
  function docsDir() {
49895
50205
  const thisFile = fileURLToPath9(import.meta.url);
49896
50206
  const dir = dirname25(thisFile);
49897
- const devPath = resolve38(dir, "..", "docs");
49898
- const builtPath = resolve38(dir, "docs");
50207
+ const devPath = resolve39(dir, "..", "docs");
50208
+ const builtPath = resolve39(dir, "docs");
49899
50209
  return existsSync64(devPath) ? devPath : builtPath;
49900
50210
  }
49901
50211
  function formatInlineCode(line) {
@@ -50261,7 +50571,7 @@ __export(upgrade_exports, {
50261
50571
  default: () => upgrade_default,
50262
50572
  examples: () => examples20
50263
50573
  });
50264
- import { execSync as execSync4 } from "child_process";
50574
+ import { execFileSync as execFileSync8 } from "child_process";
50265
50575
  var examples20, upgrade_default;
50266
50576
  var init_upgrade = __esm({
50267
50577
  "src/commands/upgrade.ts"() {
@@ -50319,13 +50629,20 @@ var init_upgrade = __esm({
50319
50629
  return;
50320
50630
  }
50321
50631
  }
50322
- const installCmd = `npm install -g hyperframes@${result.latest}`;
50632
+ const SAFE_VERSION = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
50633
+ if (!SAFE_VERSION.test(result.latest)) {
50634
+ ye(c2.dim("Refusing to install: unexpected version string from npm registry."));
50635
+ process.exitCode = 1;
50636
+ return;
50637
+ }
50638
+ const installArgs = ["install", "-g", `hyperframes@${result.latest}`];
50639
+ const installCmd = `npm ${installArgs.join(" ")}`;
50323
50640
  if (autoYes) {
50324
50641
  console.log();
50325
50642
  console.log(` ${c2.dim("Running:")} ${c2.accent(installCmd)}`);
50326
50643
  console.log();
50327
50644
  try {
50328
- execSync4(installCmd, { stdio: "inherit" });
50645
+ execFileSync8("npm", installArgs, { stdio: "inherit", shell: false });
50329
50646
  ye(c2.success(`Upgraded to v${result.latest}`));
50330
50647
  } catch {
50331
50648
  ye(c2.dim("Install failed. Try running manually:"));
@@ -50760,7 +51077,7 @@ __export(snapshot_exports, {
50760
51077
  import { spawn as spawn14 } from "child_process";
50761
51078
  import { existsSync as existsSync66, mkdtempSync as mkdtempSync3, readFileSync as readFileSync44, mkdirSync as mkdirSync36, rmSync as rmSync15 } from "fs";
50762
51079
  import { tmpdir as tmpdir5 } from "os";
50763
- import { resolve as resolve39, join as join72, relative as relative9, isAbsolute as isAbsolute9 } from "path";
51080
+ import { resolve as resolve40, join as join72, relative as relative9, isAbsolute as isAbsolute9 } from "path";
50764
51081
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
50765
51082
  const tmp = mkdtempSync3(join72(tmpdir5(), "hf-snapshot-frame-"));
50766
51083
  const outPath = join72(tmp, "frame.png");
@@ -50949,7 +51266,7 @@ async function captureSnapshots(projectDir, opts) {
50949
51266
  try {
50950
51267
  const url = new URL(v2.src);
50951
51268
  const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
50952
- const candidate = resolve39(projectDir, decodedPath);
51269
+ const candidate = resolve40(projectDir, decodedPath);
50953
51270
  const rel = relative9(projectDir, candidate);
50954
51271
  if (!rel.startsWith("..") && !isAbsolute9(rel) && existsSync66(candidate)) {
50955
51272
  filePath = candidate;
@@ -51445,7 +51762,7 @@ async function extractHtml(page, opts = {}) {
51445
51762
  (_match, pre, urls, post) => {
51446
51763
  const fixed = urls.replace(/&amp;/g, "&").replace(
51447
51764
  /(^|,\s*)(\/[^\s,]+)/g,
51448
- (_m, sep6, path2) => sep6 + pageOrigin + path2
51765
+ (_m, sep7, path2) => sep7 + pageOrigin + path2
51449
51766
  );
51450
51767
  return pre + fixed + post;
51451
51768
  }
@@ -52542,7 +52859,7 @@ var require_p_retry = __commonJS({
52542
52859
  return error;
52543
52860
  };
52544
52861
  var isNetworkError = (errorMessage) => networkErrorMsgs.includes(errorMessage);
52545
- var pRetry2 = (input, options) => new Promise((resolve42, reject) => {
52862
+ var pRetry2 = (input, options) => new Promise((resolve43, reject) => {
52546
52863
  options = {
52547
52864
  onFailedAttempt: () => {
52548
52865
  },
@@ -52552,7 +52869,7 @@ var require_p_retry = __commonJS({
52552
52869
  const operation = retry.operation(options);
52553
52870
  operation.attempt(async (attemptNumber) => {
52554
52871
  try {
52555
- resolve42(await input(attemptNumber));
52872
+ resolve43(await input(attemptNumber));
52556
52873
  } catch (error) {
52557
52874
  if (!(error instanceof Error)) {
52558
52875
  reject(new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`));
@@ -53088,8 +53405,8 @@ var require_retry3 = __commonJS({
53088
53405
  }
53089
53406
  const delay = getNextRetryDelay(config);
53090
53407
  err.config.retryConfig.currentRetryAttempt += 1;
53091
- const backoff = config.retryBackoff ? config.retryBackoff(err, delay) : new Promise((resolve42) => {
53092
- setTimeout(resolve42, delay);
53408
+ const backoff = config.retryBackoff ? config.retryBackoff(err, delay) : new Promise((resolve43) => {
53409
+ setTimeout(resolve43, delay);
53093
53410
  });
53094
53411
  if (config.onRetryAttempt) {
53095
53412
  await config.onRetryAttempt(err);
@@ -53997,8 +54314,8 @@ var require_helpers = __commonJS({
53997
54314
  function req(url, opts = {}) {
53998
54315
  const href = typeof url === "string" ? url : url.href;
53999
54316
  const req2 = (href.startsWith("https:") ? https2 : http4).request(url, opts);
54000
- const promise = new Promise((resolve42, reject) => {
54001
- req2.once("response", resolve42).once("error", reject).end();
54317
+ const promise = new Promise((resolve43, reject) => {
54318
+ req2.once("response", resolve43).once("error", reject).end();
54002
54319
  });
54003
54320
  req2.then = promise.then.bind(promise);
54004
54321
  return req2;
@@ -54175,7 +54492,7 @@ var require_parse_proxy_response = __commonJS({
54175
54492
  var debug_1 = __importDefault(require_src2());
54176
54493
  var debug = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
54177
54494
  function parseProxyResponse(socket) {
54178
- return new Promise((resolve42, reject) => {
54495
+ return new Promise((resolve43, reject) => {
54179
54496
  let buffersLength = 0;
54180
54497
  const buffers = [];
54181
54498
  function read() {
@@ -54241,7 +54558,7 @@ var require_parse_proxy_response = __commonJS({
54241
54558
  }
54242
54559
  debug("got proxy server response: %o %o", firstLine, headers);
54243
54560
  cleanup();
54244
- resolve42({
54561
+ resolve43({
54245
54562
  connect: {
54246
54563
  statusCode,
54247
54564
  statusText,
@@ -54485,7 +54802,7 @@ var require_ponyfill_es2018 = __commonJS({
54485
54802
  return new originalPromise(executor);
54486
54803
  }
54487
54804
  function promiseResolvedWith(value) {
54488
- return newPromise((resolve42) => resolve42(value));
54805
+ return newPromise((resolve43) => resolve43(value));
54489
54806
  }
54490
54807
  function promiseRejectedWith(reason) {
54491
54808
  return originalPromiseReject(reason);
@@ -54655,8 +54972,8 @@ var require_ponyfill_es2018 = __commonJS({
54655
54972
  return new TypeError("Cannot " + name + " a stream using a released reader");
54656
54973
  }
54657
54974
  function defaultReaderClosedPromiseInitialize(reader) {
54658
- reader._closedPromise = newPromise((resolve42, reject) => {
54659
- reader._closedPromise_resolve = resolve42;
54975
+ reader._closedPromise = newPromise((resolve43, reject) => {
54976
+ reader._closedPromise_resolve = resolve43;
54660
54977
  reader._closedPromise_reject = reject;
54661
54978
  });
54662
54979
  }
@@ -54830,8 +55147,8 @@ var require_ponyfill_es2018 = __commonJS({
54830
55147
  }
54831
55148
  let resolvePromise;
54832
55149
  let rejectPromise;
54833
- const promise = newPromise((resolve42, reject) => {
54834
- resolvePromise = resolve42;
55150
+ const promise = newPromise((resolve43, reject) => {
55151
+ resolvePromise = resolve43;
54835
55152
  rejectPromise = reject;
54836
55153
  });
54837
55154
  const readRequest = {
@@ -54936,8 +55253,8 @@ var require_ponyfill_es2018 = __commonJS({
54936
55253
  const reader = this._reader;
54937
55254
  let resolvePromise;
54938
55255
  let rejectPromise;
54939
- const promise = newPromise((resolve42, reject) => {
54940
- resolvePromise = resolve42;
55256
+ const promise = newPromise((resolve43, reject) => {
55257
+ resolvePromise = resolve43;
54941
55258
  rejectPromise = reject;
54942
55259
  });
54943
55260
  const readRequest = {
@@ -55956,8 +56273,8 @@ var require_ponyfill_es2018 = __commonJS({
55956
56273
  }
55957
56274
  let resolvePromise;
55958
56275
  let rejectPromise;
55959
- const promise = newPromise((resolve42, reject) => {
55960
- resolvePromise = resolve42;
56276
+ const promise = newPromise((resolve43, reject) => {
56277
+ resolvePromise = resolve43;
55961
56278
  rejectPromise = reject;
55962
56279
  });
55963
56280
  const readIntoRequest = {
@@ -56269,10 +56586,10 @@ var require_ponyfill_es2018 = __commonJS({
56269
56586
  wasAlreadyErroring = true;
56270
56587
  reason = void 0;
56271
56588
  }
56272
- const promise = newPromise((resolve42, reject) => {
56589
+ const promise = newPromise((resolve43, reject) => {
56273
56590
  stream._pendingAbortRequest = {
56274
56591
  _promise: void 0,
56275
- _resolve: resolve42,
56592
+ _resolve: resolve43,
56276
56593
  _reject: reject,
56277
56594
  _reason: reason,
56278
56595
  _wasAlreadyErroring: wasAlreadyErroring
@@ -56289,9 +56606,9 @@ var require_ponyfill_es2018 = __commonJS({
56289
56606
  if (state === "closed" || state === "errored") {
56290
56607
  return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`));
56291
56608
  }
56292
- const promise = newPromise((resolve42, reject) => {
56609
+ const promise = newPromise((resolve43, reject) => {
56293
56610
  const closeRequest = {
56294
- _resolve: resolve42,
56611
+ _resolve: resolve43,
56295
56612
  _reject: reject
56296
56613
  };
56297
56614
  stream._closeRequest = closeRequest;
@@ -56304,9 +56621,9 @@ var require_ponyfill_es2018 = __commonJS({
56304
56621
  return promise;
56305
56622
  }
56306
56623
  function WritableStreamAddWriteRequest(stream) {
56307
- const promise = newPromise((resolve42, reject) => {
56624
+ const promise = newPromise((resolve43, reject) => {
56308
56625
  const writeRequest = {
56309
- _resolve: resolve42,
56626
+ _resolve: resolve43,
56310
56627
  _reject: reject
56311
56628
  };
56312
56629
  stream._writeRequests.push(writeRequest);
@@ -56922,8 +57239,8 @@ var require_ponyfill_es2018 = __commonJS({
56922
57239
  return new TypeError("Cannot " + name + " a stream using a released writer");
56923
57240
  }
56924
57241
  function defaultWriterClosedPromiseInitialize(writer) {
56925
- writer._closedPromise = newPromise((resolve42, reject) => {
56926
- writer._closedPromise_resolve = resolve42;
57242
+ writer._closedPromise = newPromise((resolve43, reject) => {
57243
+ writer._closedPromise_resolve = resolve43;
56927
57244
  writer._closedPromise_reject = reject;
56928
57245
  writer._closedPromiseState = "pending";
56929
57246
  });
@@ -56959,8 +57276,8 @@ var require_ponyfill_es2018 = __commonJS({
56959
57276
  writer._closedPromiseState = "resolved";
56960
57277
  }
56961
57278
  function defaultWriterReadyPromiseInitialize(writer) {
56962
- writer._readyPromise = newPromise((resolve42, reject) => {
56963
- writer._readyPromise_resolve = resolve42;
57279
+ writer._readyPromise = newPromise((resolve43, reject) => {
57280
+ writer._readyPromise_resolve = resolve43;
56964
57281
  writer._readyPromise_reject = reject;
56965
57282
  });
56966
57283
  writer._readyPromiseState = "pending";
@@ -57047,7 +57364,7 @@ var require_ponyfill_es2018 = __commonJS({
57047
57364
  source._disturbed = true;
57048
57365
  let shuttingDown = false;
57049
57366
  let currentWrite = promiseResolvedWith(void 0);
57050
- return newPromise((resolve42, reject) => {
57367
+ return newPromise((resolve43, reject) => {
57051
57368
  let abortAlgorithm;
57052
57369
  if (signal !== void 0) {
57053
57370
  abortAlgorithm = () => {
@@ -57192,7 +57509,7 @@ var require_ponyfill_es2018 = __commonJS({
57192
57509
  if (isError) {
57193
57510
  reject(error);
57194
57511
  } else {
57195
- resolve42(void 0);
57512
+ resolve43(void 0);
57196
57513
  }
57197
57514
  return null;
57198
57515
  }
@@ -57473,8 +57790,8 @@ var require_ponyfill_es2018 = __commonJS({
57473
57790
  let branch1;
57474
57791
  let branch2;
57475
57792
  let resolveCancelPromise;
57476
- const cancelPromise = newPromise((resolve42) => {
57477
- resolveCancelPromise = resolve42;
57793
+ const cancelPromise = newPromise((resolve43) => {
57794
+ resolveCancelPromise = resolve43;
57478
57795
  });
57479
57796
  function pullAlgorithm() {
57480
57797
  if (reading) {
@@ -57565,8 +57882,8 @@ var require_ponyfill_es2018 = __commonJS({
57565
57882
  let branch1;
57566
57883
  let branch2;
57567
57884
  let resolveCancelPromise;
57568
- const cancelPromise = newPromise((resolve42) => {
57569
- resolveCancelPromise = resolve42;
57885
+ const cancelPromise = newPromise((resolve43) => {
57886
+ resolveCancelPromise = resolve43;
57570
57887
  });
57571
57888
  function forwardReaderError(thisReader) {
57572
57889
  uponRejection(thisReader._closedPromise, (r2) => {
@@ -58346,8 +58663,8 @@ var require_ponyfill_es2018 = __commonJS({
58346
58663
  const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1);
58347
58664
  const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy);
58348
58665
  let startPromise_resolve;
58349
- const startPromise = newPromise((resolve42) => {
58350
- startPromise_resolve = resolve42;
58666
+ const startPromise = newPromise((resolve43) => {
58667
+ startPromise_resolve = resolve43;
58351
58668
  });
58352
58669
  InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm);
58353
58670
  SetUpTransformStreamDefaultControllerFromTransformer(this, transformer);
@@ -58440,8 +58757,8 @@ var require_ponyfill_es2018 = __commonJS({
58440
58757
  if (stream._backpressureChangePromise !== void 0) {
58441
58758
  stream._backpressureChangePromise_resolve();
58442
58759
  }
58443
- stream._backpressureChangePromise = newPromise((resolve42) => {
58444
- stream._backpressureChangePromise_resolve = resolve42;
58760
+ stream._backpressureChangePromise = newPromise((resolve43) => {
58761
+ stream._backpressureChangePromise_resolve = resolve43;
58445
58762
  });
58446
58763
  stream._backpressure = backpressure;
58447
58764
  }
@@ -58609,8 +58926,8 @@ var require_ponyfill_es2018 = __commonJS({
58609
58926
  return controller._finishPromise;
58610
58927
  }
58611
58928
  const readable = stream._readable;
58612
- controller._finishPromise = newPromise((resolve42, reject) => {
58613
- controller._finishPromise_resolve = resolve42;
58929
+ controller._finishPromise = newPromise((resolve43, reject) => {
58930
+ controller._finishPromise_resolve = resolve43;
58614
58931
  controller._finishPromise_reject = reject;
58615
58932
  });
58616
58933
  const cancelPromise = controller._cancelAlgorithm(reason);
@@ -58636,8 +58953,8 @@ var require_ponyfill_es2018 = __commonJS({
58636
58953
  return controller._finishPromise;
58637
58954
  }
58638
58955
  const readable = stream._readable;
58639
- controller._finishPromise = newPromise((resolve42, reject) => {
58640
- controller._finishPromise_resolve = resolve42;
58956
+ controller._finishPromise = newPromise((resolve43, reject) => {
58957
+ controller._finishPromise_resolve = resolve43;
58641
58958
  controller._finishPromise_reject = reject;
58642
58959
  });
58643
58960
  const flushPromise = controller._flushAlgorithm();
@@ -58667,8 +58984,8 @@ var require_ponyfill_es2018 = __commonJS({
58667
58984
  return controller._finishPromise;
58668
58985
  }
58669
58986
  const writable = stream._writable;
58670
- controller._finishPromise = newPromise((resolve42, reject) => {
58671
- controller._finishPromise_resolve = resolve42;
58987
+ controller._finishPromise = newPromise((resolve43, reject) => {
58988
+ controller._finishPromise_resolve = resolve43;
58672
58989
  controller._finishPromise_reject = reject;
58673
58990
  });
58674
58991
  const cancelPromise = controller._cancelAlgorithm(reason);
@@ -60637,7 +60954,7 @@ import zlib from "zlib";
60637
60954
  import Stream2, { PassThrough as PassThrough2, pipeline as pump } from "stream";
60638
60955
  import { Buffer as Buffer3 } from "buffer";
60639
60956
  async function fetch3(url, options_) {
60640
- return new Promise((resolve42, reject) => {
60957
+ return new Promise((resolve43, reject) => {
60641
60958
  const request = new Request2(url, options_);
60642
60959
  const { parsedURL, options } = getNodeRequestOptions(request);
60643
60960
  if (!supportedSchemas.has(parsedURL.protocol)) {
@@ -60646,7 +60963,7 @@ async function fetch3(url, options_) {
60646
60963
  if (parsedURL.protocol === "data:") {
60647
60964
  const data = dist_default3(request.url);
60648
60965
  const response2 = new Response2(data, { headers: { "Content-Type": data.typeFull } });
60649
- resolve42(response2);
60966
+ resolve43(response2);
60650
60967
  return;
60651
60968
  }
60652
60969
  const send = (parsedURL.protocol === "https:" ? https : http3).request;
@@ -60768,7 +61085,7 @@ async function fetch3(url, options_) {
60768
61085
  if (responseReferrerPolicy) {
60769
61086
  requestOptions.referrerPolicy = responseReferrerPolicy;
60770
61087
  }
60771
- resolve42(fetch3(new Request2(locationURL, requestOptions)));
61088
+ resolve43(fetch3(new Request2(locationURL, requestOptions)));
60772
61089
  finalize();
60773
61090
  return;
60774
61091
  }
@@ -60801,7 +61118,7 @@ async function fetch3(url, options_) {
60801
61118
  const codings = headers.get("Content-Encoding");
60802
61119
  if (!request.compress || request.method === "HEAD" || codings === null || response_.statusCode === 204 || response_.statusCode === 304) {
60803
61120
  response = new Response2(body, responseOptions);
60804
- resolve42(response);
61121
+ resolve43(response);
60805
61122
  return;
60806
61123
  }
60807
61124
  const zlibOptions = {
@@ -60815,7 +61132,7 @@ async function fetch3(url, options_) {
60815
61132
  }
60816
61133
  });
60817
61134
  response = new Response2(body, responseOptions);
60818
- resolve42(response);
61135
+ resolve43(response);
60819
61136
  return;
60820
61137
  }
60821
61138
  if (codings === "deflate" || codings === "x-deflate") {
@@ -60839,12 +61156,12 @@ async function fetch3(url, options_) {
60839
61156
  });
60840
61157
  }
60841
61158
  response = new Response2(body, responseOptions);
60842
- resolve42(response);
61159
+ resolve43(response);
60843
61160
  });
60844
61161
  raw.once("end", () => {
60845
61162
  if (!response) {
60846
61163
  response = new Response2(body, responseOptions);
60847
- resolve42(response);
61164
+ resolve43(response);
60848
61165
  }
60849
61166
  });
60850
61167
  return;
@@ -60856,11 +61173,11 @@ async function fetch3(url, options_) {
60856
61173
  }
60857
61174
  });
60858
61175
  response = new Response2(body, responseOptions);
60859
- resolve42(response);
61176
+ resolve43(response);
60860
61177
  return;
60861
61178
  }
60862
61179
  response = new Response2(body, responseOptions);
60863
- resolve42(response);
61180
+ resolve43(response);
60864
61181
  });
60865
61182
  writeToStream(request_, request).catch(reject);
60866
61183
  });
@@ -66942,7 +67259,7 @@ var require_jwtaccess = __commonJS({
66942
67259
  }
66943
67260
  }
66944
67261
  fromStreamAsync(inputStream) {
66945
- return new Promise((resolve42, reject) => {
67262
+ return new Promise((resolve43, reject) => {
66946
67263
  if (!inputStream) {
66947
67264
  reject(new Error("Must pass in a stream containing the service account auth settings."));
66948
67265
  }
@@ -66951,7 +67268,7 @@ var require_jwtaccess = __commonJS({
66951
67268
  try {
66952
67269
  const data = JSON.parse(s2);
66953
67270
  this.fromJSON(data);
66954
- resolve42();
67271
+ resolve43();
66955
67272
  } catch (err) {
66956
67273
  reject(err);
66957
67274
  }
@@ -67190,7 +67507,7 @@ var require_jwtclient = __commonJS({
67190
67507
  }
67191
67508
  }
67192
67509
  fromStreamAsync(inputStream) {
67193
- return new Promise((resolve42, reject) => {
67510
+ return new Promise((resolve43, reject) => {
67194
67511
  if (!inputStream) {
67195
67512
  throw new Error("Must pass in a stream containing the service account auth settings.");
67196
67513
  }
@@ -67199,7 +67516,7 @@ var require_jwtclient = __commonJS({
67199
67516
  try {
67200
67517
  const data = JSON.parse(s2);
67201
67518
  this.fromJSON(data);
67202
- resolve42();
67519
+ resolve43();
67203
67520
  } catch (e3) {
67204
67521
  reject(e3);
67205
67522
  }
@@ -67332,7 +67649,7 @@ var require_refreshclient = __commonJS({
67332
67649
  }
67333
67650
  }
67334
67651
  async fromStreamAsync(inputStream) {
67335
- return new Promise((resolve42, reject) => {
67652
+ return new Promise((resolve43, reject) => {
67336
67653
  if (!inputStream) {
67337
67654
  return reject(new Error("Must pass in a stream containing the user refresh token."));
67338
67655
  }
@@ -67341,7 +67658,7 @@ var require_refreshclient = __commonJS({
67341
67658
  try {
67342
67659
  const data = JSON.parse(s2);
67343
67660
  this.fromJSON(data);
67344
- return resolve42();
67661
+ return resolve43();
67345
67662
  } catch (err) {
67346
67663
  return reject(err);
67347
67664
  }
@@ -69174,7 +69491,7 @@ var require_pluggable_auth_handler = __commonJS({
69174
69491
  * @return A promise that resolves with the executable response.
69175
69492
  */
69176
69493
  retrieveResponseFromExecutable(envMap) {
69177
- return new Promise((resolve42, reject) => {
69494
+ return new Promise((resolve43, reject) => {
69178
69495
  const child = childProcess.spawn(this.commandComponents[0], this.commandComponents.slice(1), {
69179
69496
  env: { ...process.env, ...Object.fromEntries(envMap) }
69180
69497
  });
@@ -69196,7 +69513,7 @@ var require_pluggable_auth_handler = __commonJS({
69196
69513
  try {
69197
69514
  const responseJson = JSON.parse(output);
69198
69515
  const response = new executable_response_1.ExecutableResponse(responseJson);
69199
- return resolve42(response);
69516
+ return resolve43(response);
69200
69517
  } catch (error) {
69201
69518
  if (error instanceof executable_response_1.ExecutableResponseError) {
69202
69519
  return reject(error);
@@ -70099,7 +70416,7 @@ var require_googleauth = __commonJS({
70099
70416
  }
70100
70417
  }
70101
70418
  fromStreamAsync(inputStream, options) {
70102
- return new Promise((resolve42, reject) => {
70419
+ return new Promise((resolve43, reject) => {
70103
70420
  if (!inputStream) {
70104
70421
  throw new Error("Must pass in a stream containing the Google auth settings.");
70105
70422
  }
@@ -70109,7 +70426,7 @@ var require_googleauth = __commonJS({
70109
70426
  try {
70110
70427
  const data = JSON.parse(chunks.join(""));
70111
70428
  const r2 = this._cacheClientFromJSON(data, options);
70112
- return resolve42(r2);
70429
+ return resolve43(r2);
70113
70430
  } catch (err) {
70114
70431
  if (!this.keyFilename)
70115
70432
  throw err;
@@ -70119,7 +70436,7 @@ var require_googleauth = __commonJS({
70119
70436
  });
70120
70437
  this.cachedCredential = client;
70121
70438
  this.setGapicJWTValues(client);
70122
- return resolve42(client);
70439
+ return resolve43(client);
70123
70440
  }
70124
70441
  } catch (err) {
70125
70442
  return reject(err);
@@ -70155,17 +70472,17 @@ var require_googleauth = __commonJS({
70155
70472
  * Run the Google Cloud SDK command that prints the default project ID
70156
70473
  */
70157
70474
  async getDefaultServiceProjectId() {
70158
- return new Promise((resolve42) => {
70475
+ return new Promise((resolve43) => {
70159
70476
  (0, child_process_1.exec)("gcloud config config-helper --format json", (err, stdout2) => {
70160
70477
  if (!err && stdout2) {
70161
70478
  try {
70162
70479
  const projectId = JSON.parse(stdout2).configuration.properties.core.project;
70163
- resolve42(projectId);
70480
+ resolve43(projectId);
70164
70481
  return;
70165
70482
  } catch (e3) {
70166
70483
  }
70167
70484
  }
70168
- resolve42(null);
70485
+ resolve43(null);
70169
70486
  });
70170
70487
  });
70171
70488
  }
@@ -78008,14 +78325,14 @@ function __asyncValues(o) {
78008
78325
  }, i2);
78009
78326
  function verb(n) {
78010
78327
  i2[n] = o[n] && function(v2) {
78011
- return new Promise(function(resolve42, reject) {
78012
- v2 = o[n](v2), settle(resolve42, reject, v2.done, v2.value);
78328
+ return new Promise(function(resolve43, reject) {
78329
+ v2 = o[n](v2), settle(resolve43, reject, v2.done, v2.value);
78013
78330
  });
78014
78331
  };
78015
78332
  }
78016
- function settle(resolve42, reject, d2, v2) {
78333
+ function settle(resolve43, reject, d2, v2) {
78017
78334
  Promise.resolve(v2).then(function(v3) {
78018
- resolve42({ value: v3, done: d2 });
78335
+ resolve43({ value: v3, done: d2 });
78019
78336
  }, reject);
78020
78337
  }
78021
78338
  }
@@ -88505,8 +88822,8 @@ var init_node4 = __esm({
88505
88822
  const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.BidiGenerateMusic?key=${apiKey}`;
88506
88823
  let onopenResolve = () => {
88507
88824
  };
88508
- const onopenPromise = new Promise((resolve42) => {
88509
- onopenResolve = resolve42;
88825
+ const onopenPromise = new Promise((resolve43) => {
88826
+ onopenResolve = resolve43;
88510
88827
  });
88511
88828
  const callbacks = params.callbacks;
88512
88829
  const onopenAwaitedCallback = function() {
@@ -88712,8 +89029,8 @@ var init_node4 = __esm({
88712
89029
  }
88713
89030
  let onopenResolve = () => {
88714
89031
  };
88715
- const onopenPromise = new Promise((resolve42) => {
88716
- onopenResolve = resolve42;
89032
+ const onopenPromise = new Promise((resolve43) => {
89033
+ onopenResolve = resolve43;
88717
89034
  });
88718
89035
  const callbacks = params.callbacks;
88719
89036
  const onopenAwaitedCallback = function() {
@@ -91061,7 +91378,7 @@ var init_node4 = __esm({
91061
91378
  return void 0;
91062
91379
  }
91063
91380
  };
91064
- sleep$1 = (ms) => new Promise((resolve42) => setTimeout(resolve42, ms));
91381
+ sleep$1 = (ms) => new Promise((resolve43) => setTimeout(resolve43, ms));
91065
91382
  FallbackEncoder = ({ headers, body }) => {
91066
91383
  return {
91067
91384
  bodyHeaders: {
@@ -91570,8 +91887,8 @@ ${underline2}`);
91570
91887
  };
91571
91888
  APIPromise = class _APIPromise extends Promise {
91572
91889
  constructor(client, responsePromise, parseResponse = defaultParseResponse) {
91573
- super((resolve42) => {
91574
- resolve42(null);
91890
+ super((resolve43) => {
91891
+ resolve43(null);
91575
91892
  });
91576
91893
  this.responsePromise = responsePromise;
91577
91894
  this.parseResponse = parseResponse;
@@ -93106,12 +93423,12 @@ var init_agentPromptGenerator = __esm({
93106
93423
 
93107
93424
  // src/capture/scaffolding.ts
93108
93425
  import { existsSync as existsSync67, writeFileSync as writeFileSync32, readFileSync as readFileSync47 } from "fs";
93109
- import { join as join77, resolve as resolve40 } from "path";
93426
+ import { join as join77, resolve as resolve41 } from "path";
93110
93427
  function loadEnvFile(startDir) {
93111
93428
  try {
93112
- let dir = resolve40(startDir);
93429
+ let dir = resolve41(startDir);
93113
93430
  for (let i2 = 0; i2 < 5; i2++) {
93114
- const envPath = resolve40(dir, ".env");
93431
+ const envPath = resolve41(dir, ".env");
93115
93432
  try {
93116
93433
  const envContent = readFileSync47(envPath, "utf-8");
93117
93434
  for (const line of envContent.split("\n")) {
@@ -93125,7 +93442,7 @@ function loadEnvFile(startDir) {
93125
93442
  }
93126
93443
  break;
93127
93444
  } catch {
93128
- dir = resolve40(dir, "..");
93445
+ dir = resolve41(dir, "..");
93129
93446
  }
93130
93447
  }
93131
93448
  } catch {
@@ -93892,7 +94209,7 @@ __export(capture_exports2, {
93892
94209
  default: () => capture_default,
93893
94210
  examples: () => examples23
93894
94211
  });
93895
- import { resolve as resolve41 } from "path";
94212
+ import { resolve as resolve42 } from "path";
93896
94213
  var examples23, capture_default;
93897
94214
  var init_capture2 = __esm({
93898
94215
  "src/commands/capture.ts"() {
@@ -93951,7 +94268,7 @@ var init_capture2 = __esm({
93951
94268
  const hostname = new URL(url).hostname.replace(/^www\./, "");
93952
94269
  outputName = `captures/${hostname.replace(/\./g, "-")}`;
93953
94270
  }
93954
- const outputDir = resolve41(outputName);
94271
+ const outputDir = resolve42(outputName);
93955
94272
  const isJson = args.json;
93956
94273
  if (!isJson) {
93957
94274
  const { c: c3 } = await Promise.resolve().then(() => (init_colors(), colors_exports));