@hyperframes/producer 0.4.22 → 0.4.23
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 +53 -14
- package/dist/index.js.map +3 -3
- package/dist/public-server.js +53 -14
- 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/public-server.js
CHANGED
|
@@ -101919,7 +101919,7 @@ function getAttr(tag, attr) {
|
|
|
101919
101919
|
return match2 ? match2[1] ?? null : null;
|
|
101920
101920
|
}
|
|
101921
101921
|
function hasAttr(tag, attr) {
|
|
101922
|
-
return new RegExp(
|
|
101922
|
+
return new RegExp(`\\s${attr}(?:\\s|=|>|/)`).test(tag);
|
|
101923
101923
|
}
|
|
101924
101924
|
function injectAttr(tag, attr, value) {
|
|
101925
101925
|
return tag.replace(/>$/, ` ${attr}="${value}">`);
|
|
@@ -102030,7 +102030,8 @@ function extractResolvedMedia(html) {
|
|
|
102030
102030
|
src: getAttr(tag, "src") ?? void 0,
|
|
102031
102031
|
start: startStr !== null ? parseFloat(startStr) : 0,
|
|
102032
102032
|
duration,
|
|
102033
|
-
mediaStart: mediaStartStr ? parseFloat(mediaStartStr) : 0
|
|
102033
|
+
mediaStart: mediaStartStr ? parseFloat(mediaStartStr) : 0,
|
|
102034
|
+
loop: hasAttr(tag, "loop")
|
|
102034
102035
|
});
|
|
102035
102036
|
}
|
|
102036
102037
|
return resolved;
|
|
@@ -105498,6 +105499,7 @@ async function extractMediaMetadata(filePath) {
|
|
|
105498
105499
|
videoCodec: "png",
|
|
105499
105500
|
hasAudio: false,
|
|
105500
105501
|
isVFR: false,
|
|
105502
|
+
hasAlpha: false,
|
|
105501
105503
|
colorSpace: stillImageMeta.colorSpace
|
|
105502
105504
|
};
|
|
105503
105505
|
}
|
|
@@ -105512,6 +105514,9 @@ async function extractMediaMetadata(filePath) {
|
|
|
105512
105514
|
const colorSpaceVal = videoStream.color_space || "";
|
|
105513
105515
|
const ffprobeColorSpace = colorTransfer || colorPrimaries || colorSpaceVal ? { colorTransfer, colorPrimaries, colorSpace: colorSpaceVal } : null;
|
|
105514
105516
|
const colorSpace = ffprobeColorSpace ?? stillImageMeta?.colorSpace ?? null;
|
|
105517
|
+
const pixelFormat = videoStream.pix_fmt || "";
|
|
105518
|
+
const alphaMode = videoStream.tags?.alpha_mode || "";
|
|
105519
|
+
const hasAlpha = /(^|[^a-z])yuva|rgba|argb|bgra|gbrap|gray[a-z0-9]*a/i.test(pixelFormat) || alphaMode === "1";
|
|
105515
105520
|
return {
|
|
105516
105521
|
durationSeconds: output2?.format.duration ? parseFloat(output2.format.duration) : 0,
|
|
105517
105522
|
width: videoStream.width || stillImageMeta?.width || 0,
|
|
@@ -105520,6 +105525,7 @@ async function extractMediaMetadata(filePath) {
|
|
|
105520
105525
|
videoCodec: videoStream.codec_name || "unknown",
|
|
105521
105526
|
hasAudio: output2?.streams.some((s) => s.codec_type === "audio") ?? false,
|
|
105522
105527
|
isVFR,
|
|
105528
|
+
hasAlpha,
|
|
105523
105529
|
colorSpace
|
|
105524
105530
|
};
|
|
105525
105531
|
})();
|
|
@@ -105820,6 +105826,7 @@ function parseVideoElements(html) {
|
|
|
105820
105826
|
start,
|
|
105821
105827
|
end,
|
|
105822
105828
|
mediaStart: mediaStartAttr ? parseFloat(mediaStartAttr) : 0,
|
|
105829
|
+
loop: el.hasAttribute("loop"),
|
|
105823
105830
|
hasAudio: hasAudioAttr === "true"
|
|
105824
105831
|
});
|
|
105825
105832
|
}
|
|
@@ -105855,10 +105862,11 @@ function parseImageElements(html) {
|
|
|
105855
105862
|
}
|
|
105856
105863
|
async function extractVideoFramesRange(videoPath, videoId, startTime, duration, options, signal, config2, outputDirOverride) {
|
|
105857
105864
|
const ffmpegProcessTimeout = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
|
|
105858
|
-
const { fps, outputDir, quality = 95
|
|
105865
|
+
const { fps, outputDir, quality = 95 } = options;
|
|
105859
105866
|
const videoOutputDir = outputDirOverride ?? join9(outputDir, videoId);
|
|
105860
105867
|
if (!existsSync9(videoOutputDir)) mkdirSync6(videoOutputDir, { recursive: true });
|
|
105861
105868
|
const metadata = await extractMediaMetadata(videoPath);
|
|
105869
|
+
const format3 = resolveFrameFormat(metadata, options.format);
|
|
105862
105870
|
const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format3}`;
|
|
105863
105871
|
const outputPattern = join9(videoOutputDir, framePattern);
|
|
105864
105872
|
const isHdr = isHdrColorSpace(metadata.colorSpace);
|
|
@@ -105867,6 +105875,9 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
105867
105875
|
if (isHdr && isMacOS) {
|
|
105868
105876
|
args.push("-hwaccel", "videotoolbox");
|
|
105869
105877
|
}
|
|
105878
|
+
if (metadata.hasAlpha && metadata.videoCodec === "vp9") {
|
|
105879
|
+
args.push("-c:v", "libvpx-vp9");
|
|
105880
|
+
}
|
|
105870
105881
|
args.push("-ss", String(startTime), "-i", videoPath, "-t", String(duration));
|
|
105871
105882
|
const vfFilters = [];
|
|
105872
105883
|
if (isHdr && isMacOS) {
|
|
@@ -105978,6 +105989,10 @@ function resolveSegmentDuration(requested, mediaStart, metadata) {
|
|
|
105978
105989
|
const sourceRemaining = metadata.durationSeconds - mediaStart;
|
|
105979
105990
|
return sourceRemaining > 0 ? sourceRemaining : metadata.durationSeconds;
|
|
105980
105991
|
}
|
|
105992
|
+
function resolveFrameFormat(metadata, requested) {
|
|
105993
|
+
if (requested) return requested;
|
|
105994
|
+
return metadata.hasAlpha ? "png" : "jpg";
|
|
105995
|
+
}
|
|
105981
105996
|
async function convertVfrToCfr(inputPath, outputPath, targetFps, startTime, duration, signal, config2) {
|
|
105982
105997
|
const timeout2 = config2?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
|
|
105983
105998
|
const args = [
|
|
@@ -106170,12 +106185,12 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
|
|
|
106170
106185
|
breakdown.vfrPreflightMs = Date.now() - vfrPreflightStart;
|
|
106171
106186
|
const phase3Start = Date.now();
|
|
106172
106187
|
const cacheRootDir = config2?.extractCacheDir;
|
|
106173
|
-
const cacheFormat = options.format ?? "jpg";
|
|
106174
106188
|
async function tryCachedExtract(video, videoPath, videoDuration, i) {
|
|
106175
106189
|
if (!cacheRootDir) return null;
|
|
106176
106190
|
const keyInput = cacheKeyInputs[i];
|
|
106177
106191
|
const probedMeta = videoMetadata[i];
|
|
106178
106192
|
if (!keyInput || !probedMeta) return null;
|
|
106193
|
+
const cacheFormat = resolveFrameFormat(probedMeta, options.format);
|
|
106179
106194
|
const keyDuration = resolveSegmentDuration(
|
|
106180
106195
|
keyInput.end - keyInput.start,
|
|
106181
106196
|
keyInput.mediaStart,
|
|
@@ -106208,7 +106223,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
|
|
|
106208
106223
|
video.id,
|
|
106209
106224
|
video.mediaStart,
|
|
106210
106225
|
videoDuration,
|
|
106211
|
-
options,
|
|
106226
|
+
{ ...options, format: cacheFormat },
|
|
106212
106227
|
signal,
|
|
106213
106228
|
config2,
|
|
106214
106229
|
lookup.entry.dir
|
|
@@ -106238,7 +106253,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
|
|
|
106238
106253
|
video.id,
|
|
106239
106254
|
video.mediaStart,
|
|
106240
106255
|
videoDuration,
|
|
106241
|
-
options,
|
|
106256
|
+
{ ...options, format: resolveFrameFormat(probedMeta, options.format) },
|
|
106242
106257
|
signal,
|
|
106243
106258
|
config2
|
|
106244
106259
|
);
|
|
@@ -106271,10 +106286,17 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config2,
|
|
|
106271
106286
|
phaseBreakdown: breakdown
|
|
106272
106287
|
};
|
|
106273
106288
|
}
|
|
106274
|
-
function getFrameAtTime(extracted, globalTime, videoStart) {
|
|
106275
|
-
|
|
106289
|
+
function getFrameAtTime(extracted, globalTime, videoStart, loop = false, mediaStart = 0) {
|
|
106290
|
+
let localTime = globalTime - videoStart;
|
|
106276
106291
|
if (localTime < 0) return null;
|
|
106292
|
+
const loopDuration = Math.max(0, extracted.metadata.durationSeconds - mediaStart);
|
|
106293
|
+
if (loop && loopDuration > 0 && localTime >= loopDuration) {
|
|
106294
|
+
localTime %= loopDuration;
|
|
106295
|
+
}
|
|
106277
106296
|
const frameIndex = Math.floor(localTime * extracted.fps);
|
|
106297
|
+
if (loop && frameIndex >= extracted.totalFrames && extracted.totalFrames > 0) {
|
|
106298
|
+
return extracted.framePaths.get(extracted.totalFrames - 1) || null;
|
|
106299
|
+
}
|
|
106278
106300
|
if (frameIndex < 0 || frameIndex >= extracted.totalFrames) return null;
|
|
106279
106301
|
return extracted.framePaths.get(frameIndex) || null;
|
|
106280
106302
|
}
|
|
@@ -106284,8 +106306,8 @@ var FrameLookupTable = class {
|
|
|
106284
106306
|
activeVideoIds = /* @__PURE__ */ new Set();
|
|
106285
106307
|
startCursor = 0;
|
|
106286
106308
|
lastTime = null;
|
|
106287
|
-
addVideo(extracted, start, end, mediaStart) {
|
|
106288
|
-
this.videos.set(extracted.videoId, { extracted, start, end, mediaStart });
|
|
106309
|
+
addVideo(extracted, start, end, mediaStart, loop = false) {
|
|
106310
|
+
this.videos.set(extracted.videoId, { extracted, start, end, mediaStart, loop });
|
|
106289
106311
|
this.orderedVideos = Array.from(this.videos.entries()).map(([videoId, video]) => ({ videoId, ...video })).sort((a, b) => a.start - b.start);
|
|
106290
106312
|
this.resetActiveState();
|
|
106291
106313
|
}
|
|
@@ -106293,7 +106315,7 @@ var FrameLookupTable = class {
|
|
|
106293
106315
|
const video = this.videos.get(videoId);
|
|
106294
106316
|
if (!video) return null;
|
|
106295
106317
|
if (globalTime < video.start || globalTime >= video.end) return null;
|
|
106296
|
-
return getFrameAtTime(video.extracted, globalTime, video.start);
|
|
106318
|
+
return getFrameAtTime(video.extracted, globalTime, video.start, video.loop, video.mediaStart);
|
|
106297
106319
|
}
|
|
106298
106320
|
resetActiveState() {
|
|
106299
106321
|
this.activeVideoIds.clear();
|
|
@@ -106342,8 +106364,19 @@ var FrameLookupTable = class {
|
|
|
106342
106364
|
for (const videoId of this.activeVideoIds) {
|
|
106343
106365
|
const video = this.videos.get(videoId);
|
|
106344
106366
|
if (!video) continue;
|
|
106345
|
-
|
|
106367
|
+
let localTime = globalTime - video.start;
|
|
106368
|
+
const loopDuration = Math.max(0, video.extracted.metadata.durationSeconds - video.mediaStart);
|
|
106369
|
+
if (video.loop && loopDuration > 0 && localTime >= loopDuration) {
|
|
106370
|
+
localTime %= loopDuration;
|
|
106371
|
+
}
|
|
106346
106372
|
const frameIndex = Math.floor(localTime * video.extracted.fps);
|
|
106373
|
+
if (video.loop && frameIndex >= video.extracted.totalFrames) {
|
|
106374
|
+
const framePath2 = video.extracted.framePaths.get(video.extracted.totalFrames - 1);
|
|
106375
|
+
if (framePath2) {
|
|
106376
|
+
frames.set(videoId, { framePath: framePath2, frameIndex: video.extracted.totalFrames - 1 });
|
|
106377
|
+
}
|
|
106378
|
+
continue;
|
|
106379
|
+
}
|
|
106347
106380
|
if (frameIndex < 0 || frameIndex >= video.extracted.totalFrames) continue;
|
|
106348
106381
|
const framePath = video.extracted.framePaths.get(frameIndex);
|
|
106349
106382
|
if (!framePath) continue;
|
|
@@ -106377,7 +106410,7 @@ function createFrameLookupTable(videos, extracted) {
|
|
|
106377
106410
|
for (const ext of extracted) extractedMap.set(ext.videoId, ext);
|
|
106378
106411
|
for (const video of videos) {
|
|
106379
106412
|
const ext = extractedMap.get(video.id);
|
|
106380
|
-
if (ext) table.addVideo(ext, video.start, video.end, video.mediaStart);
|
|
106413
|
+
if (ext) table.addVideo(ext, video.start, video.end, video.mediaStart, video.loop);
|
|
106381
106414
|
}
|
|
106382
106415
|
return table;
|
|
106383
106416
|
}
|
|
@@ -109300,7 +109333,7 @@ async function compileHtmlFile(html, baseDir, downloadDir) {
|
|
|
109300
109333
|
let compiledHtml = resolutions.length > 0 ? injectDurations(staticCompiled, resolutions) : staticCompiled;
|
|
109301
109334
|
const preResolved = extractResolvedMedia(compiledHtml);
|
|
109302
109335
|
const clampResults = await Promise.all(
|
|
109303
|
-
preResolved.filter((el) => !!el.src).map(async (el) => {
|
|
109336
|
+
preResolved.filter((el) => !!el.src && !el.loop).map(async (el) => {
|
|
109304
109337
|
const { duration: maxDuration } = await resolveMediaDuration(
|
|
109305
109338
|
el.src,
|
|
109306
109339
|
el.mediaStart,
|
|
@@ -109908,6 +109941,7 @@ async function discoverMediaFromBrowser(page) {
|
|
|
109908
109941
|
const end = parseFloat(htmlEl.getAttribute("data-end") || "0");
|
|
109909
109942
|
const duration = parseFloat(htmlEl.getAttribute("data-duration") || "0");
|
|
109910
109943
|
const mediaStart = parseFloat(htmlEl.getAttribute("data-media-start") || "0");
|
|
109944
|
+
const loop = htmlEl.hasAttribute("loop");
|
|
109911
109945
|
const hasAudio = htmlEl.getAttribute("data-has-audio") === "true";
|
|
109912
109946
|
const volume = parseFloat(htmlEl.getAttribute("data-volume") || "1");
|
|
109913
109947
|
results.push({
|
|
@@ -109918,6 +109952,7 @@ async function discoverMediaFromBrowser(page) {
|
|
|
109918
109952
|
end,
|
|
109919
109953
|
duration,
|
|
109920
109954
|
mediaStart,
|
|
109955
|
+
loop,
|
|
109921
109956
|
hasAudio,
|
|
109922
109957
|
volume
|
|
109923
109958
|
});
|
|
@@ -110792,6 +110827,9 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
110792
110827
|
if (el.hasAudio && !existing.hasAudio) {
|
|
110793
110828
|
existing.hasAudio = true;
|
|
110794
110829
|
}
|
|
110830
|
+
if (el.loop && !existing.loop) {
|
|
110831
|
+
existing.loop = true;
|
|
110832
|
+
}
|
|
110795
110833
|
}
|
|
110796
110834
|
} else {
|
|
110797
110835
|
composition.videos.push({
|
|
@@ -110800,6 +110838,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
110800
110838
|
start: el.start,
|
|
110801
110839
|
end: el.end,
|
|
110802
110840
|
mediaStart: el.mediaStart,
|
|
110841
|
+
loop: el.loop,
|
|
110803
110842
|
hasAudio: el.hasAudio
|
|
110804
110843
|
});
|
|
110805
110844
|
existingVideoIds.add(el.id);
|