@hyperframes/engine 0.8.172 → 0.8.174
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/config.d.ts +2 -0
- package/dist/config.js +7 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/services/chunkEncoder.js +4 -3
- package/dist/services/extractionCache.d.ts +1 -1
- package/dist/services/extractionCache.js +1 -1
- package/dist/services/frameCapture.d.ts +1 -0
- package/dist/services/frameCapture.js +11 -0
- package/dist/services/streamingEncoder.js +12 -13
- package/dist/services/videoFrameExtractor.js +31 -10
- package/dist/utils/hdr.d.ts +1 -0
- package/dist/utils/hdr.js +4 -0
- package/dist/utils/sdrCaptureColor.d.ts +1 -1
- package/dist/utils/sdrCaptureColor.js +1 -1
- package/package.json +3 -3
package/dist/config.d.ts
CHANGED
|
@@ -404,6 +404,8 @@ export declare function explainDrawElementDisabled(args: {
|
|
|
404
404
|
workerEncode: boolean;
|
|
405
405
|
chromeCeiling?: number;
|
|
406
406
|
}): "unsupported_platform" | "old_chrome" | "software_gpu" | "worker_encode_off" | "disabled";
|
|
407
|
+
/** `pageNavigationTimeout` alone, for callers that need the page-load budget without the rest of the config. */
|
|
408
|
+
export declare function resolvePageNavigationTimeout(): number;
|
|
407
409
|
export declare function resolveConfig(overrides?: Partial<EngineConfig>): EngineConfig;
|
|
408
410
|
/**
|
|
409
411
|
* Runtime-resolved companion to the software-GPU screenshot clamp in
|
package/dist/config.js
CHANGED
|
@@ -444,6 +444,12 @@ export function explainDrawElementDisabled(args) {
|
|
|
444
444
|
return "worker_encode_off";
|
|
445
445
|
return "disabled";
|
|
446
446
|
}
|
|
447
|
+
/** `pageNavigationTimeout` alone, for callers that need the page-load budget without the rest of the config. */
|
|
448
|
+
export function resolvePageNavigationTimeout() {
|
|
449
|
+
const raw = process.env.PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS;
|
|
450
|
+
const parsed = raw === undefined || raw === "" ? NaN : Number(raw);
|
|
451
|
+
return Number.isFinite(parsed) ? parsed : DEFAULT_CONFIG.pageNavigationTimeout;
|
|
452
|
+
}
|
|
447
453
|
export function resolveConfig(overrides) {
|
|
448
454
|
const env = (key) => process.env[key];
|
|
449
455
|
const envNum = (key, fallback) => {
|
|
@@ -528,7 +534,7 @@ export function resolveConfig(overrides) {
|
|
|
528
534
|
frameDataUriCacheBytesLimitMb: Math.max(64, envNum("PRODUCER_FRAME_DATA_URI_CACHE_BYTES_MB", memoryAdaptiveCacheBytesMb())),
|
|
529
535
|
playerReadyTimeout: envNum("PRODUCER_PLAYER_READY_TIMEOUT_MS", DEFAULT_CONFIG.playerReadyTimeout),
|
|
530
536
|
renderReadyTimeout: envNum("PRODUCER_RENDER_READY_TIMEOUT_MS", DEFAULT_CONFIG.renderReadyTimeout),
|
|
531
|
-
pageNavigationTimeout:
|
|
537
|
+
pageNavigationTimeout: resolvePageNavigationTimeout(),
|
|
532
538
|
verifyRuntime: env("PRODUCER_VERIFY_HYPERFRAME_RUNTIME") !== "false",
|
|
533
539
|
runtimeManifestPath: env("PRODUCER_HYPERFRAME_MANIFEST_PATH"),
|
|
534
540
|
extractCacheDir: resolveExtractCacheDirFromEnv(env),
|
package/dist/index.d.ts
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
*
|
|
31
31
|
*/
|
|
32
32
|
export type { HfProtocol, HfMediaElement, HfTransitionMeta, CaptureOptions, CaptureVideoMetadataHint, CaptureResult, CaptureBufferResult, CapturePerfSummary, CaptureWarning, CaptureWarningCode, SubTimelineWaitMemo, SubTimelineWaitOutcome, } from "./types.js";
|
|
33
|
-
export { resolveConfig, validateEngineConfigSnapshot, DEFAULT_CONFIG, scaleProtocolTimeoutForComposition, shouldClampToScreenshotForConcreteGpu, applyConcreteGpuScreenshotClamp, explainDrawElementDisabled, resolveExtractCacheDir, defaultExtractCacheDir, EXTRACT_CACHE_DIR_DISABLED_ALIASES, type EngineConfig, type ExtractCacheDirResolution, } from "./config.js";
|
|
33
|
+
export { resolveConfig, resolvePageNavigationTimeout, validateEngineConfigSnapshot, DEFAULT_CONFIG, scaleProtocolTimeoutForComposition, shouldClampToScreenshotForConcreteGpu, applyConcreteGpuScreenshotClamp, explainDrawElementDisabled, resolveExtractCacheDir, defaultExtractCacheDir, EXTRACT_CACHE_DIR_DISABLED_ALIASES, type EngineConfig, type ExtractCacheDirResolution, } from "./config.js";
|
|
34
34
|
export { SDR_RGB_TO_BT709_FILTER, SDR_RGB_TO_TAGGED_BT709_FILTER, } from "./utils/sdrCaptureColor.js";
|
|
35
35
|
export { DEFAULT_VP9_CPU_USED, MAX_VP9_CPU_USED, MIN_VP9_CPU_USED, normalizeVp9CpuUsed, } from "./services/vp9Options.js";
|
|
36
36
|
export { getCgroupMemoryLimitMb, getSystemTotalMb, isLowMemorySystem, LOW_MEMORY_TOTAL_MB_THRESHOLD, } from "./services/systemMemory.js";
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
*
|
|
31
31
|
*/
|
|
32
32
|
// ── Configuration ──────────────────────────────────────────────────────────────
|
|
33
|
-
export { resolveConfig, validateEngineConfigSnapshot, DEFAULT_CONFIG, scaleProtocolTimeoutForComposition, shouldClampToScreenshotForConcreteGpu, applyConcreteGpuScreenshotClamp, explainDrawElementDisabled, resolveExtractCacheDir, defaultExtractCacheDir, EXTRACT_CACHE_DIR_DISABLED_ALIASES, } from "./config.js";
|
|
33
|
+
export { resolveConfig, resolvePageNavigationTimeout, validateEngineConfigSnapshot, DEFAULT_CONFIG, scaleProtocolTimeoutForComposition, shouldClampToScreenshotForConcreteGpu, applyConcreteGpuScreenshotClamp, explainDrawElementDisabled, resolveExtractCacheDir, defaultExtractCacheDir, EXTRACT_CACHE_DIR_DISABLED_ALIASES, } from "./config.js";
|
|
34
34
|
export { SDR_RGB_TO_BT709_FILTER, SDR_RGB_TO_TAGGED_BT709_FILTER, } from "./utils/sdrCaptureColor.js";
|
|
35
35
|
export { DEFAULT_VP9_CPU_USED, MAX_VP9_CPU_USED, MIN_VP9_CPU_USED, normalizeVp9CpuUsed, } from "./services/vp9Options.js";
|
|
36
36
|
export { getCgroupMemoryLimitMb, getSystemTotalMb, isLowMemorySystem, LOW_MEMORY_TOTAL_MB_THRESHOLD, } from "./services/systemMemory.js";
|
|
@@ -9,7 +9,7 @@ import { closeSync, copyFileSync, existsSync, ftruncateSync, mkdirSync, mkdtempS
|
|
|
9
9
|
import { join, dirname, extname } from "path";
|
|
10
10
|
import { DEFAULT_CONFIG } from "../config.js";
|
|
11
11
|
import { getCachedGpuEncoder, getGpuEncoderName, buildVideoToolboxRateControlArgs, mapPresetForGpuEncoder, } from "../utils/gpuEncoder.js";
|
|
12
|
-
import { getHdrEncoderColorParams } from "../utils/hdr.js";
|
|
12
|
+
import { getHdrEncoderColorParams, hdrFrameTagsFilter } from "../utils/hdr.js";
|
|
13
13
|
import { withEvenDimensionPad } from "../utils/evenDimensions.js";
|
|
14
14
|
import { SDR_CAPTURE_TO_BT709_FILTER, SDR_RGB_TO_TAGGED_BT709_FILTER, } from "../utils/sdrCaptureColor.js";
|
|
15
15
|
import { describeFfmpegFailure, ffmpegStatsReader, formatFfmpegError, isExternalFfmpegInterruption, runFfmpeg, } from "../utils/runFfmpeg.js";
|
|
@@ -325,8 +325,9 @@ export function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = nu
|
|
|
325
325
|
}
|
|
326
326
|
// Range conversion: Chrome's full-range capture → limited/TV range; SDR also
|
|
327
327
|
// converts to the BT.709 matrix it is tagged with.
|
|
328
|
+
const hdrTags = options.hdr ? hdrFrameTagsFilter(options.hdr.transfer) : undefined;
|
|
328
329
|
const sdrFilter = options.hdr ? undefined : SDR_CAPTURE_TO_BT709_FILTER;
|
|
329
|
-
const captureFilter = sdrFilter ??
|
|
330
|
+
const captureFilter = sdrFilter ?? `scale=in_range=pc:out_range=tv,${hdrTags}`;
|
|
330
331
|
if (gpuEncoder === "vaapi") {
|
|
331
332
|
// vaapi already runs `format=nv12,hwupload`; the nv12 conversion aligns
|
|
332
333
|
// odd dimensions before upload, so only prepend the colour conversion.
|
|
@@ -340,7 +341,7 @@ export function buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder = nu
|
|
|
340
341
|
// encoder. They hit the same "height not divisible by 2" abort as
|
|
341
342
|
// libx264 on an odd-sized 4:2:0 canvas, so pad odd dimensions up to even
|
|
342
343
|
// on the software side before the encode.
|
|
343
|
-
const vf = withEvenDimensionPad(sdrFilter ?? "", pixelFormat, options.width, options.height);
|
|
344
|
+
const vf = withEvenDimensionPad(sdrFilter ?? hdrTags ?? "", pixelFormat, options.width, options.height);
|
|
344
345
|
if (vf)
|
|
345
346
|
args.push("-vf", vf);
|
|
346
347
|
}
|
|
@@ -42,7 +42,7 @@ export declare const GC_MARKER = ".hf-last-gc";
|
|
|
42
42
|
* Current schema version. Bump it whenever extraction writes different frames for the same key,
|
|
43
43
|
* or warm entries keep serving the old frames across a deploy. Each bump's commit says why.
|
|
44
44
|
*/
|
|
45
|
-
export declare const SCHEMA_PREFIX = "hfcache-
|
|
45
|
+
export declare const SCHEMA_PREFIX = "hfcache-v8-";
|
|
46
46
|
export type CacheFrameFormat = "jpg" | "png";
|
|
47
47
|
export interface CacheKeyInput {
|
|
48
48
|
/** Absolute path to the source video file. Part of the key so moved files
|
|
@@ -45,7 +45,7 @@ export const GC_MARKER = ".hf-last-gc";
|
|
|
45
45
|
* Current schema version. Bump it whenever extraction writes different frames for the same key,
|
|
46
46
|
* or warm entries keep serving the old frames across a deploy. Each bump's commit says why.
|
|
47
47
|
*/
|
|
48
|
-
export const SCHEMA_PREFIX = "hfcache-
|
|
48
|
+
export const SCHEMA_PREFIX = "hfcache-v8-";
|
|
49
49
|
/** Truncated hex chars of SHA-256 used for the entry directory name. */
|
|
50
50
|
const KEY_HEX_CHARS = 16;
|
|
51
51
|
export async function readContentSha256(path, signal) {
|
|
@@ -130,6 +130,7 @@ export interface CaptureSession {
|
|
|
130
130
|
beginFrameIntervalMs: number;
|
|
131
131
|
beginFrameHasDamageCount: number;
|
|
132
132
|
beginFrameNoDamageCount: number;
|
|
133
|
+
beginFrameSeekPresented?: boolean;
|
|
133
134
|
/** Optional producer config — when set, overrides module-level env var constants. */
|
|
134
135
|
config?: Partial<EngineConfig>;
|
|
135
136
|
/** True if running on SwiftShader (detected at init). Undefined before init. */
|
|
@@ -2971,6 +2971,17 @@ async function captureFrameSurface(session, frameIndex, time, seekOptions, heldV
|
|
|
2971
2971
|
let screenshotBuffer;
|
|
2972
2972
|
if (session.captureMode === "beginframe") {
|
|
2973
2973
|
const frameTimeTicks = session.beginFrameTimeTicks + frameIndex * session.beginFrameIntervalMs;
|
|
2974
|
+
if (!session.beginFrameSeekPresented) {
|
|
2975
|
+
// A session's first capture can return the frame composited during init instead of
|
|
2976
|
+
// this seek, so display the seek once at a tick between the probe and this capture.
|
|
2977
|
+
const client = await getCdpSession(page);
|
|
2978
|
+
await client.send("HeadlessExperimental.beginFrame", {
|
|
2979
|
+
frameTimeTicks: frameTimeTicks - session.beginFrameIntervalMs / 2,
|
|
2980
|
+
interval: session.beginFrameIntervalMs,
|
|
2981
|
+
noDisplayUpdates: false,
|
|
2982
|
+
});
|
|
2983
|
+
session.beginFrameSeekPresented = true;
|
|
2984
|
+
}
|
|
2974
2985
|
const result = await beginFrameCapture(page, options, frameTimeTicks, session.beginFrameIntervalMs);
|
|
2975
2986
|
if (result.hasDamage)
|
|
2976
2987
|
session.beginFrameHasDamageCount++;
|
|
@@ -22,9 +22,9 @@ import { dirname } from "path";
|
|
|
22
22
|
import { getCachedGpuEncoder, getGpuEncoderName, buildVideoToolboxRateControlArgs, mapPresetForGpuEncoder, } from "../utils/gpuEncoder.js";
|
|
23
23
|
import { ffmpegStatsReader, formatFfmpegError, isExternalFfmpegInterruption, } from "../utils/runFfmpeg.js";
|
|
24
24
|
import { getFfmpegBinary } from "../utils/ffmpegBinaries.js";
|
|
25
|
-
import { getHdrEncoderColorParams } from "../utils/hdr.js";
|
|
25
|
+
import { getHdrEncoderColorParams, hdrFrameTagsFilter } from "../utils/hdr.js";
|
|
26
26
|
import { withEvenDimensionPad } from "../utils/evenDimensions.js";
|
|
27
|
-
import { SDR_CAPTURE_TO_BT709_FILTER,
|
|
27
|
+
import { SDR_CAPTURE_TO_BT709_FILTER, SDR_RGB_TO_TAGGED_BT709_FILTER, } from "../utils/sdrCaptureColor.js";
|
|
28
28
|
import { DEFAULT_CONFIG } from "../config.js";
|
|
29
29
|
import { fpsToFfmpegArg, fpsToNumber } from "@hyperframes/core";
|
|
30
30
|
import { appendVp9CpuUsedArg } from "./vp9Options.js";
|
|
@@ -248,26 +248,25 @@ export function buildStreamingArgs(options, outputPath, gpuEncoder = null) {
|
|
|
248
248
|
else {
|
|
249
249
|
args.push("-colorspace:v", "bt709", "-color_primaries:v", "bt709", "-color_trc:v", "bt709", "-color_range", "tv");
|
|
250
250
|
}
|
|
251
|
-
// Raw HDR input (from WebGPU pipeline) is already PQ-encoded
|
|
252
|
-
//
|
|
253
|
-
const
|
|
254
|
-
?
|
|
255
|
-
:
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
else if (gpuEncoder === "vaapi") {
|
|
251
|
+
// Raw HDR input (from WebGPU pipeline) is already PQ-encoded and is only tagged; SDR is
|
|
252
|
+
// converted: raw sRGB or Chrome's BT.601 JPEG screenshots to tagged BT.709 limited range.
|
|
253
|
+
const frameFilter = options.rawInputFormat && options.hdr
|
|
254
|
+
? hdrFrameTagsFilter(options.hdr.transfer)
|
|
255
|
+
: options.rawInputFormat
|
|
256
|
+
? SDR_RGB_TO_TAGGED_BT709_FILTER
|
|
257
|
+
: SDR_CAPTURE_TO_BT709_FILTER;
|
|
258
|
+
if (gpuEncoder === "vaapi") {
|
|
260
259
|
// vaapi already runs `format=nv12,hwupload`; the nv12 conversion aligns
|
|
261
260
|
// odd dimensions before upload, so only prepend the colour conversion.
|
|
262
261
|
const vfIdx = args.indexOf("-vf");
|
|
263
262
|
if (vfIdx !== -1) {
|
|
264
|
-
args[vfIdx + 1] = `${
|
|
263
|
+
args[vfIdx + 1] = `${frameFilter},${args[vfIdx + 1]}`;
|
|
265
264
|
}
|
|
266
265
|
}
|
|
267
266
|
else {
|
|
268
267
|
// Pad odd dimensions up to even so 4:2:0 encoders (software and
|
|
269
268
|
// nvenc/videotoolbox/qsv/amf) don't abort with "height not divisible by 2".
|
|
270
|
-
args.push("-vf", withEvenDimensionPad(
|
|
269
|
+
args.push("-vf", withEvenDimensionPad(frameFilter, pixelFormat, options.width, options.height));
|
|
271
270
|
}
|
|
272
271
|
// Fixed timescale for consistent A/V timing across platforms.
|
|
273
272
|
args.push("-video_track_timescale", "90000");
|
|
@@ -437,6 +437,14 @@ function chromeGuessForUntaggedMatrix(metadata) {
|
|
|
437
437
|
* same absolute times as a single pass, so their frames are byte-identical to it.
|
|
438
438
|
*/
|
|
439
439
|
const EXTRACTION_SEGMENT_SECONDS = 120;
|
|
440
|
+
/** Frame times since file start are `PTS*TB + seek`; snapping them to `lead + k/FR` gives every process one grid. */
|
|
441
|
+
function undoTickRoundingOnTheSourceFrameGrid(seek, lead) {
|
|
442
|
+
const sinceFileStart = `(PTS*TB+${seek}-${lead})`;
|
|
443
|
+
return [
|
|
444
|
+
"settb=AVTB",
|
|
445
|
+
`setpts=if(isnan(FR)\\,PTS\\,(${lead}+round(${sinceFileStart}*FR)/FR-${seek})/TB)`,
|
|
446
|
+
];
|
|
447
|
+
}
|
|
440
448
|
// Caps extraction ffmpeg runs across all clips; uncapped, dozens of clips starved each other into timeouts.
|
|
441
449
|
const EXTRACTION_SLOTS = Math.max(1, Math.floor(cpus().length / 2));
|
|
442
450
|
const inExtractionSlot = createConcurrencyLimit(EXTRACTION_SLOTS);
|
|
@@ -467,11 +475,12 @@ async function runSegmentedExtraction(job) {
|
|
|
467
475
|
while (next < segmentCount && !signal.aborted) {
|
|
468
476
|
const index = next++;
|
|
469
477
|
const { firstFrame, frames } = segments[index];
|
|
478
|
+
const seek = startTime + firstFrame / fps;
|
|
470
479
|
const result = await inExtractionSlot(() => runFfmpeg([
|
|
471
480
|
...decodeArgs,
|
|
472
481
|
"-noaccurate_seek",
|
|
473
482
|
"-ss",
|
|
474
|
-
String(
|
|
483
|
+
String(seek),
|
|
475
484
|
"-i",
|
|
476
485
|
videoPath,
|
|
477
486
|
// Read one frame past the segment and keep exactly its own frames.
|
|
@@ -481,7 +490,7 @@ async function runSegmentedExtraction(job) {
|
|
|
481
490
|
String(frames),
|
|
482
491
|
"-start_number",
|
|
483
492
|
String(firstFrame + 1),
|
|
484
|
-
...filterAndEncodeArgs,
|
|
493
|
+
...filterAndEncodeArgs(seek),
|
|
485
494
|
], { ...job.runOptions, signal }), signal);
|
|
486
495
|
results[index] = result;
|
|
487
496
|
if (!result.success)
|
|
@@ -580,11 +589,19 @@ outputDirOverride) {
|
|
|
580
589
|
if (decodeWithVideoToolbox) {
|
|
581
590
|
vfFilters.push("format=nv12");
|
|
582
591
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
592
|
+
const samplingAt = vfFilters.length;
|
|
593
|
+
// Each slot takes the last frame starting at or before its time. Ticks of 2 ms or finer
|
|
594
|
+
// first shift half a tick, absorbing container rounding (WebM/MKV use whole ms).
|
|
595
|
+
const samplingFilters = (seek) => sampleAtOutputFps
|
|
596
|
+
? [
|
|
597
|
+
...(metadata.isVFR
|
|
598
|
+
? []
|
|
599
|
+
: undoTickRoundingOnTheSourceFrameGrid(seek, metadata.videoStreamLeadSeconds ?? 0)),
|
|
600
|
+
"settb=intb/2",
|
|
601
|
+
"setpts=PTS-lte(TB\\,0.001)",
|
|
602
|
+
`fps=${ffmpegFps}:start_time=0:round=up`,
|
|
603
|
+
]
|
|
604
|
+
: [];
|
|
588
605
|
if (options.sdrToHdrTransfer) {
|
|
589
606
|
// Ordering intent: fps sampling runs BEFORE the colorspace remap so only
|
|
590
607
|
// kept frames are converted. The remap is pointwise per-frame, so the
|
|
@@ -610,7 +627,11 @@ outputDirOverride) {
|
|
|
610
627
|
encodeArgs.push("-compression_level", "1");
|
|
611
628
|
encodeArgs.push("-y", outputPattern);
|
|
612
629
|
const runOptions = { signal, timeout: ffmpegProcessTimeout };
|
|
613
|
-
const
|
|
630
|
+
const filterArgsFor = (seek) => {
|
|
631
|
+
const filters = [...vfFilters];
|
|
632
|
+
filters.splice(samplingAt, 0, ...samplingFilters(seek));
|
|
633
|
+
return filters.length > 0 ? ["-vf", filters.join(",")] : [];
|
|
634
|
+
};
|
|
614
635
|
const segmentFrames = Math.round(EXTRACTION_SEGMENT_SECONDS * fps);
|
|
615
636
|
const totalFrames = extractionFrameCountForDuration(duration, normalizedFps, metadata.isVFR);
|
|
616
637
|
// A VFR window rounds its frame count up, and only the segments' `-frames:v` bound
|
|
@@ -620,14 +641,14 @@ outputDirOverride) {
|
|
|
620
641
|
const processResult = sampleAtOutputFps && (options.frameRanges || boundVfrFrameCount || totalFrames > segmentFrames)
|
|
621
642
|
? await runSegmentedExtraction({
|
|
622
643
|
decodeArgs,
|
|
623
|
-
filterAndEncodeArgs: [...
|
|
644
|
+
filterAndEncodeArgs: (seek) => [...filterArgsFor(seek), ...encodeArgs],
|
|
624
645
|
videoPath,
|
|
625
646
|
startTime,
|
|
626
647
|
fps,
|
|
627
648
|
segments: splitFrameRanges(options.frameRanges ?? [{ firstFrame: 0, frames: totalFrames }], segmentFrames),
|
|
628
649
|
runOptions,
|
|
629
650
|
})
|
|
630
|
-
: await inExtractionSlot(() => runFfmpeg([...args, ...
|
|
651
|
+
: await inExtractionSlot(() => runFfmpeg([...args, ...filterArgsFor(startTime), ...encodeArgs], runOptions), signal);
|
|
631
652
|
if (processResult.failureReason === "external_interruption") {
|
|
632
653
|
throw new VideoSourceExtractionError("external_interruption", true, "Video frame extraction interrupted by host lifecycle", `FFmpeg exited with code ${processResult.exitCode}: ${processResult.stderr.slice(-500)}`);
|
|
633
654
|
}
|
package/dist/utils/hdr.d.ts
CHANGED
|
@@ -70,6 +70,7 @@ export interface HdrEncoderColorParams {
|
|
|
70
70
|
* stream is rejected as SDR by most HDR-aware players and CDNs.
|
|
71
71
|
*/
|
|
72
72
|
export declare function getHdrEncoderColorParams(transfer: HdrTransfer, mastering?: HdrMasteringMetadata): HdrEncoderColorParams;
|
|
73
|
+
export declare function hdrFrameTagsFilter(transfer: HdrTransfer): string;
|
|
73
74
|
export interface CompositionHdrInfo {
|
|
74
75
|
hasHdr: boolean;
|
|
75
76
|
dominantTransfer: HdrTransfer | null;
|
package/dist/utils/hdr.js
CHANGED
|
@@ -64,6 +64,10 @@ export function getHdrEncoderColorParams(transfer, mastering = DEFAULT_HDR10_MAS
|
|
|
64
64
|
mastering,
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
|
+
export function hdrFrameTagsFilter(transfer) {
|
|
68
|
+
const { colorPrimaries, colorTrc, colorspace } = getHdrEncoderColorParams(transfer);
|
|
69
|
+
return `setparams=color_primaries=${colorPrimaries}:color_trc=${colorTrc}:colorspace=${colorspace}:range=tv`;
|
|
70
|
+
}
|
|
67
71
|
export const HDR_AUTO_PROMOTION_PIPELINE = {
|
|
68
72
|
colorSpace: "BT.2020",
|
|
69
73
|
codec: "HEVC Main10",
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare const SDR_RGB_TO_BT709_FILTER = "scale=out_color_matrix=bt709:out_range=tv:flags=neighbor";
|
|
2
|
-
export declare const SDR_CAPTURE_TO_BT709_FILTER = "scale=in_color_matrix=bt601:in_range=pc:flags=neighbor+accurate_rnd,format=gbrp,scale=out_color_matrix=bt709:out_range=tv:flags=neighbor";
|
|
3
2
|
export declare const SDR_RGB_TO_TAGGED_BT709_FILTER = "scale=out_color_matrix=bt709:out_range=tv:flags=neighbor,setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709:range=tv";
|
|
3
|
+
export declare const SDR_CAPTURE_TO_BT709_FILTER = "scale=in_color_matrix=bt601:in_range=pc:flags=neighbor+accurate_rnd,format=gbrp,scale=out_color_matrix=bt709:out_range=tv:flags=neighbor,setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709:range=tv";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export const SDR_RGB_TO_BT709_FILTER = "scale=out_color_matrix=bt709:out_range=tv:flags=neighbor";
|
|
2
|
-
export const SDR_CAPTURE_TO_BT709_FILTER = `scale=in_color_matrix=bt601:in_range=pc:flags=neighbor+accurate_rnd,format=gbrp,${SDR_RGB_TO_BT709_FILTER}`;
|
|
3
2
|
export const SDR_RGB_TO_TAGGED_BT709_FILTER = `${SDR_RGB_TO_BT709_FILTER},setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709:range=tv`;
|
|
3
|
+
export const SDR_CAPTURE_TO_BT709_FILTER = `scale=in_color_matrix=bt601:in_range=pc:flags=neighbor+accurate_rnd,format=gbrp,${SDR_RGB_TO_TAGGED_BT709_FILTER}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/engine",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.174",
|
|
4
4
|
"description": "Seekable web page to video rendering engine (Puppeteer + FFmpeg)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"linkedom": "^0.18.12",
|
|
51
51
|
"puppeteer": "^25.8.0",
|
|
52
52
|
"puppeteer-core": "^25.8.0",
|
|
53
|
-
"@hyperframes/core": "^0.8.
|
|
54
|
-
"@hyperframes/parsers": "^0.8.
|
|
53
|
+
"@hyperframes/core": "^0.8.174",
|
|
54
|
+
"@hyperframes/parsers": "^0.8.174"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/node": "^25.0.10",
|