hyperframes 0.4.9 → 0.4.10
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/cli.js +118 -5
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -54,7 +54,7 @@ var VERSION;
|
|
|
54
54
|
var init_version = __esm({
|
|
55
55
|
"src/version.ts"() {
|
|
56
56
|
"use strict";
|
|
57
|
-
VERSION = true ? "0.4.
|
|
57
|
+
VERSION = true ? "0.4.10" : "0.0.0-dev";
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -5411,8 +5411,8 @@ function flushSync() {
|
|
|
5411
5411
|
eventQueue = [];
|
|
5412
5412
|
const payload = JSON.stringify({ api_key: POSTHOG_API_KEY, batch });
|
|
5413
5413
|
try {
|
|
5414
|
-
const { spawn:
|
|
5415
|
-
const child =
|
|
5414
|
+
const { spawn: spawn12 } = __require("child_process");
|
|
5415
|
+
const child = spawn12(
|
|
5416
5416
|
process.execPath,
|
|
5417
5417
|
[
|
|
5418
5418
|
"-e",
|
|
@@ -34137,9 +34137,60 @@ __export(snapshot_exports, {
|
|
|
34137
34137
|
default: () => snapshot_default,
|
|
34138
34138
|
examples: () => examples18
|
|
34139
34139
|
});
|
|
34140
|
-
import {
|
|
34140
|
+
import { spawn as spawn11 } from "child_process";
|
|
34141
|
+
import { existsSync as existsSync45, mkdtempSync as mkdtempSync2, readFileSync as readFileSync31, mkdirSync as mkdirSync24, rmSync as rmSync9 } from "fs";
|
|
34142
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
34141
34143
|
import { resolve as resolve32, join as join45, dirname as dirname20, relative as relative4, isAbsolute as isAbsolute4 } from "path";
|
|
34142
34144
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
34145
|
+
async function extractVideoFrameToBuffer(videoPath, timeSeconds) {
|
|
34146
|
+
const tmp = mkdtempSync2(join45(tmpdir4(), "hf-snapshot-frame-"));
|
|
34147
|
+
const outPath = join45(tmp, "frame.png");
|
|
34148
|
+
try {
|
|
34149
|
+
const result = await new Promise(
|
|
34150
|
+
(resolvePromise) => {
|
|
34151
|
+
const ff = spawn11("ffmpeg", [
|
|
34152
|
+
"-hide_banner",
|
|
34153
|
+
"-loglevel",
|
|
34154
|
+
"error",
|
|
34155
|
+
"-ss",
|
|
34156
|
+
String(Math.max(0, timeSeconds)),
|
|
34157
|
+
"-i",
|
|
34158
|
+
videoPath,
|
|
34159
|
+
"-frames:v",
|
|
34160
|
+
"1",
|
|
34161
|
+
"-q:v",
|
|
34162
|
+
"2",
|
|
34163
|
+
"-y",
|
|
34164
|
+
outPath
|
|
34165
|
+
]);
|
|
34166
|
+
let stderr = "";
|
|
34167
|
+
let timedOut = false;
|
|
34168
|
+
const timer = setTimeout(() => {
|
|
34169
|
+
timedOut = true;
|
|
34170
|
+
ff.kill("SIGTERM");
|
|
34171
|
+
}, FFMPEG_EXTRACT_TIMEOUT_MS);
|
|
34172
|
+
ff.stderr.on("data", (d) => {
|
|
34173
|
+
stderr += d.toString();
|
|
34174
|
+
});
|
|
34175
|
+
ff.on("close", (code) => {
|
|
34176
|
+
clearTimeout(timer);
|
|
34177
|
+
resolvePromise({ code, stderr, timedOut });
|
|
34178
|
+
});
|
|
34179
|
+
ff.on("error", () => {
|
|
34180
|
+
clearTimeout(timer);
|
|
34181
|
+
resolvePromise({ code: null, stderr: "ffmpeg spawn failed", timedOut });
|
|
34182
|
+
});
|
|
34183
|
+
}
|
|
34184
|
+
);
|
|
34185
|
+
if (result.code !== 0 || result.timedOut || !existsSync45(outPath)) return null;
|
|
34186
|
+
return readFileSync31(outPath);
|
|
34187
|
+
} finally {
|
|
34188
|
+
try {
|
|
34189
|
+
rmSync9(tmp, { recursive: true, force: true });
|
|
34190
|
+
} catch {
|
|
34191
|
+
}
|
|
34192
|
+
}
|
|
34193
|
+
}
|
|
34143
34194
|
async function captureSnapshots(projectDir, opts) {
|
|
34144
34195
|
const { bundleToSingleHtml: bundleToSingleHtml2 } = await Promise.resolve().then(() => (init_compiler(), compiler_exports));
|
|
34145
34196
|
const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
|
|
@@ -34254,6 +34305,14 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
34254
34305
|
const positions = opts.at?.length ? opts.at : numFrames === 1 ? [duration / 2] : Array.from({ length: numFrames }, (_2, i2) => i2 / (numFrames - 1) * duration);
|
|
34255
34306
|
const snapshotDir = join45(projectDir, "snapshots");
|
|
34256
34307
|
mkdirSync24(snapshotDir, { recursive: true });
|
|
34308
|
+
let injectVideoFramesBatch2 = null;
|
|
34309
|
+
let syncVideoFrameVisibility2 = null;
|
|
34310
|
+
try {
|
|
34311
|
+
const engine = await Promise.resolve().then(() => (init_src2(), src_exports));
|
|
34312
|
+
injectVideoFramesBatch2 = engine.injectVideoFramesBatch;
|
|
34313
|
+
syncVideoFrameVisibility2 = engine.syncVideoFrameVisibility;
|
|
34314
|
+
} catch {
|
|
34315
|
+
}
|
|
34257
34316
|
for (let i2 = 0; i2 < positions.length; i2++) {
|
|
34258
34317
|
const time = positions[i2];
|
|
34259
34318
|
await page.evaluate((t3) => {
|
|
@@ -34276,6 +34335,59 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
34276
34335
|
() => new Promise((r2) => requestAnimationFrame(() => requestAnimationFrame(() => r2())))
|
|
34277
34336
|
);
|
|
34278
34337
|
await new Promise((r2) => setTimeout(r2, 200));
|
|
34338
|
+
if (injectVideoFramesBatch2 && syncVideoFrameVisibility2) {
|
|
34339
|
+
const active = await page.evaluate((t3) => {
|
|
34340
|
+
return Array.from(document.querySelectorAll("video[data-start]")).map((el) => {
|
|
34341
|
+
const v = el;
|
|
34342
|
+
const start = parseFloat(v.dataset.start ?? "0") || 0;
|
|
34343
|
+
const rawRate = v.defaultPlaybackRate;
|
|
34344
|
+
const playbackRate = Number.isFinite(rawRate) && rawRate > 0 ? Math.max(0.1, Math.min(5, rawRate)) : 1;
|
|
34345
|
+
const mediaStart = parseFloat(v.dataset.playbackStart ?? v.dataset.mediaStart ?? "0") || 0;
|
|
34346
|
+
const rawDuration = parseFloat(v.dataset.duration ?? "");
|
|
34347
|
+
const srcDur = Number.isFinite(v.duration) && v.duration > 0 ? v.duration : 0;
|
|
34348
|
+
const duration2 = Number.isFinite(rawDuration) && rawDuration > 0 ? rawDuration : srcDur > 0 ? Math.max(0, (srcDur - mediaStart) / playbackRate) : Number.POSITIVE_INFINITY;
|
|
34349
|
+
const relTime = (t3 - start) * playbackRate + mediaStart;
|
|
34350
|
+
const activeNow = t3 >= start && t3 < start + duration2 && relTime >= 0 && !!v.id;
|
|
34351
|
+
return {
|
|
34352
|
+
id: v.id,
|
|
34353
|
+
src: v.currentSrc || v.src,
|
|
34354
|
+
relTime,
|
|
34355
|
+
active: activeNow
|
|
34356
|
+
};
|
|
34357
|
+
}).filter((entry) => entry.active && entry.src);
|
|
34358
|
+
}, time);
|
|
34359
|
+
const updates = [];
|
|
34360
|
+
for (const v of active) {
|
|
34361
|
+
let filePath = null;
|
|
34362
|
+
try {
|
|
34363
|
+
const url = new URL(v.src);
|
|
34364
|
+
const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
|
|
34365
|
+
const candidate = resolve32(projectDir, decodedPath);
|
|
34366
|
+
const rel = relative4(projectDir, candidate);
|
|
34367
|
+
if (!rel.startsWith("..") && !isAbsolute4(rel) && existsSync45(candidate)) {
|
|
34368
|
+
filePath = candidate;
|
|
34369
|
+
}
|
|
34370
|
+
} catch {
|
|
34371
|
+
}
|
|
34372
|
+
if (!filePath) continue;
|
|
34373
|
+
const png = await extractVideoFrameToBuffer(filePath, Math.max(0, v.relTime));
|
|
34374
|
+
if (!png) continue;
|
|
34375
|
+
updates.push({
|
|
34376
|
+
videoId: v.id,
|
|
34377
|
+
dataUri: `data:image/png;base64,${png.toString("base64")}`
|
|
34378
|
+
});
|
|
34379
|
+
}
|
|
34380
|
+
try {
|
|
34381
|
+
if (updates.length > 0) {
|
|
34382
|
+
await injectVideoFramesBatch2(page, updates);
|
|
34383
|
+
}
|
|
34384
|
+
await syncVideoFrameVisibility2(
|
|
34385
|
+
page,
|
|
34386
|
+
active.map((a) => a.id)
|
|
34387
|
+
);
|
|
34388
|
+
} catch {
|
|
34389
|
+
}
|
|
34390
|
+
}
|
|
34279
34391
|
const timeLabel = opts.at?.length ? `${time.toFixed(1)}s` : `${Math.round(time / duration * 100)}pct`;
|
|
34280
34392
|
const filename = `frame-${String(i2).padStart(2, "0")}-at-${timeLabel}.png`;
|
|
34281
34393
|
const framePath = join45(snapshotDir, filename);
|
|
@@ -34290,7 +34402,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
34290
34402
|
}
|
|
34291
34403
|
return savedPaths;
|
|
34292
34404
|
}
|
|
34293
|
-
var __filename2, __dirname3, examples18, snapshot_default;
|
|
34405
|
+
var __filename2, __dirname3, FFMPEG_EXTRACT_TIMEOUT_MS, examples18, snapshot_default;
|
|
34294
34406
|
var init_snapshot = __esm({
|
|
34295
34407
|
"src/commands/snapshot.ts"() {
|
|
34296
34408
|
"use strict";
|
|
@@ -34299,6 +34411,7 @@ var init_snapshot = __esm({
|
|
|
34299
34411
|
init_colors();
|
|
34300
34412
|
__filename2 = fileURLToPath8(import.meta.url);
|
|
34301
34413
|
__dirname3 = dirname20(__filename2);
|
|
34414
|
+
FFMPEG_EXTRACT_TIMEOUT_MS = 3e4;
|
|
34302
34415
|
examples18 = [
|
|
34303
34416
|
["Capture 5 key frames from a composition", "snapshot captures/stripe"],
|
|
34304
34417
|
["Capture 10 evenly-spaced frames", "snapshot captures/stripe --frames 10"]
|