@hyperframes/producer 0.8.193 → 0.8.195

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1492,12 +1492,15 @@ import {
1492
1492
  readMediaStart,
1493
1493
  redactTelemetryString as redactTelemetryString2,
1494
1494
  resolveNaturalMediaTimelineDurationFromValues,
1495
+ rewriteAssetPath,
1495
1496
  rewriteAssetPaths,
1496
1497
  rewriteCssAssetUrls,
1497
1498
  rewriteInlineStyleAssetUrls
1498
1499
  } from "@hyperframes/core";
1499
1500
  import { MAX_AUDIO_GAIN } from "@hyperframes/core/audio-gain";
1500
- import { gsapCdnDist } from "@hyperframes/core/gsap-cdn";
1501
+ import { readPlaybackRate } from "@hyperframes/parsers/media-duration";
1502
+ import { resolveRateSpec } from "@hyperframes/core/speed-ramp";
1503
+ import { gsapCdnDist, normalizeGsapBaseUrl } from "@hyperframes/core/gsap-cdn";
1501
1504
  import {
1502
1505
  assignBundledRuntimeCompositionIds,
1503
1506
  assignMediaRenderIds,
@@ -2530,7 +2533,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, visited = /*
2530
2533
  const results = await Promise.all(
2531
2534
  workItems.map(async (item) => {
2532
2535
  const { html: compiledSub } = await compileHtmlFile(
2533
- item.rawSubHtml,
2536
+ rewriteUnresolvableGsapToCdn(item.rawSubHtml, projectDir, item.srcPath),
2534
2537
  dirname4(item.filePath),
2535
2538
  downloadDir,
2536
2539
  void 0,
@@ -2704,7 +2707,9 @@ function inlineSubCompositions(html, subCompositions, projectDir, variableOverri
2704
2707
  let compHtml = subCompositions.get(srcPath) || null;
2705
2708
  if (!compHtml) {
2706
2709
  const read = readProjectFile(resolve5(projectDir, srcPath));
2707
- if (read.kind === "file") compHtml = read.text;
2710
+ if (read.kind === "file") {
2711
+ compHtml = rewriteUnresolvableGsapToCdn(read.text, projectDir, srcPath);
2712
+ }
2708
2713
  }
2709
2714
  return compHtml;
2710
2715
  },
@@ -3247,18 +3252,27 @@ async function embedLocalFontFaces(html, projectDir) {
3247
3252
  }
3248
3253
  return result;
3249
3254
  }
3250
- var GSAP_CDN_BASE = gsapCdnDist();
3251
- function rewriteUnresolvableGsapToCdn(html, projectDir) {
3255
+ function renderGsapDist() {
3256
+ try {
3257
+ return gsapCdnDist(void 0, normalizeGsapBaseUrl(process.env.HYPERFRAMES_GSAP_BASE_URL));
3258
+ } catch (cause) {
3259
+ throw new Error(
3260
+ "Invalid HYPERFRAMES_GSAP_BASE_URL: use an absolute HTTPS npm mirror root (plain HTTP only for localhost) without credentials, query, or fragment",
3261
+ { cause }
3262
+ );
3263
+ }
3264
+ }
3265
+ function rewriteUnresolvableGsapToCdn(html, projectDir, compSrcPath) {
3266
+ let gsapDist;
3267
+ const exists = (path) => existsSync6(resolve5(projectDir, path));
3252
3268
  return html.replace(
3253
3269
  /(<script\b[^>]*\bsrc=["'])([^"']*gsap[^"']*\/dist\/([^"']+))(["'][^>]*>)/gi,
3254
3270
  (full, prefix, src, file, suffix) => {
3255
3271
  if (/^https?:\/\//i.test(src)) return full;
3256
- const absPath = resolve5(projectDir, src);
3257
- if (existsSync6(absPath)) return full;
3258
- defaultLogger.info(
3259
- `[Compiler] Rewriting missing gsap script to CDN: ${src} \u2192 ${GSAP_CDN_BASE}${file}`
3260
- );
3261
- return `${prefix}${GSAP_CDN_BASE}${file}${suffix}`;
3272
+ if (exists(compSrcPath ? rewriteAssetPath(compSrcPath, src, exists) : src)) return full;
3273
+ gsapDist ??= renderGsapDist();
3274
+ defaultLogger.info(`[Compiler] Rewriting missing gsap script: ${src} \u2192 ${gsapDist}${file}`);
3275
+ return `${prefix}${gsapDist}${file}${suffix}`;
3262
3276
  }
3263
3277
  );
3264
3278
  }
@@ -3472,6 +3486,9 @@ async function discoverMediaFromBrowser(page) {
3472
3486
  const intrinsicDuration = isImage ? 0 : htmlEl.duration;
3473
3487
  const playbackStartRaw = htmlEl.getAttribute("data-playback-start");
3474
3488
  const mediaStartRaw = htmlEl.getAttribute("data-media-start");
3489
+ const playbackRateRaw = htmlEl.getAttribute("data-playback-rate");
3490
+ const automationRaw = htmlEl.getAttribute("data-automation");
3491
+ const defaultPlaybackRate = isImage ? 1 : htmlEl.defaultPlaybackRate;
3475
3492
  const loop = htmlEl.hasAttribute("loop");
3476
3493
  const hasAudio = htmlEl.getAttribute("data-has-audio") === "true";
3477
3494
  const volume = parseFloat(htmlEl.getAttribute("data-volume") || "1");
@@ -3487,6 +3504,9 @@ async function discoverMediaFromBrowser(page) {
3487
3504
  durationInferred,
3488
3505
  playbackStartRaw,
3489
3506
  mediaStartRaw,
3507
+ playbackRateRaw,
3508
+ automationRaw,
3509
+ defaultPlaybackRate,
3490
3510
  loop,
3491
3511
  hasAudio,
3492
3512
  volume,
@@ -3496,7 +3516,17 @@ async function discoverMediaFromBrowser(page) {
3496
3516
  return results;
3497
3517
  });
3498
3518
  return elements.map(
3499
- ({ endRaw, durationRaw, intrinsicDuration, playbackStartRaw, mediaStartRaw, ...element }) => ({
3519
+ ({
3520
+ endRaw,
3521
+ durationRaw,
3522
+ intrinsicDuration,
3523
+ playbackStartRaw,
3524
+ mediaStartRaw,
3525
+ playbackRateRaw,
3526
+ automationRaw,
3527
+ defaultPlaybackRate,
3528
+ ...element
3529
+ }) => ({
3500
3530
  ...element,
3501
3531
  end: parseStrictFiniteTimingNumber(endRaw) ?? 0,
3502
3532
  duration: element.durationInferred && Number.isFinite(intrinsicDuration) && intrinsicDuration > 0 ? intrinsicDuration : parseStrictFiniteTimingNumber(durationRaw) ?? 0,
@@ -3506,7 +3536,14 @@ async function discoverMediaFromBrowser(page) {
3506
3536
  if (name === "data-media-start") return mediaStartRaw;
3507
3537
  return null;
3508
3538
  }
3509
- })
3539
+ }),
3540
+ playbackRate: resolveRateSpec(
3541
+ automationRaw,
3542
+ readPlaybackRate(
3543
+ (name) => name === "data-playback-rate" ? playbackRateRaw : null,
3544
+ defaultPlaybackRate
3545
+ )
3546
+ )
3510
3547
  })
3511
3548
  );
3512
3549
  }
@@ -3926,9 +3963,18 @@ import {
3926
3963
  getCompositionDuration,
3927
3964
  initializeSession as initializeSession4,
3928
3965
  isTransientBrowserError,
3929
- probeBeginFrameLiveness
3966
+ probeBeginFrameLiveness,
3967
+ videoAudioId
3930
3968
  } from "@hyperframes/engine";
3931
- import { MEDIA_RENDER_ID_ATTR as MEDIA_RENDER_ID_ATTR2, fpsToNumber as fpsToNumber7, readMediaStart as readMediaStart2 } from "@hyperframes/core";
3969
+ import {
3970
+ MEDIA_RENDER_ID_ATTR as MEDIA_RENDER_ID_ATTR2,
3971
+ fpsToNumber as fpsToNumber7,
3972
+ normalizeRateSpec as normalizeRateSpec3,
3973
+ readMediaStart as readMediaStart2,
3974
+ shiftRateLane as shiftRateLane2,
3975
+ sourceTimeAt as sourceTimeAt3,
3976
+ timeAtSourceTime
3977
+ } from "@hyperframes/core";
3932
3978
  import { extractMediaSrcMutations } from "@hyperframes/parsers";
3933
3979
 
3934
3980
  // src/services/render/stages/probeFailures.ts
@@ -3987,16 +4033,28 @@ function authoredMediaStarts(html) {
3987
4033
  }
3988
4034
  return starts;
3989
4035
  }
3990
- function adoptRuntimeMediaStart(composition, el, authored) {
4036
+ function isVideoAudio(audio, videoId) {
4037
+ return audio.type === "video" && audio.id === videoAudioId(videoId);
4038
+ }
4039
+ function adoptRuntimeMediaTiming(composition, el, authored) {
3991
4040
  const shift = el.mediaStart - authored;
3992
- if (el.mediaStart <= 0 || Math.abs(shift) <= BROWSER_MEDIA_EPSILON) return;
3993
4041
  const entries = el.tagName === "video" ? [
3994
4042
  ...composition.videos.filter((video) => video.id === el.id),
3995
- ...composition.audios.filter(
3996
- (audio) => audio.type === "video" && audio.id === `${el.id}-audio`
3997
- )
4043
+ ...composition.audios.filter((audio) => isVideoAudio(audio, el.id))
3998
4044
  ] : composition.audios.filter((audio) => audio.type !== "video" && audio.id === el.id);
3999
- for (const entry of entries) entry.mediaStart += shift;
4045
+ for (const entry of entries) {
4046
+ if (typeof entry.playbackRate !== "object") {
4047
+ if (typeof el.playbackRate === "object") {
4048
+ const consumed = Math.max(0, entry.mediaStart - authored);
4049
+ const head = timeAtSourceTime(normalizeRateSpec3(entry.playbackRate), consumed);
4050
+ entry.mediaStart += sourceTimeAt3(el.playbackRate, head) - consumed;
4051
+ entry.playbackRate = shiftRateLane2(el.playbackRate, head);
4052
+ } else {
4053
+ entry.playbackRate = el.playbackRate;
4054
+ }
4055
+ }
4056
+ if (el.mediaStart > 0 && Math.abs(shift) > BROWSER_MEDIA_EPSILON) entry.mediaStart += shift;
4057
+ }
4000
4058
  }
4001
4059
  function reconcileBrowserMediaEnd(existingEnd, projectedEnd, sourceChanged, durationInferred) {
4002
4060
  if (projectedEnd <= 0) return existingEnd;
@@ -4280,7 +4338,7 @@ async function runProbeStage(input) {
4280
4338
  sourceChanged,
4281
4339
  el.durationInferred
4282
4340
  );
4283
- adoptRuntimeMediaStart(
4341
+ adoptRuntimeMediaTiming(
4284
4342
  composition,
4285
4343
  el,
4286
4344
  authoredStarts.get(el.id) ?? existing.mediaStart
@@ -4303,6 +4361,7 @@ async function runProbeStage(input) {
4303
4361
  start: el.start,
4304
4362
  end: resolveBrowserMediaEnd(el.start, el.end, el.duration),
4305
4363
  mediaStart: el.mediaStart,
4364
+ playbackRate: el.playbackRate,
4306
4365
  loop: el.loop,
4307
4366
  hasAudio: el.hasAudio && !el.muted
4308
4367
  });
@@ -4327,7 +4386,7 @@ async function runProbeStage(input) {
4327
4386
  sourceChanged,
4328
4387
  el.durationInferred
4329
4388
  );
4330
- adoptRuntimeMediaStart(
4389
+ adoptRuntimeMediaTiming(
4331
4390
  composition,
4332
4391
  el,
4333
4392
  authoredStarts.get(el.id) ?? existing.mediaStart
@@ -4345,6 +4404,7 @@ async function runProbeStage(input) {
4345
4404
  end: resolveBrowserMediaEnd(el.start, el.end, el.duration),
4346
4405
  mediaStart: el.mediaStart,
4347
4406
  loop: el.loop,
4407
+ playbackRate: el.playbackRate,
4348
4408
  layer: 0,
4349
4409
  volume: el.volume,
4350
4410
  type: "audio"
@@ -4605,7 +4665,8 @@ import {
4605
4665
  isHttpUrl as isHttpUrl2,
4606
4666
  resolveProjectRelativeSrc as resolveProjectRelativeSrc3,
4607
4667
  runVideoExtractionWithRetry,
4608
- safeVideoExtractionSourceIdentity
4668
+ safeVideoExtractionSourceIdentity,
4669
+ videoAudioId as videoAudioId2
4609
4670
  } from "@hyperframes/engine";
4610
4671
 
4611
4672
  // src/services/render/extractionFailureMetadata.ts
@@ -4963,7 +5024,7 @@ function appendAutoDetectedVideoAudio(composition, extracted) {
4963
5024
  const video = composition.videos.find((v) => v.id === ext.videoId);
4964
5025
  if (!video || !video.hasAudio || video.hidden || existingAudioSrcs.has(video.src)) continue;
4965
5026
  composition.audios.push({
4966
- id: `${video.id}-audio`,
5027
+ id: videoAudioId2(video.id),
4967
5028
  src: video.src,
4968
5029
  start: video.start,
4969
5030
  end: video.end,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "0.1.0",
3
3
  "buildId": "dev",
4
- "sha256": "10a061ef2b83cedec556bdfd42c76f3fd08082832f47bb2803a86b1fce3a6d99",
4
+ "sha256": "5325b9ad7580263b1e0a9ad0873c5a768b80a8807731148ebfe84ef585184902",
5
5
  "artifacts": {
6
6
  "iife": "hyperframe.runtime.iife.js",
7
7
  "esm": "hyperframe.runtime.mjs"