@reshotdev/screenshot 0.0.1-beta.2 ā 0.0.1-beta.4
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/package.json +1 -1
- package/src/lib/capture-script-runner.js +27 -37
package/package.json
CHANGED
|
@@ -1931,12 +1931,17 @@ async function runScenarioWithVideoCapture(scenario, options = {}) {
|
|
|
1931
1931
|
|
|
1932
1932
|
await fs.writeFile(sentinelPath, buffer);
|
|
1933
1933
|
sentinelPaths.push({ index: sentinelIndex, label, path: sentinelPath });
|
|
1934
|
+
if (firstSentinelTimestamp === null) {
|
|
1935
|
+
firstSentinelTimestamp = (Date.now() - startTime) / 1000;
|
|
1936
|
+
debug(`First sentinel captured at ${firstSentinelTimestamp.toFixed(2)}s`);
|
|
1937
|
+
}
|
|
1934
1938
|
sentinelIndex++;
|
|
1935
1939
|
return sentinelPath;
|
|
1936
1940
|
}
|
|
1937
1941
|
|
|
1938
1942
|
// Capture initial state BEFORE first navigation (placeholder - actual capture after goto)
|
|
1939
1943
|
let hasNavigated = false;
|
|
1944
|
+
let firstSentinelTimestamp = null;
|
|
1940
1945
|
|
|
1941
1946
|
// Execute all steps and capture timeline
|
|
1942
1947
|
for (let stepIndex = 0; stepIndex < script.length; stepIndex++) {
|
|
@@ -2292,20 +2297,32 @@ async function runScenarioWithVideoCapture(scenario, options = {}) {
|
|
|
2292
2297
|
)
|
|
2293
2298
|
);
|
|
2294
2299
|
|
|
2295
|
-
// Convert to MP4 with ffmpeg, trimming
|
|
2296
|
-
//
|
|
2297
|
-
const
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2300
|
+
// Convert to MP4 with ffmpeg, trimming blank loading frames from start
|
|
2301
|
+
// and excess frames from end
|
|
2302
|
+
const startOffset = Math.max(0, (firstSentinelTimestamp || 0) - 0.3);
|
|
2303
|
+
const endTimestamp = finalTimestamp + 0.5;
|
|
2304
|
+
const contentDuration = endTimestamp - startOffset;
|
|
2305
|
+
if (startOffset > 0) {
|
|
2306
|
+
console.log(
|
|
2307
|
+
chalk.cyan(
|
|
2308
|
+
` š¹ Converting to MP4 (${startOffset.toFixed(1)}sā${endTimestamp.toFixed(1)}s, ${contentDuration.toFixed(1)}s content)...`
|
|
2309
|
+
)
|
|
2310
|
+
);
|
|
2311
|
+
} else {
|
|
2312
|
+
console.log(
|
|
2313
|
+
chalk.cyan(
|
|
2314
|
+
` š¹ Converting to MP4 (trimmed to ${contentDuration.toFixed(1)}s)...`
|
|
2315
|
+
)
|
|
2316
|
+
);
|
|
2317
|
+
}
|
|
2318
|
+
debug(`Running ffmpeg: start=${startOffset}s, duration=${contentDuration}s`);
|
|
2304
2319
|
await runFFmpegConvert([
|
|
2320
|
+
"-ss",
|
|
2321
|
+
startOffset.toFixed(2),
|
|
2305
2322
|
"-i",
|
|
2306
2323
|
recordedVideoPath,
|
|
2307
2324
|
"-t",
|
|
2308
|
-
|
|
2325
|
+
contentDuration.toFixed(2),
|
|
2309
2326
|
"-c:v",
|
|
2310
2327
|
"libx264",
|
|
2311
2328
|
"-preset",
|
|
@@ -2330,33 +2347,6 @@ async function runScenarioWithVideoCapture(scenario, options = {}) {
|
|
|
2330
2347
|
)
|
|
2331
2348
|
);
|
|
2332
2349
|
|
|
2333
|
-
// Extract poster frame from the video (first frame at 0.5s for non-blank content)
|
|
2334
|
-
const posterPath = finalVideoPath.replace(/\.mp4$/, "-poster.png");
|
|
2335
|
-
try {
|
|
2336
|
-
await runFFmpegConvert([
|
|
2337
|
-
"-i",
|
|
2338
|
-
finalVideoPath,
|
|
2339
|
-
"-ss",
|
|
2340
|
-
"0.5",
|
|
2341
|
-
"-frames:v",
|
|
2342
|
-
"1",
|
|
2343
|
-
"-q:v",
|
|
2344
|
-
"2",
|
|
2345
|
-
"-y",
|
|
2346
|
-
posterPath,
|
|
2347
|
-
]);
|
|
2348
|
-
if (fs.existsSync(posterPath)) {
|
|
2349
|
-
const posterSize = fs.statSync(posterPath).size;
|
|
2350
|
-
console.log(
|
|
2351
|
-
chalk.green(
|
|
2352
|
-
` ā Poster frame: ${posterPath} (${(posterSize / 1024).toFixed(1)} KB)`
|
|
2353
|
-
)
|
|
2354
|
-
);
|
|
2355
|
-
}
|
|
2356
|
-
} catch (e) {
|
|
2357
|
-
debug(`Poster frame extraction failed: ${e.message}`);
|
|
2358
|
-
}
|
|
2359
|
-
|
|
2360
2350
|
// Save timeline for reference
|
|
2361
2351
|
const timelinePath = path.join(
|
|
2362
2352
|
outputDir || path.join(".reshot/output", scenario.key, "default"),
|