@hyperframes/producer 0.8.209 → 0.8.210
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/distributed.js +54 -7
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +64 -64
- package/dist/index.js +78 -12
- package/dist/public-server.js +48 -8
- package/dist/renderRequest.d.ts +2 -1
- package/dist/services/distributed/plan.d.ts +3 -1
- package/dist/services/render/deliveryEncoder.d.ts +1 -0
- package/dist/services/render/hdrMode.d.ts +1 -0
- package/dist/services/render/stages/freezePlan.d.ts +2 -0
- package/dist/services/renderOrchestrator.d.ts +3 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -847,9 +847,26 @@ function resolveHlsEncoderGopLock(outputFormat, fps, segmentSeconds) {
|
|
|
847
847
|
}
|
|
848
848
|
|
|
849
849
|
// src/services/render/deliveryEncoder.ts
|
|
850
|
-
import {
|
|
850
|
+
import {
|
|
851
|
+
PRORES_PROFILE_NAMES,
|
|
852
|
+
appendRateCapArgs,
|
|
853
|
+
isProresProfile,
|
|
854
|
+
keyframeIntervalToGopSize as keyframeIntervalToGopSize2
|
|
855
|
+
} from "@hyperframes/engine";
|
|
856
|
+
function validateProresProfile(format, proresProfile) {
|
|
857
|
+
if (proresProfile === void 0) return;
|
|
858
|
+
if (!isProresProfile(proresProfile)) {
|
|
859
|
+
throw new Error(
|
|
860
|
+
`proresProfile must be one of ${PRORES_PROFILE_NAMES.join(", ")}; got ${JSON.stringify(proresProfile)}`
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
if (format !== void 0 && format !== "mov") {
|
|
864
|
+
throw new Error(`proresProfile applies to mov renders, not ${format}`);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
851
867
|
function validateDeliveryEncoderConfig(config) {
|
|
852
|
-
const { keyframeIntervalSeconds, maxBitrate, bufferSize, format } = config;
|
|
868
|
+
const { keyframeIntervalSeconds, maxBitrate, bufferSize, format, proresProfile } = config;
|
|
869
|
+
validateProresProfile(format, proresProfile);
|
|
853
870
|
if (keyframeIntervalSeconds === void 0 && maxBitrate === void 0 && bufferSize === void 0)
|
|
854
871
|
return;
|
|
855
872
|
if (keyframeIntervalSeconds !== void 0) {
|
|
@@ -3230,14 +3247,15 @@ async function extractHdrVideoFrames(args) {
|
|
|
3230
3247
|
}
|
|
3231
3248
|
first.release();
|
|
3232
3249
|
if (video.loop) (await windows.lease(totalFrames - 1))?.release();
|
|
3250
|
+
const held = holdFirstFrameUntilStreamStarts(windows, firstTick);
|
|
3233
3251
|
out.set(videoId, {
|
|
3234
3252
|
dir: frameDir,
|
|
3235
|
-
windows,
|
|
3253
|
+
windows: held,
|
|
3236
3254
|
width: dims.width,
|
|
3237
3255
|
height: dims.height,
|
|
3238
3256
|
frameSize,
|
|
3239
3257
|
get frameCount() {
|
|
3240
|
-
return
|
|
3258
|
+
return held.totalFrames;
|
|
3241
3259
|
},
|
|
3242
3260
|
scratch: Buffer.allocUnsafe(frameSize),
|
|
3243
3261
|
loop: video.loop,
|
|
@@ -3266,9 +3284,18 @@ function hdrWindowFfmpegArgs(a) {
|
|
|
3266
3284
|
if (trim > 0) filters.push(`trim=start_frame=${trim}`);
|
|
3267
3285
|
return [
|
|
3268
3286
|
...["-ss", (a.mediaStart + seekFrame / a.fps).toFixed(6), "-i", a.srcPath],
|
|
3269
|
-
...["-vf", filters.join(","), "-frames:v", String(a.frames)]
|
|
3287
|
+
...["-vf", filters.join(","), "-frames:v", String(a.frames), "-fps_mode", "passthrough"]
|
|
3270
3288
|
];
|
|
3271
3289
|
}
|
|
3290
|
+
function holdFirstFrameUntilStreamStarts(windows, firstTick) {
|
|
3291
|
+
return {
|
|
3292
|
+
get totalFrames() {
|
|
3293
|
+
return firstTick + windows.totalFrames;
|
|
3294
|
+
},
|
|
3295
|
+
lease: (frameIndex) => windows.lease(Math.max(0, frameIndex - firstTick)),
|
|
3296
|
+
close: () => windows.close()
|
|
3297
|
+
};
|
|
3298
|
+
}
|
|
3272
3299
|
function decodeHdrImageBuffers(args) {
|
|
3273
3300
|
const { log, hdrImageSrcPaths, prep, hdrDiagnostics } = args;
|
|
3274
3301
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -4834,6 +4861,12 @@ function logHdrResolution(input, hdrMode, effectiveHdr, forcedHdrWithoutSources)
|
|
|
4834
4861
|
`[Render] HDR ${reason}, output: ${effectiveHdr.transfer.toUpperCase()} (BT.2020, 10-bit H.265)`
|
|
4835
4862
|
);
|
|
4836
4863
|
}
|
|
4864
|
+
function formatCarriesHdr(format) {
|
|
4865
|
+
return format === "mp4";
|
|
4866
|
+
}
|
|
4867
|
+
function rendersSdrOnly(config) {
|
|
4868
|
+
return config.hdrMode === "force-sdr" || !formatCarriesHdr(config.format ?? "mp4");
|
|
4869
|
+
}
|
|
4837
4870
|
function resolveEffectiveHdrMode(input) {
|
|
4838
4871
|
const hdrMode = input.hdrMode ?? "auto";
|
|
4839
4872
|
const videoColorSpaces = (input.extractionResult?.extracted ?? []).map(
|
|
@@ -4855,7 +4888,7 @@ function resolveEffectiveHdrMode(input) {
|
|
|
4855
4888
|
} else if (info?.hasHdr && info.dominantTransfer) {
|
|
4856
4889
|
effectiveHdr = { transfer: info.dominantTransfer };
|
|
4857
4890
|
}
|
|
4858
|
-
if (effectiveHdr && input.outputFormat
|
|
4891
|
+
if (effectiveHdr && !formatCarriesHdr(input.outputFormat)) {
|
|
4859
4892
|
input.log.warn(formatDowngradeWarning(input.outputFormat, forcedHdrWithoutSources));
|
|
4860
4893
|
effectiveHdr = void 0;
|
|
4861
4894
|
}
|
|
@@ -9477,7 +9510,7 @@ async function runExtractVideosStage(input) {
|
|
|
9477
9510
|
fps: job.config.fps,
|
|
9478
9511
|
outputDir: join18(compiledDir, "__hyperframes_video_frames"),
|
|
9479
9512
|
format: job.config.videoFrameFormat ?? "auto",
|
|
9480
|
-
toneMapHdrToSdr: job.config
|
|
9513
|
+
toneMapHdrToSdr: rendersSdrOnly(job.config),
|
|
9481
9514
|
timelineEnd: composition.duration,
|
|
9482
9515
|
maxTransientRetries: extractionPolicy.maxTransientRetries,
|
|
9483
9516
|
collectProbeFailures: extractionPolicy.failureMode === "enforce",
|
|
@@ -14061,7 +14094,12 @@ async function executeRenderPipeline(input) {
|
|
|
14061
14094
|
});
|
|
14062
14095
|
const encoderHdr = hasHdrContent ? effectiveHdr : void 0;
|
|
14063
14096
|
const presetFormat = outputFormat === "webm" || outputFormat === "mov" ? outputFormat : "mp4";
|
|
14064
|
-
const preset = getEncoderPreset3(
|
|
14097
|
+
const preset = getEncoderPreset3(
|
|
14098
|
+
job.config.quality,
|
|
14099
|
+
presetFormat,
|
|
14100
|
+
encoderHdr,
|
|
14101
|
+
job.config.proresProfile
|
|
14102
|
+
);
|
|
14065
14103
|
if (job.config.crf != null && job.config.videoBitrate) {
|
|
14066
14104
|
log.warn(
|
|
14067
14105
|
`[Render] Both crf=${job.config.crf} and videoBitrate=${job.config.videoBitrate} were set. These are mutually exclusive; honoring crf and ignoring videoBitrate. Set only one to silence this warning.`
|
|
@@ -14876,6 +14914,7 @@ async function executeRenderPipeline(input) {
|
|
|
14876
14914
|
|
|
14877
14915
|
// src/renderRequest.ts
|
|
14878
14916
|
import {
|
|
14917
|
+
PRORES_PROFILE_NAMES as PRORES_PROFILE_NAMES2,
|
|
14879
14918
|
isVideoFrameFormat as isVideoFrameFormat2,
|
|
14880
14919
|
resolveConfig as resolveConfig4,
|
|
14881
14920
|
validateEngineConfigSnapshot as validateEngineConfigSnapshot2
|
|
@@ -16893,6 +16932,8 @@ function buildLockedRenderConfig(input) {
|
|
|
16893
16932
|
closedGop: true,
|
|
16894
16933
|
forceKeyframes: "n=0",
|
|
16895
16934
|
pixelFormat,
|
|
16935
|
+
// Omitted for the default so existing 4444 plans keep their planHash.
|
|
16936
|
+
...config.proresProfile && config.proresProfile !== "4444" ? { proresProfile: config.proresProfile } : {},
|
|
16896
16937
|
chunkSize: input.effectiveChunkSize,
|
|
16897
16938
|
chunkCount: input.chunkCount,
|
|
16898
16939
|
runtimeEnv: input.runtimeEnv,
|
|
@@ -16914,7 +16955,11 @@ function resolveEncoderTriple(config) {
|
|
|
16914
16955
|
`[plan] DistributedRenderConfig.codec is only valid for format="mp4"; received codec=${JSON.stringify(config.codec)} with format=${JSON.stringify(config.format)}. Omit codec for non-mp4 formats: mov is always ProRes 4444, webm is always libvpx-vp9, and png-sequence has no encoder.`
|
|
16915
16956
|
);
|
|
16916
16957
|
}
|
|
16917
|
-
return resolveNonMp4EncoderTriple(
|
|
16958
|
+
return resolveNonMp4EncoderTriple(
|
|
16959
|
+
config.format,
|
|
16960
|
+
config.quality ?? "standard",
|
|
16961
|
+
config.proresProfile
|
|
16962
|
+
);
|
|
16918
16963
|
}
|
|
16919
16964
|
function resolveMp4EncoderTriple(codec) {
|
|
16920
16965
|
const c = codec ?? "h264";
|
|
@@ -16928,9 +16973,10 @@ function resolveMp4EncoderTriple(codec) {
|
|
|
16928
16973
|
}
|
|
16929
16974
|
return { encoder: "libx264-software", pixelFormat: "yuv420p", preset: "medium" };
|
|
16930
16975
|
}
|
|
16931
|
-
function resolveNonMp4EncoderTriple(format, quality) {
|
|
16976
|
+
function resolveNonMp4EncoderTriple(format, quality, proresProfile) {
|
|
16932
16977
|
if (format === "mov") {
|
|
16933
|
-
|
|
16978
|
+
const { pixelFormat, preset } = getEncoderPreset4(quality, "mov", void 0, proresProfile);
|
|
16979
|
+
return { encoder: "prores-software", pixelFormat, preset };
|
|
16934
16980
|
}
|
|
16935
16981
|
if (format === "webm") {
|
|
16936
16982
|
const enginePreset = getEncoderPreset4(quality, "webm");
|
|
@@ -17585,6 +17631,18 @@ function validateDistributedRenderConfig(config) {
|
|
|
17585
17631
|
error instanceof Error ? error.message : String(error)
|
|
17586
17632
|
);
|
|
17587
17633
|
}
|
|
17634
|
+
try {
|
|
17635
|
+
validateDeliveryEncoderConfig({
|
|
17636
|
+
format: config.format,
|
|
17637
|
+
fps: { num: config.fps, den: 1 },
|
|
17638
|
+
proresProfile: config.proresProfile
|
|
17639
|
+
});
|
|
17640
|
+
} catch (error) {
|
|
17641
|
+
throw new InvalidConfigError(
|
|
17642
|
+
"config.proresProfile",
|
|
17643
|
+
error instanceof Error ? error.message : String(error)
|
|
17644
|
+
);
|
|
17645
|
+
}
|
|
17588
17646
|
if (config.chunkSize !== void 0) {
|
|
17589
17647
|
if (!Number.isInteger(config.chunkSize) || config.chunkSize < 1) {
|
|
17590
17648
|
throw new InvalidConfigError(
|
|
@@ -17824,6 +17882,7 @@ function assertRequestOptionScalars(options) {
|
|
|
17824
17882
|
for (const field of ["entryFile", "videoBitrate", "maxBitrate", "bufferSize"]) {
|
|
17825
17883
|
assertOptionalString(options, field);
|
|
17826
17884
|
}
|
|
17885
|
+
assertOptionalEnum(options, "proresProfile", PRORES_PROFILE_NAMES2);
|
|
17827
17886
|
assertOptionalEnum(options, "strictness", ["strict", "best-effort"]);
|
|
17828
17887
|
assertOptionalEnum(options, "hdrMode", ["auto", "force-hdr", "force-sdr"]);
|
|
17829
17888
|
assertOptionalEnum(options, "pageMotionBlur", ["off"]);
|
|
@@ -17925,6 +17984,7 @@ function distributedConfigFromRequest(request, runtime = {}) {
|
|
|
17925
17984
|
pageMotionBlur: options.pageMotionBlur,
|
|
17926
17985
|
bitrate: options.videoBitrate,
|
|
17927
17986
|
keyframeIntervalSeconds: options.keyframeIntervalSeconds,
|
|
17987
|
+
proresProfile: options.proresProfile,
|
|
17928
17988
|
maxBitrate: options.maxBitrate,
|
|
17929
17989
|
bufferSize: options.bufferSize,
|
|
17930
17990
|
videoFrameFormat: options.videoFrameFormat,
|
|
@@ -17975,6 +18035,7 @@ function renderRequestFromDistributedConfig(input) {
|
|
|
17975
18035
|
...optionalProperty("pageMotionBlur", config.pageMotionBlur),
|
|
17976
18036
|
...optionalProperty("videoBitrate", config.bitrate),
|
|
17977
18037
|
...optionalProperty("keyframeIntervalSeconds", config.keyframeIntervalSeconds),
|
|
18038
|
+
...optionalProperty("proresProfile", config.proresProfile),
|
|
17978
18039
|
...optionalProperty("maxBitrate", config.maxBitrate),
|
|
17979
18040
|
...optionalProperty("bufferSize", config.bufferSize),
|
|
17980
18041
|
...optionalProperty("videoFrameFormat", config.videoFrameFormat),
|
|
@@ -20597,7 +20658,12 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
20597
20658
|
const isPngSequence = plan2.dimensions.format === "png-sequence";
|
|
20598
20659
|
outputKind = isPngSequence ? "frame-dir" : "file";
|
|
20599
20660
|
const presetFormat = isPngSequence ? "mp4" : plan2.dimensions.format;
|
|
20600
|
-
const basePreset = getEncoderPreset6(
|
|
20661
|
+
const basePreset = getEncoderPreset6(
|
|
20662
|
+
job.config.quality,
|
|
20663
|
+
presetFormat,
|
|
20664
|
+
void 0,
|
|
20665
|
+
encoder.proresProfile
|
|
20666
|
+
);
|
|
20601
20667
|
const preset = resolvePresetForLockedEncoder(basePreset, encoder.encoder);
|
|
20602
20668
|
const effectiveQuality = encoder.crf ?? preset.quality;
|
|
20603
20669
|
const effectiveBitrate = encoder.crf != null ? void 0 : encoder.bitrate;
|
package/dist/public-server.js
CHANGED
|
@@ -868,9 +868,26 @@ function resolveHlsEncoderGopLock(outputFormat, fps, segmentSeconds) {
|
|
|
868
868
|
}
|
|
869
869
|
|
|
870
870
|
// src/services/render/deliveryEncoder.ts
|
|
871
|
-
import {
|
|
871
|
+
import {
|
|
872
|
+
PRORES_PROFILE_NAMES,
|
|
873
|
+
appendRateCapArgs,
|
|
874
|
+
isProresProfile,
|
|
875
|
+
keyframeIntervalToGopSize as keyframeIntervalToGopSize2
|
|
876
|
+
} from "@hyperframes/engine";
|
|
877
|
+
function validateProresProfile(format, proresProfile) {
|
|
878
|
+
if (proresProfile === void 0) return;
|
|
879
|
+
if (!isProresProfile(proresProfile)) {
|
|
880
|
+
throw new Error(
|
|
881
|
+
`proresProfile must be one of ${PRORES_PROFILE_NAMES.join(", ")}; got ${JSON.stringify(proresProfile)}`
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
if (format !== void 0 && format !== "mov") {
|
|
885
|
+
throw new Error(`proresProfile applies to mov renders, not ${format}`);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
872
888
|
function validateDeliveryEncoderConfig(config) {
|
|
873
|
-
const { keyframeIntervalSeconds, maxBitrate, bufferSize, format } = config;
|
|
889
|
+
const { keyframeIntervalSeconds, maxBitrate, bufferSize, format, proresProfile } = config;
|
|
890
|
+
validateProresProfile(format, proresProfile);
|
|
874
891
|
if (keyframeIntervalSeconds === void 0 && maxBitrate === void 0 && bufferSize === void 0)
|
|
875
892
|
return;
|
|
876
893
|
if (keyframeIntervalSeconds !== void 0) {
|
|
@@ -3247,14 +3264,15 @@ async function extractHdrVideoFrames(args) {
|
|
|
3247
3264
|
}
|
|
3248
3265
|
first.release();
|
|
3249
3266
|
if (video.loop) (await windows.lease(totalFrames - 1))?.release();
|
|
3267
|
+
const held = holdFirstFrameUntilStreamStarts(windows, firstTick);
|
|
3250
3268
|
out.set(videoId, {
|
|
3251
3269
|
dir: frameDir,
|
|
3252
|
-
windows,
|
|
3270
|
+
windows: held,
|
|
3253
3271
|
width: dims.width,
|
|
3254
3272
|
height: dims.height,
|
|
3255
3273
|
frameSize,
|
|
3256
3274
|
get frameCount() {
|
|
3257
|
-
return
|
|
3275
|
+
return held.totalFrames;
|
|
3258
3276
|
},
|
|
3259
3277
|
scratch: Buffer.allocUnsafe(frameSize),
|
|
3260
3278
|
loop: video.loop,
|
|
@@ -3283,9 +3301,18 @@ function hdrWindowFfmpegArgs(a) {
|
|
|
3283
3301
|
if (trim > 0) filters.push(`trim=start_frame=${trim}`);
|
|
3284
3302
|
return [
|
|
3285
3303
|
...["-ss", (a.mediaStart + seekFrame / a.fps).toFixed(6), "-i", a.srcPath],
|
|
3286
|
-
...["-vf", filters.join(","), "-frames:v", String(a.frames)]
|
|
3304
|
+
...["-vf", filters.join(","), "-frames:v", String(a.frames), "-fps_mode", "passthrough"]
|
|
3287
3305
|
];
|
|
3288
3306
|
}
|
|
3307
|
+
function holdFirstFrameUntilStreamStarts(windows, firstTick) {
|
|
3308
|
+
return {
|
|
3309
|
+
get totalFrames() {
|
|
3310
|
+
return firstTick + windows.totalFrames;
|
|
3311
|
+
},
|
|
3312
|
+
lease: (frameIndex) => windows.lease(Math.max(0, frameIndex - firstTick)),
|
|
3313
|
+
close: () => windows.close()
|
|
3314
|
+
};
|
|
3315
|
+
}
|
|
3289
3316
|
function decodeHdrImageBuffers(args) {
|
|
3290
3317
|
const { log, hdrImageSrcPaths, prep, hdrDiagnostics } = args;
|
|
3291
3318
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -4851,6 +4878,12 @@ function logHdrResolution(input, hdrMode, effectiveHdr, forcedHdrWithoutSources)
|
|
|
4851
4878
|
`[Render] HDR ${reason}, output: ${effectiveHdr.transfer.toUpperCase()} (BT.2020, 10-bit H.265)`
|
|
4852
4879
|
);
|
|
4853
4880
|
}
|
|
4881
|
+
function formatCarriesHdr(format) {
|
|
4882
|
+
return format === "mp4";
|
|
4883
|
+
}
|
|
4884
|
+
function rendersSdrOnly(config) {
|
|
4885
|
+
return config.hdrMode === "force-sdr" || !formatCarriesHdr(config.format ?? "mp4");
|
|
4886
|
+
}
|
|
4854
4887
|
function resolveEffectiveHdrMode(input) {
|
|
4855
4888
|
const hdrMode = input.hdrMode ?? "auto";
|
|
4856
4889
|
const videoColorSpaces = (input.extractionResult?.extracted ?? []).map(
|
|
@@ -4872,7 +4905,7 @@ function resolveEffectiveHdrMode(input) {
|
|
|
4872
4905
|
} else if (info?.hasHdr && info.dominantTransfer) {
|
|
4873
4906
|
effectiveHdr = { transfer: info.dominantTransfer };
|
|
4874
4907
|
}
|
|
4875
|
-
if (effectiveHdr && input.outputFormat
|
|
4908
|
+
if (effectiveHdr && !formatCarriesHdr(input.outputFormat)) {
|
|
4876
4909
|
input.log.warn(formatDowngradeWarning(input.outputFormat, forcedHdrWithoutSources));
|
|
4877
4910
|
effectiveHdr = void 0;
|
|
4878
4911
|
}
|
|
@@ -9458,7 +9491,7 @@ async function runExtractVideosStage(input) {
|
|
|
9458
9491
|
fps: job.config.fps,
|
|
9459
9492
|
outputDir: join18(compiledDir, "__hyperframes_video_frames"),
|
|
9460
9493
|
format: job.config.videoFrameFormat ?? "auto",
|
|
9461
|
-
toneMapHdrToSdr: job.config
|
|
9494
|
+
toneMapHdrToSdr: rendersSdrOnly(job.config),
|
|
9462
9495
|
timelineEnd: composition.duration,
|
|
9463
9496
|
maxTransientRetries: extractionPolicy.maxTransientRetries,
|
|
9464
9497
|
collectProbeFailures: extractionPolicy.failureMode === "enforce",
|
|
@@ -14042,7 +14075,12 @@ async function executeRenderPipeline(input) {
|
|
|
14042
14075
|
});
|
|
14043
14076
|
const encoderHdr = hasHdrContent ? effectiveHdr : void 0;
|
|
14044
14077
|
const presetFormat = outputFormat === "webm" || outputFormat === "mov" ? outputFormat : "mp4";
|
|
14045
|
-
const preset = getEncoderPreset3(
|
|
14078
|
+
const preset = getEncoderPreset3(
|
|
14079
|
+
job.config.quality,
|
|
14080
|
+
presetFormat,
|
|
14081
|
+
encoderHdr,
|
|
14082
|
+
job.config.proresProfile
|
|
14083
|
+
);
|
|
14046
14084
|
if (job.config.crf != null && job.config.videoBitrate) {
|
|
14047
14085
|
log.warn(
|
|
14048
14086
|
`[Render] Both crf=${job.config.crf} and videoBitrate=${job.config.videoBitrate} were set. These are mutually exclusive; honoring crf and ignoring videoBitrate. Set only one to silence this warning.`
|
|
@@ -15072,6 +15110,7 @@ import { parseEncoderOptions } from "@hyperframes/studio-server/encoder-options"
|
|
|
15072
15110
|
|
|
15073
15111
|
// src/renderRequest.ts
|
|
15074
15112
|
import {
|
|
15113
|
+
PRORES_PROFILE_NAMES as PRORES_PROFILE_NAMES2,
|
|
15075
15114
|
isVideoFrameFormat as isVideoFrameFormat2,
|
|
15076
15115
|
resolveConfig as resolveConfig4,
|
|
15077
15116
|
validateEngineConfigSnapshot as validateEngineConfigSnapshot2
|
|
@@ -15354,6 +15393,7 @@ function assertRequestOptionScalars(options) {
|
|
|
15354
15393
|
for (const field of ["entryFile", "videoBitrate", "maxBitrate", "bufferSize"]) {
|
|
15355
15394
|
assertOptionalString(options, field);
|
|
15356
15395
|
}
|
|
15396
|
+
assertOptionalEnum(options, "proresProfile", PRORES_PROFILE_NAMES2);
|
|
15357
15397
|
assertOptionalEnum(options, "strictness", ["strict", "best-effort"]);
|
|
15358
15398
|
assertOptionalEnum(options, "hdrMode", ["auto", "force-hdr", "force-sdr"]);
|
|
15359
15399
|
assertOptionalEnum(options, "pageMotionBlur", ["off"]);
|
package/dist/renderRequest.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EngineConfig, type VideoFrameFormat } from "@hyperframes/engine";
|
|
1
|
+
import { type EngineConfig, type ProresProfile, type VideoFrameFormat } from "@hyperframes/engine";
|
|
2
2
|
import { type CanvasResolution, type Fps } from "@hyperframes/core";
|
|
3
3
|
import type { ProducerLogger } from "./logger.js";
|
|
4
4
|
import type { RenderConfig } from "./services/renderOrchestrator.js";
|
|
@@ -38,6 +38,7 @@ export interface RenderRequestOptions {
|
|
|
38
38
|
crf?: number;
|
|
39
39
|
videoBitrate?: string;
|
|
40
40
|
keyframeIntervalSeconds?: number;
|
|
41
|
+
proresProfile?: ProresProfile;
|
|
41
42
|
maxBitrate?: string;
|
|
42
43
|
bufferSize?: string;
|
|
43
44
|
videoFrameFormat?: VideoFrameFormat;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CanvasResolution, type DistributedFps } from "@hyperframes/core";
|
|
2
|
-
import { type EngineConfig, type VideoFrameFormat, type AudioProcessingFailure } from "@hyperframes/engine";
|
|
2
|
+
import { type EngineConfig, type VideoFrameFormat, type ProresProfile, type AudioProcessingFailure } from "@hyperframes/engine";
|
|
3
3
|
import { type ProducerLogger } from "../../logger.js";
|
|
4
4
|
import { type RenderJob, type RenderStrictness } from "../renderOrchestrator.js";
|
|
5
5
|
import { type ChunkSliceJson, type PlanFileDigests } from "../render/stages/freezePlan.js";
|
|
@@ -49,6 +49,8 @@ export interface DistributedRenderConfig extends Pick<RenderRequestOptions, "pag
|
|
|
49
49
|
bitrate?: string;
|
|
50
50
|
/** Longest gap between keyframes, in seconds (mp4). Chunk joins add keyframes, so this is a maximum. */
|
|
51
51
|
keyframeIntervalSeconds?: number;
|
|
52
|
+
/** ProRes profile for `format: "mov"`; the 422 profiles have no alpha. Defaults to `4444`. */
|
|
53
|
+
proresProfile?: ProresProfile;
|
|
52
54
|
/** Peak bitrate cap (mp4), per chunk. */
|
|
53
55
|
maxBitrate?: string;
|
|
54
56
|
/** Rate-cap buffer; defaults to twice `maxBitrate`. */
|
|
@@ -7,6 +7,7 @@ export interface DeliveryEncoderConfig {
|
|
|
7
7
|
keyframeIntervalSeconds?: number;
|
|
8
8
|
maxBitrate?: string;
|
|
9
9
|
bufferSize?: string;
|
|
10
|
+
proresProfile?: string;
|
|
10
11
|
}
|
|
11
12
|
/** The `EncoderOptions` fields the delivery config sets, ready to spread into any encoder input. */
|
|
12
13
|
export interface DeliveryEncoderOptions {
|
|
@@ -34,5 +34,6 @@ export declare function findRenderHdrAutoPromotionTrigger(input: {
|
|
|
34
34
|
}[];
|
|
35
35
|
nativeHdrImageIds: ReadonlySet<string>;
|
|
36
36
|
}): string | undefined;
|
|
37
|
+
export declare function rendersSdrOnly(config: Pick<RenderConfig, "hdrMode" | "format">): boolean;
|
|
37
38
|
export declare function resolveEffectiveHdrMode(input: HdrModeInput): EffectiveHdr;
|
|
38
39
|
export {};
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* has in memory.
|
|
11
11
|
*/
|
|
12
12
|
import type { Fps } from "@hyperframes/core";
|
|
13
|
+
import type { ProresProfile } from "@hyperframes/engine";
|
|
13
14
|
import type { RenderRequestOptions } from "../../../renderRequest.js";
|
|
14
15
|
import { type PlanDimensions } from "./planHash.js";
|
|
15
16
|
/**
|
|
@@ -32,6 +33,7 @@ export interface LockedRenderConfig extends Pick<RenderRequestOptions, "pageMoti
|
|
|
32
33
|
*/
|
|
33
34
|
quality: "draft" | "standard" | "high";
|
|
34
35
|
ffmpegVersion: string;
|
|
36
|
+
proresProfile?: ProresProfile;
|
|
35
37
|
preset: string;
|
|
36
38
|
crf?: number;
|
|
37
39
|
bitrate?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CanvasResolution, type Fps, type FpsInput, type HfVfxCapture } from "@hyperframes/core";
|
|
2
|
-
import { type EngineConfig, type ExtractionPhaseBreakdown, type VideoFrameFormat, type CaptureOptions, type CaptureVideoMetadataHint, type CaptureSession, type BeforeCaptureHook, type ParallelProgress, type WorkerTask, type CapturePerfSummary, type CaptureWarning, type SubTimelineWaitOutcome, type WorkerSizing, type StaticVerificationOutcome, type CaptureFailureKind, type MotionBlurOptions } from "@hyperframes/engine";
|
|
2
|
+
import { type EngineConfig, type ExtractionPhaseBreakdown, type VideoFrameFormat, type CaptureOptions, type CaptureVideoMetadataHint, type CaptureSession, type BeforeCaptureHook, type ProresProfile, type ParallelProgress, type WorkerTask, type CapturePerfSummary, type CaptureWarning, type SubTimelineWaitOutcome, type WorkerSizing, type StaticVerificationOutcome, type CaptureFailureKind, type MotionBlurOptions } from "@hyperframes/engine";
|
|
3
3
|
import { type ProducerLogger } from "../logger.js";
|
|
4
4
|
import { type RenderOutputFormat } from "./render/renderFormat.js";
|
|
5
5
|
import { type RenderCaptureObservability, type RenderObservabilitySummary, type OpenStallAttempt, type StageStallRule } from "./render/observability.js";
|
|
@@ -103,6 +103,8 @@ export interface RenderConfig {
|
|
|
103
103
|
videoBitrate?: string;
|
|
104
104
|
/** Keyframe every N seconds (mp4). A maximum where chunks join, as on Lambda. */
|
|
105
105
|
keyframeIntervalSeconds?: number;
|
|
106
|
+
/** MOV only: ProRes profile. Default `4444` keeps alpha; the 422 profiles drop it. */
|
|
107
|
+
proresProfile?: ProresProfile;
|
|
106
108
|
/** Peak bitrate cap (e.g. "8M", mp4) alongside CRF. */
|
|
107
109
|
maxBitrate?: string;
|
|
108
110
|
/** Rate-cap buffer; defaults to twice `maxBitrate`. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/producer",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.210",
|
|
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.2.1",
|
|
37
37
|
"puppeteer-core": "^25.2.1",
|
|
38
|
-
"@hyperframes/core": "0.8.
|
|
39
|
-
"@hyperframes/engine": "0.8.
|
|
40
|
-
"@hyperframes/lint": "0.8.
|
|
41
|
-
"@hyperframes/
|
|
42
|
-
"@hyperframes/
|
|
38
|
+
"@hyperframes/core": "0.8.210",
|
|
39
|
+
"@hyperframes/engine": "0.8.210",
|
|
40
|
+
"@hyperframes/lint": "0.8.210",
|
|
41
|
+
"@hyperframes/studio-server": "0.8.210",
|
|
42
|
+
"@hyperframes/parsers": "0.8.210"
|
|
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.
|
|
51
|
+
"@hyperframes/aws-lambda": "0.8.210"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=22"
|