@hyperframes/producer 0.8.212 → 0.8.213

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/index.js CHANGED
@@ -2439,7 +2439,7 @@ async function blitHdrVideoLayer(canvas, el, time, fps, hdrVideoFrameSources, hd
2439
2439
  );
2440
2440
  if (effectiveIndex === null) return;
2441
2441
  const mediaTime = (frameSource.mediaStart ?? 0) + effectiveIndex / fps;
2442
- if (isVideoHiddenBeforeStreamStart(frameSource.videoStreamLeadSeconds, mediaTime)) return;
2442
+ if (isVideoHiddenBeforeStreamStart(frameSource.videoStartSeconds, mediaTime)) return;
2443
2443
  if (hdrPerf) hdrPerf.hdrVideoLayerBlits += 1;
2444
2444
  const lease = await frameSource.windows.lease(effectiveIndex);
2445
2445
  if (!lease) return;
@@ -2839,6 +2839,7 @@ import { join as join8 } from "node:path";
2839
2839
  import {
2840
2840
  decodePngToRgb48le,
2841
2841
  extractMediaMetadata as extractMediaMetadata2,
2842
+ ffmpegSeekSeconds,
2842
2843
  getCgroupMemoryLimitMb,
2843
2844
  normalizeObjectFit,
2844
2845
  queryElementStacking,
@@ -2846,7 +2847,8 @@ import {
2846
2847
  resolveFinalFrameExtractionWindow,
2847
2848
  resolveProjectRelativeSrc,
2848
2849
  resolveVideoExtractionWindow,
2849
- runFfmpeg
2850
+ runFfmpeg,
2851
+ videoStartOnMediaTimeline
2850
2852
  } from "@hyperframes/engine";
2851
2853
  import { fpsToFfmpegArg, fpsToNumber as fpsToNumber3 } from "@hyperframes/core";
2852
2854
 
@@ -3170,10 +3172,7 @@ async function extractHdrVideoFrames(args) {
3170
3172
  initialWindow,
3171
3173
  abortSignal
3172
3174
  );
3173
- extractionWindows.set(videoId, {
3174
- window: window2,
3175
- videoStreamLeadSeconds: metadata.videoStreamLeadSeconds
3176
- });
3175
+ extractionWindows.set(videoId, { window: window2, metadata });
3177
3176
  prep.hdrVideoStartTimes.set(videoId, window2.compositionStart);
3178
3177
  const frameSize = dims.width * dims.height * 6;
3179
3178
  const frames = window2.finalFrameOnly ? 1 : Math.ceil(window2.durationSeconds * fps);
@@ -3191,15 +3190,16 @@ async function extractHdrVideoFrames(args) {
3191
3190
  const video = composition.videos.find((v) => v.id === videoId);
3192
3191
  const planned = extractionWindows.get(videoId);
3193
3192
  if (!video || !planned) continue;
3194
- const { window: window2 } = planned;
3193
+ const { window: window2, metadata } = planned;
3195
3194
  mkdirSync2(framesDir, { recursive: true });
3196
3195
  const frameDir = mkdtempSync2(join8(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
3197
3196
  createdFrameDirs.add(frameDir);
3198
3197
  const dims = prep.hdrExtractionDims.get(videoId) ?? { width, height };
3199
3198
  const frameSize = dims.width * dims.height * 6;
3200
3199
  const extractionMediaStart = window2.extractionMediaStart ?? window2.mediaStart;
3200
+ const ffmpegSeek = ffmpegSeekSeconds(metadata, extractionMediaStart);
3201
3201
  const scale = `scale=${dims.width}:${dims.height}:force_original_aspect_ratio=increase,crop=${dims.width}:${dims.height}`;
3202
- const firstTick = window2.finalFrameOnly ? 0 : await probeFirstTick(srcPath, extractionMediaStart, fps, runFfmpegImpl, abortSignal);
3202
+ const firstTick = window2.finalFrameOnly ? 0 : await probeFirstTick(srcPath, ffmpegSeek, fps, runFfmpegImpl, abortSignal);
3203
3203
  const totalFrames = window2.finalFrameOnly ? 1 : Math.max(1, Math.ceil(window2.durationSeconds * fps - firstTick - 1e-9)) + Number(video.loop);
3204
3204
  const windowFrames = Math.min(totalFrames, hdrWindowFrames(frameSize, windowBytes));
3205
3205
  const windows = createHdrFrameWindows({
@@ -3212,10 +3212,19 @@ async function extractHdrVideoFrames(args) {
3212
3212
  const ffmpegArgs = window2.finalFrameOnly ? (
3213
3213
  // Decode before seeking for the one-frame path. Input-side seeking can
3214
3214
  // return zero frames for valid unindexed/negative-base transports.
3215
- ["-i", srcPath, "-ss", String(extractionMediaStart), "-frames:v", "1", "-vf", scale]
3215
+ [
3216
+ "-i",
3217
+ srcPath,
3218
+ "-ss",
3219
+ String(Math.max(0, ffmpegSeek)),
3220
+ "-frames:v",
3221
+ "1",
3222
+ "-vf",
3223
+ scale
3224
+ ]
3216
3225
  ) : hdrWindowFfmpegArgs({
3217
3226
  srcPath,
3218
- mediaStart: extractionMediaStart,
3227
+ ffmpegSeek,
3219
3228
  fps,
3220
3229
  fpsArg: fpsToFfmpegArg(job.config.fps),
3221
3230
  firstTick,
@@ -3265,7 +3274,7 @@ async function extractHdrVideoFrames(args) {
3265
3274
  scratch: Buffer.allocUnsafe(frameSize),
3266
3275
  loop: video.loop,
3267
3276
  mediaStart: extractionMediaStart,
3268
- videoStreamLeadSeconds: planned.videoStreamLeadSeconds
3277
+ videoStartSeconds: videoStartOnMediaTimeline(metadata)
3269
3278
  });
3270
3279
  }
3271
3280
  return { sources: out, estimatedBytes, releaseReservation };
@@ -3288,7 +3297,7 @@ function hdrWindowFfmpegArgs(a) {
3288
3297
  const filters = [`fps=${a.fpsArg}:start_time=${(a.firstTick / a.fps).toFixed(6)}`, a.scale];
3289
3298
  if (trim > 0) filters.push(`trim=start_frame=${trim}`);
3290
3299
  return [
3291
- ...["-ss", (a.mediaStart + seekFrame / a.fps).toFixed(6), "-i", a.srcPath],
3300
+ ...["-ss", (a.ffmpegSeek + seekFrame / a.fps).toFixed(6), "-i", a.srcPath],
3292
3301
  ...["-vf", filters.join(","), "-frames:v", String(a.frames), "-fps_mode", "passthrough"]
3293
3302
  ];
3294
3303
  }
@@ -9165,6 +9174,7 @@ function validateNoGpuEncode(config) {
9165
9174
  function validateNoSystemFonts(compiledHtml) {
9166
9175
  const customProperties = collectFontFamilyCustomProperties(compiledHtml);
9167
9176
  for (const { surface, declaration } of iterateFontFamilyDeclarations(compiledHtml)) {
9177
+ if (surface === "font") continue;
9168
9178
  const families = resolveFontFamilyDeclarationFamilies(declaration, customProperties);
9169
9179
  if (families.length === 0) continue;
9170
9180
  const primaryRaw = families[0];
@@ -15148,6 +15158,7 @@ function readVideoMetadata(value, field) {
15148
15158
  // while carrying non-zero edit-list/transport timestamps in new plans.
15149
15159
  videoStreamStartSeconds: record.videoStreamStartSeconds === void 0 ? 0 : readFiniteNumber(record.videoStreamStartSeconds, `${field}.videoStreamStartSeconds`),
15150
15160
  videoStreamLeadSeconds: record.videoStreamLeadSeconds === void 0 ? 0 : readFiniteNumber(record.videoStreamLeadSeconds, `${field}.videoStreamLeadSeconds`),
15161
+ mediaTimeOffsetSeconds: record.mediaTimeOffsetSeconds === void 0 ? 0 : readFiniteNumber(record.mediaTimeOffsetSeconds, `${field}.mediaTimeOffsetSeconds`),
15151
15162
  width: readPositiveInteger(record.width, `${field}.width`),
15152
15163
  height: readPositiveInteger(record.height, `${field}.height`),
15153
15164
  fps: readFiniteNumber(record.fps, `${field}.fps`),
@@ -2456,7 +2456,7 @@ async function blitHdrVideoLayer(canvas, el, time, fps, hdrVideoFrameSources, hd
2456
2456
  );
2457
2457
  if (effectiveIndex === null) return;
2458
2458
  const mediaTime = (frameSource.mediaStart ?? 0) + effectiveIndex / fps;
2459
- if (isVideoHiddenBeforeStreamStart(frameSource.videoStreamLeadSeconds, mediaTime)) return;
2459
+ if (isVideoHiddenBeforeStreamStart(frameSource.videoStartSeconds, mediaTime)) return;
2460
2460
  if (hdrPerf) hdrPerf.hdrVideoLayerBlits += 1;
2461
2461
  const lease = await frameSource.windows.lease(effectiveIndex);
2462
2462
  if (!lease) return;
@@ -2856,6 +2856,7 @@ import { join as join8 } from "node:path";
2856
2856
  import {
2857
2857
  decodePngToRgb48le,
2858
2858
  extractMediaMetadata as extractMediaMetadata2,
2859
+ ffmpegSeekSeconds,
2859
2860
  getCgroupMemoryLimitMb,
2860
2861
  normalizeObjectFit,
2861
2862
  queryElementStacking,
@@ -2863,7 +2864,8 @@ import {
2863
2864
  resolveFinalFrameExtractionWindow,
2864
2865
  resolveProjectRelativeSrc,
2865
2866
  resolveVideoExtractionWindow,
2866
- runFfmpeg
2867
+ runFfmpeg,
2868
+ videoStartOnMediaTimeline
2867
2869
  } from "@hyperframes/engine";
2868
2870
  import { fpsToFfmpegArg, fpsToNumber as fpsToNumber3 } from "@hyperframes/core";
2869
2871
 
@@ -3187,10 +3189,7 @@ async function extractHdrVideoFrames(args) {
3187
3189
  initialWindow,
3188
3190
  abortSignal
3189
3191
  );
3190
- extractionWindows.set(videoId, {
3191
- window: window2,
3192
- videoStreamLeadSeconds: metadata.videoStreamLeadSeconds
3193
- });
3192
+ extractionWindows.set(videoId, { window: window2, metadata });
3194
3193
  prep.hdrVideoStartTimes.set(videoId, window2.compositionStart);
3195
3194
  const frameSize = dims.width * dims.height * 6;
3196
3195
  const frames = window2.finalFrameOnly ? 1 : Math.ceil(window2.durationSeconds * fps);
@@ -3208,15 +3207,16 @@ async function extractHdrVideoFrames(args) {
3208
3207
  const video = composition.videos.find((v) => v.id === videoId);
3209
3208
  const planned = extractionWindows.get(videoId);
3210
3209
  if (!video || !planned) continue;
3211
- const { window: window2 } = planned;
3210
+ const { window: window2, metadata } = planned;
3212
3211
  mkdirSync2(framesDir, { recursive: true });
3213
3212
  const frameDir = mkdtempSync2(join8(framesDir, `hdr_${tempDirSafePrefix(videoId)}-`));
3214
3213
  createdFrameDirs.add(frameDir);
3215
3214
  const dims = prep.hdrExtractionDims.get(videoId) ?? { width, height };
3216
3215
  const frameSize = dims.width * dims.height * 6;
3217
3216
  const extractionMediaStart = window2.extractionMediaStart ?? window2.mediaStart;
3217
+ const ffmpegSeek = ffmpegSeekSeconds(metadata, extractionMediaStart);
3218
3218
  const scale = `scale=${dims.width}:${dims.height}:force_original_aspect_ratio=increase,crop=${dims.width}:${dims.height}`;
3219
- const firstTick = window2.finalFrameOnly ? 0 : await probeFirstTick(srcPath, extractionMediaStart, fps, runFfmpegImpl, abortSignal);
3219
+ const firstTick = window2.finalFrameOnly ? 0 : await probeFirstTick(srcPath, ffmpegSeek, fps, runFfmpegImpl, abortSignal);
3220
3220
  const totalFrames = window2.finalFrameOnly ? 1 : Math.max(1, Math.ceil(window2.durationSeconds * fps - firstTick - 1e-9)) + Number(video.loop);
3221
3221
  const windowFrames = Math.min(totalFrames, hdrWindowFrames(frameSize, windowBytes));
3222
3222
  const windows = createHdrFrameWindows({
@@ -3229,10 +3229,19 @@ async function extractHdrVideoFrames(args) {
3229
3229
  const ffmpegArgs = window2.finalFrameOnly ? (
3230
3230
  // Decode before seeking for the one-frame path. Input-side seeking can
3231
3231
  // return zero frames for valid unindexed/negative-base transports.
3232
- ["-i", srcPath, "-ss", String(extractionMediaStart), "-frames:v", "1", "-vf", scale]
3232
+ [
3233
+ "-i",
3234
+ srcPath,
3235
+ "-ss",
3236
+ String(Math.max(0, ffmpegSeek)),
3237
+ "-frames:v",
3238
+ "1",
3239
+ "-vf",
3240
+ scale
3241
+ ]
3233
3242
  ) : hdrWindowFfmpegArgs({
3234
3243
  srcPath,
3235
- mediaStart: extractionMediaStart,
3244
+ ffmpegSeek,
3236
3245
  fps,
3237
3246
  fpsArg: fpsToFfmpegArg(job.config.fps),
3238
3247
  firstTick,
@@ -3282,7 +3291,7 @@ async function extractHdrVideoFrames(args) {
3282
3291
  scratch: Buffer.allocUnsafe(frameSize),
3283
3292
  loop: video.loop,
3284
3293
  mediaStart: extractionMediaStart,
3285
- videoStreamLeadSeconds: planned.videoStreamLeadSeconds
3294
+ videoStartSeconds: videoStartOnMediaTimeline(metadata)
3286
3295
  });
3287
3296
  }
3288
3297
  return { sources: out, estimatedBytes, releaseReservation };
@@ -3305,7 +3314,7 @@ function hdrWindowFfmpegArgs(a) {
3305
3314
  const filters = [`fps=${a.fpsArg}:start_time=${(a.firstTick / a.fps).toFixed(6)}`, a.scale];
3306
3315
  if (trim > 0) filters.push(`trim=start_frame=${trim}`);
3307
3316
  return [
3308
- ...["-ss", (a.mediaStart + seekFrame / a.fps).toFixed(6), "-i", a.srcPath],
3317
+ ...["-ss", (a.ffmpegSeek + seekFrame / a.fps).toFixed(6), "-i", a.srcPath],
3309
3318
  ...["-vf", filters.join(","), "-frames:v", String(a.frames), "-fps_mode", "passthrough"]
3310
3319
  ];
3311
3320
  }
@@ -44,7 +44,7 @@ export interface HdrVideoFrameSource {
44
44
  /** The playable range is one source cycle and must wrap at its end. */
45
45
  loop?: boolean;
46
46
  mediaStart?: number;
47
- videoStreamLeadSeconds?: number;
47
+ videoStartSeconds?: number;
48
48
  }
49
49
  export declare function closeHdrVideoFrameSource(source: HdrVideoFrameSource, log?: ProducerLogger): void;
50
50
  export declare function resolveHdrVideoFrameIndex(time: number, startTime: number, fps: number, frameCount: number, loop?: boolean): number | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/producer",
3
- "version": "0.8.212",
3
+ "version": "0.8.213",
4
4
  "description": "HTML-to-video rendering engine using Chrome's BeginFrame API",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,11 +35,11 @@
35
35
  "postcss": "^8.4.0",
36
36
  "puppeteer": "~25.11.0",
37
37
  "puppeteer-core": "^25.11.0",
38
- "@hyperframes/engine": "0.8.212",
39
- "@hyperframes/lint": "0.8.212",
40
- "@hyperframes/parsers": "0.8.212",
41
- "@hyperframes/studio-server": "0.8.212",
42
- "@hyperframes/core": "0.8.212"
38
+ "@hyperframes/engine": "0.8.213",
39
+ "@hyperframes/lint": "0.8.213",
40
+ "@hyperframes/core": "0.8.213",
41
+ "@hyperframes/parsers": "0.8.213",
42
+ "@hyperframes/studio-server": "0.8.213"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/node": "^25.0.10",
@@ -48,7 +48,7 @@
48
48
  "tsx": "^4.21.0",
49
49
  "typescript": "^5.7.2",
50
50
  "vitest": "^4.1.11",
51
- "@hyperframes/aws-lambda": "0.8.212"
51
+ "@hyperframes/aws-lambda": "0.8.213"
52
52
  },
53
53
  "engines": {
54
54
  "node": ">=22"