@hyperframes/producer 0.4.22 → 0.5.0-alpha.1
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/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +5 -5
- package/dist/index.js +59 -16
- package/dist/index.js.map +3 -3
- package/dist/public-server.js +59 -16
- package/dist/public-server.js.map +3 -3
- package/dist/services/htmlCompiler.d.ts +1 -0
- package/dist/services/htmlCompiler.d.ts.map +1 -1
- package/dist/services/renderOrchestrator.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -99130,7 +99130,7 @@ function getAttr(tag, attr) {
|
|
|
99130
99130
|
return match2 ? match2[1] ?? null : null;
|
|
99131
99131
|
}
|
|
99132
99132
|
function hasAttr(tag, attr) {
|
|
99133
|
-
return new RegExp(
|
|
99133
|
+
return new RegExp(`\\s${attr}(?:\\s|=|>|/)`).test(tag);
|
|
99134
99134
|
}
|
|
99135
99135
|
function injectAttr(tag, attr, value) {
|
|
99136
99136
|
return tag.replace(/>$/, ` ${attr}="${value}">`);
|
|
@@ -99241,7 +99241,8 @@ function extractResolvedMedia(html) {
|
|
|
99241
99241
|
src: getAttr(tag, "src") ?? void 0,
|
|
99242
99242
|
start: startStr !== null ? parseFloat(startStr) : 0,
|
|
99243
99243
|
duration,
|
|
99244
|
-
mediaStart: mediaStartStr ? parseFloat(mediaStartStr) : 0
|
|
99244
|
+
mediaStart: mediaStartStr ? parseFloat(mediaStartStr) : 0,
|
|
99245
|
+
loop: hasAttr(tag, "loop")
|
|
99245
99246
|
});
|
|
99246
99247
|
}
|
|
99247
99248
|
return resolved;
|
|
@@ -101437,8 +101438,12 @@ async function initializeSession(session) {
|
|
|
101437
101438
|
}
|
|
101438
101439
|
});
|
|
101439
101440
|
page.on("pageerror", (err) => {
|
|
101440
|
-
const
|
|
101441
|
-
|
|
101441
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
101442
|
+
const text = `[Browser:PAGEERROR] ${message}`;
|
|
101443
|
+
const isPlayAbort = /^AbortError:/.test(message) && message.includes("play()") && message.includes("pause()");
|
|
101444
|
+
if (!isPlayAbort) {
|
|
101445
|
+
console.error(text);
|
|
101446
|
+
}
|
|
101442
101447
|
session.browserConsoleBuffer.push(text);
|
|
101443
101448
|
if (session.browserConsoleBuffer.length > BROWSER_CONSOLE_BUFFER_SIZE) {
|
|
101444
101449
|
session.browserConsoleBuffer.shift();
|
|
@@ -102709,6 +102714,7 @@ async function extractMediaMetadata(filePath) {
|
|
|
102709
102714
|
videoCodec: "png",
|
|
102710
102715
|
hasAudio: false,
|
|
102711
102716
|
isVFR: false,
|
|
102717
|
+
hasAlpha: false,
|
|
102712
102718
|
colorSpace: stillImageMeta.colorSpace
|
|
102713
102719
|
};
|
|
102714
102720
|
}
|
|
@@ -102723,6 +102729,9 @@ async function extractMediaMetadata(filePath) {
|
|
|
102723
102729
|
const colorSpaceVal = videoStream.color_space || "";
|
|
102724
102730
|
const ffprobeColorSpace = colorTransfer || colorPrimaries || colorSpaceVal ? { colorTransfer, colorPrimaries, colorSpace: colorSpaceVal } : null;
|
|
102725
102731
|
const colorSpace = ffprobeColorSpace ?? stillImageMeta?.colorSpace ?? null;
|
|
102732
|
+
const pixelFormat = videoStream.pix_fmt || "";
|
|
102733
|
+
const alphaMode = videoStream.tags?.alpha_mode || "";
|
|
102734
|
+
const hasAlpha = /(^|[^a-z])yuva|rgba|argb|bgra|gbrap|gray[a-z0-9]*a/i.test(pixelFormat) || alphaMode === "1";
|
|
102726
102735
|
return {
|
|
102727
102736
|
durationSeconds: output2?.format.duration ? parseFloat(output2.format.duration) : 0,
|
|
102728
102737
|
width: videoStream.width || stillImageMeta?.width || 0,
|
|
@@ -102731,6 +102740,7 @@ async function extractMediaMetadata(filePath) {
|
|
|
102731
102740
|
videoCodec: videoStream.codec_name || "unknown",
|
|
102732
102741
|
hasAudio: output2?.streams.some((s) => s.codec_type === "audio") ?? false,
|
|
102733
102742
|
isVFR,
|
|
102743
|
+
hasAlpha,
|
|
102734
102744
|
colorSpace
|
|
102735
102745
|
};
|
|
102736
102746
|
})();
|
|
@@ -103031,6 +103041,7 @@ function parseVideoElements(html) {
|
|
|
103031
103041
|
start,
|
|
103032
103042
|
end,
|
|
103033
103043
|
mediaStart: mediaStartAttr ? parseFloat(mediaStartAttr) : 0,
|
|
103044
|
+
loop: el.hasAttribute("loop"),
|
|
103034
103045
|
hasAudio: hasAudioAttr === "true"
|
|
103035
103046
|
});
|
|
103036
103047
|
}
|
|
@@ -103066,10 +103077,11 @@ function parseImageElements(html) {
|
|
|
103066
103077
|
}
|
|
103067
103078
|
async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config2, outputDirOverride) {
|
|
103068
103079
|
const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
|
|
103069
|
-
const { fps, outputDir, quality = 95
|
|
103080
|
+
const { fps, outputDir, quality = 95 } = options;
|
|
103070
103081
|
const videoOutputDir = outputDirOverride ?? join9(outputDir, videoId);
|
|
103071
103082
|
if (!existsSync9(videoOutputDir)) mkdirSync6(videoOutputDir, { recursive: true });
|
|
103072
103083
|
const metadata = await extractMediaMetadata(videoPath);
|
|
103084
|
+
const format3 = resolveFrameFormat(metadata, options.format);
|
|
103073
103085
|
const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format3}`;
|
|
103074
103086
|
const outputPattern = join9(videoOutputDir, framePattern);
|
|
103075
103087
|
const isHdr = isHdrColorSpace(metadata.colorSpace);
|
|
@@ -103078,6 +103090,9 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
103078
103090
|
if (isHdr && isMacOS) {
|
|
103079
103091
|
args.push("-hwaccel", "videotoolbox");
|
|
103080
103092
|
}
|
|
103093
|
+
if (metadata.hasAlpha && metadata.videoCodec === "vp9") {
|
|
103094
|
+
args.push("-c:v", "libvpx-vp9");
|
|
103095
|
+
}
|
|
103081
103096
|
args.push("-ss", String(startTime), "-i", videoPath, "-t", String(duration));
|
|
103082
103097
|
const vfFilters = [];
|
|
103083
103098
|
if (isHdr && isMacOS) {
|
|
@@ -103189,6 +103204,10 @@ function resolveSegmentDuration(requested, mediaStart, metadata) {
|
|
|
103189
103204
|
const sourceRemaining = metadata.durationSeconds - mediaStart;
|
|
103190
103205
|
return sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
|
|
103191
103206
|
}
|
|
103207
|
+
function resolveFrameFormat(metadata, requested) {
|
|
103208
|
+
if (requested) return requested;
|
|
103209
|
+
return metadata.hasAlpha ? "png" : "jpg";
|
|
103210
|
+
}
|
|
103192
103211
|
async function convertVfrToCfr(inputPath, outputPath, targetFps, startTime, duration, signal, config2) {
|
|
103193
103212
|
const timeout2 = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
|
|
103194
103213
|
const args = [
|
|
@@ -103381,12 +103400,12 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
|
|
|
103381
103400
|
breakdown.vfrPreflightMs = Date.now() - vfrPreflightStart;
|
|
103382
103401
|
const phase3Start = Date.now();
|
|
103383
103402
|
const cacheRootDir = config2?.extractCacheDir;
|
|
103384
|
-
const cacheFormat = options.format ?? "jpg";
|
|
103385
103403
|
async function tryCachedExtract(video, videoPath, videoDuration, i) {
|
|
103386
103404
|
if (!cacheRootDir) return null;
|
|
103387
103405
|
const keyInput = cacheKeyInputs[i];
|
|
103388
103406
|
const probedMeta = videoMetadata[i];
|
|
103389
103407
|
if (!keyInput || !probedMeta) return null;
|
|
103408
|
+
const cacheFormat = resolveFrameFormat(probedMeta, options.format);
|
|
103390
103409
|
const keyDuration = resolveSegmentDuration(
|
|
103391
103410
|
keyInput.end - keyInput.start,
|
|
103392
103411
|
keyInput.mediaStart,
|
|
@@ -103419,7 +103438,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
|
|
|
103419
103438
|
video.id,
|
|
103420
103439
|
video.mediaStart,
|
|
103421
103440
|
videoDuration,
|
|
103422
|
-
options,
|
|
103441
|
+
{ ...options, format: cacheFormat },
|
|
103423
103442
|
signal,
|
|
103424
103443
|
config2,
|
|
103425
103444
|
lookup.entry.dir
|
|
@@ -103449,7 +103468,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
|
|
|
103449
103468
|
video.id,
|
|
103450
103469
|
video.mediaStart,
|
|
103451
103470
|
videoDuration,
|
|
103452
|
-
options,
|
|
103471
|
+
{ ...options, format: resolveFrameFormat(probedMeta, options.format) },
|
|
103453
103472
|
signal,
|
|
103454
103473
|
config2
|
|
103455
103474
|
);
|
|
@@ -103482,10 +103501,17 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
|
|
|
103482
103501
|
phaseBreakdown: breakdown
|
|
103483
103502
|
};
|
|
103484
103503
|
}
|
|
103485
|
-
function getFrameAtTime(extracted, globalTime, videoStart) {
|
|
103486
|
-
|
|
103504
|
+
function getFrameAtTime(extracted, globalTime, videoStart, loop = false, mediaStart = 0) {
|
|
103505
|
+
let localTime = globalTime - videoStart;
|
|
103487
103506
|
if (localTime < 0) return null;
|
|
103507
|
+
const loopDuration = Math.max(0, extracted.metadata.durationSeconds - mediaStart);
|
|
103508
|
+
if (loop && loopDuration > 0 && localTime >= loopDuration) {
|
|
103509
|
+
localTime %= loopDuration;
|
|
103510
|
+
}
|
|
103488
103511
|
const frameIndex = Math.floor(localTime * extracted.fps);
|
|
103512
|
+
if (loop && frameIndex >= extracted.totalFrames && extracted.totalFrames > 0) {
|
|
103513
|
+
return extracted.framePaths.get(extracted.totalFrames - 1) || null;
|
|
103514
|
+
}
|
|
103489
103515
|
if (frameIndex < 0 || frameIndex >= extracted.totalFrames) return null;
|
|
103490
103516
|
return extracted.framePaths.get(frameIndex) || null;
|
|
103491
103517
|
}
|
|
@@ -103495,8 +103521,8 @@ var FrameLookupTable = class {
|
|
|
103495
103521
|
activeVideoIds = /* @__PURE__ */ new Set();
|
|
103496
103522
|
startCursor = 0;
|
|
103497
103523
|
lastTime = null;
|
|
103498
|
-
addVideo(extracted, start, end, mediaStart) {
|
|
103499
|
-
this.videos.set(extracted.videoId, { extracted, start, end, mediaStart });
|
|
103524
|
+
addVideo(extracted, start, end, mediaStart, loop = false) {
|
|
103525
|
+
this.videos.set(extracted.videoId, { extracted, start, end, mediaStart, loop });
|
|
103500
103526
|
this.orderedVideos = Array.from(this.videos.entries()).map(([videoId, video]) => ({ videoId, ...video })).sort((a, b) => a.start - b.start);
|
|
103501
103527
|
this.resetActiveState();
|
|
103502
103528
|
}
|
|
@@ -103504,7 +103530,7 @@ var FrameLookupTable = class {
|
|
|
103504
103530
|
const video = this.videos.get(videoId);
|
|
103505
103531
|
if (!video) return null;
|
|
103506
103532
|
if (globalTime < video.start || globalTime >= video.end) return null;
|
|
103507
|
-
return getFrameAtTime(video.extracted, globalTime, video.start);
|
|
103533
|
+
return getFrameAtTime(video.extracted, globalTime, video.start, video.loop, video.mediaStart);
|
|
103508
103534
|
}
|
|
103509
103535
|
resetActiveState() {
|
|
103510
103536
|
this.activeVideoIds.clear();
|
|
@@ -103553,8 +103579,19 @@ var FrameLookupTable = class {
|
|
|
103553
103579
|
for (const videoId of this.activeVideoIds) {
|
|
103554
103580
|
const video = this.videos.get(videoId);
|
|
103555
103581
|
if (!video) continue;
|
|
103556
|
-
|
|
103582
|
+
let localTime = globalTime - video.start;
|
|
103583
|
+
const loopDuration = Math.max(0, video.extracted.metadata.durationSeconds - video.mediaStart);
|
|
103584
|
+
if (video.loop && loopDuration > 0 && localTime >= loopDuration) {
|
|
103585
|
+
localTime %= loopDuration;
|
|
103586
|
+
}
|
|
103557
103587
|
const frameIndex = Math.floor(localTime * video.extracted.fps);
|
|
103588
|
+
if (video.loop && frameIndex >= video.extracted.totalFrames) {
|
|
103589
|
+
const framePath2 = video.extracted.framePaths.get(video.extracted.totalFrames - 1);
|
|
103590
|
+
if (framePath2) {
|
|
103591
|
+
frames.set(videoId, { framePath: framePath2, frameIndex: video.extracted.totalFrames - 1 });
|
|
103592
|
+
}
|
|
103593
|
+
continue;
|
|
103594
|
+
}
|
|
103558
103595
|
if (frameIndex < 0 || frameIndex >= video.extracted.totalFrames) continue;
|
|
103559
103596
|
const framePath = video.extracted.framePaths.get(frameIndex);
|
|
103560
103597
|
if (!framePath) continue;
|
|
@@ -103588,7 +103625,7 @@ function createFrameLookupTable(videos, extracted) {
|
|
|
103588
103625
|
for (const ext of extracted) extractedMap.set(ext.videoId, ext);
|
|
103589
103626
|
for (const video of videos) {
|
|
103590
103627
|
const ext = extractedMap.get(video.id);
|
|
103591
|
-
if (ext) table.addVideo(ext, video.start, video.end, video.mediaStart);
|
|
103628
|
+
if (ext) table.addVideo(ext, video.start, video.end, video.mediaStart, video.loop);
|
|
103592
103629
|
}
|
|
103593
103630
|
return table;
|
|
103594
103631
|
}
|
|
@@ -109135,7 +109172,7 @@ async function compileHtmlFile(html, baseDir, downloadDir) {
|
|
|
109135
109172
|
let compiledHtml = resolutions.length > 0 ? injectDurations(staticCompiled, resolutions) : staticCompiled;
|
|
109136
109173
|
const preResolved = extractResolvedMedia(compiledHtml);
|
|
109137
109174
|
const clampResults = await Promise.all(
|
|
109138
|
-
preResolved.filter((el) => !!el.src).map(async (el) => {
|
|
109175
|
+
preResolved.filter((el) => !!el.src && !el.loop).map(async (el) => {
|
|
109139
109176
|
const { duration: maxDuration } = await resolveMediaDuration(
|
|
109140
109177
|
el.src,
|
|
109141
109178
|
el.mediaStart,
|
|
@@ -109743,6 +109780,7 @@ async function discoverMediaFromBrowser(page) {
|
|
|
109743
109780
|
const end = parseFloat(htmlEl.getAttribute("data-end") || "0");
|
|
109744
109781
|
const duration = parseFloat(htmlEl.getAttribute("data-duration") || "0");
|
|
109745
109782
|
const mediaStart = parseFloat(htmlEl.getAttribute("data-media-start") || "0");
|
|
109783
|
+
const loop = htmlEl.hasAttribute("loop");
|
|
109746
109784
|
const hasAudio = htmlEl.getAttribute("data-has-audio") === "true";
|
|
109747
109785
|
const volume = parseFloat(htmlEl.getAttribute("data-volume") || "1");
|
|
109748
109786
|
results.push({
|
|
@@ -109753,6 +109791,7 @@ async function discoverMediaFromBrowser(page) {
|
|
|
109753
109791
|
end,
|
|
109754
109792
|
duration,
|
|
109755
109793
|
mediaStart,
|
|
109794
|
+
loop,
|
|
109756
109795
|
hasAudio,
|
|
109757
109796
|
volume
|
|
109758
109797
|
});
|
|
@@ -110627,6 +110666,9 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
110627
110666
|
if (el.hasAudio && !existing.hasAudio) {
|
|
110628
110667
|
existing.hasAudio = true;
|
|
110629
110668
|
}
|
|
110669
|
+
if (el.loop && !existing.loop) {
|
|
110670
|
+
existing.loop = true;
|
|
110671
|
+
}
|
|
110630
110672
|
}
|
|
110631
110673
|
} else {
|
|
110632
110674
|
composition.videos.push({
|
|
@@ -110635,6 +110677,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
110635
110677
|
start: el.start,
|
|
110636
110678
|
end: el.end,
|
|
110637
110679
|
mediaStart: el.mediaStart,
|
|
110680
|
+
loop: el.loop,
|
|
110638
110681
|
hasAudio: el.hasAudio
|
|
110639
110682
|
});
|
|
110640
110683
|
existingVideoIds.add(el.id);
|