@t3lnet/sceneforge 1.0.29 → 1.0.31
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.
|
@@ -182,8 +182,6 @@ export async function runRecordDemoCommand(argv) {
|
|
|
182
182
|
const hqVideo = hasFlag(args, "--hq-video");
|
|
183
183
|
const hqFormat = getFlagValue(args, "--hq-format") ?? "jpeg";
|
|
184
184
|
const hqQuality = parseInt(getFlagValue(args, "--hq-quality") ?? "100", 10);
|
|
185
|
-
const hqFpsArg = getFlagValue(args, "--hq-fps");
|
|
186
|
-
const hqFps = hqFpsArg ? parseInt(hqFpsArg, 10) : undefined; // undefined = use actual capture rate
|
|
187
185
|
|
|
188
186
|
if (!baseUrl) {
|
|
189
187
|
console.error("[error] --base-url is required");
|
|
@@ -308,7 +306,7 @@ export async function runRecordDemoCommand(argv) {
|
|
|
308
306
|
const finalVideoPath = path.join(outputPaths.videosDir, `${definition.name}.webm`);
|
|
309
307
|
try {
|
|
310
308
|
if (!demoError && result?.success) {
|
|
311
|
-
await cdpRecorder.assembleVideo(finalVideoPath
|
|
309
|
+
await cdpRecorder.assembleVideo(finalVideoPath);
|
|
312
310
|
console.log(`[record] High-quality video saved: ${finalVideoPath}`);
|
|
313
311
|
if (result.scriptPath) {
|
|
314
312
|
// Use the actual first frame time for alignment, not when we started the recorder
|
|
@@ -209,12 +209,9 @@ export function createCDPRecorder(page, options) {
|
|
|
209
209
|
* Uses timestamp-aware assembly to preserve real-time playback timing
|
|
210
210
|
*
|
|
211
211
|
* @param {string} outputPath - Output video path
|
|
212
|
-
* @param {Object} [assembleOptions] - Assembly options
|
|
213
|
-
* @param {number} [assembleOptions.fps] - Output framerate for encoding (default: 30)
|
|
214
212
|
* @returns {Promise<string>} - Path to assembled video
|
|
215
213
|
*/
|
|
216
|
-
async assembleVideo(outputPath
|
|
217
|
-
const { fps: outputFps = 30 } = assembleOptions;
|
|
214
|
+
async assembleVideo(outputPath) {
|
|
218
215
|
|
|
219
216
|
if (frameTimestamps.length === 0) {
|
|
220
217
|
throw new Error("No frames captured - cannot assemble video");
|
|
@@ -234,8 +231,8 @@ export function createCDPRecorder(page, options) {
|
|
|
234
231
|
// Last frame - use average duration or minimum display time
|
|
235
232
|
const avgDuration = sortedFrames.length > 1
|
|
236
233
|
? (sortedFrames[sortedFrames.length - 1].timestamp - sortedFrames[0].timestamp) / (sortedFrames.length - 1)
|
|
237
|
-
: 1 /
|
|
238
|
-
duration = Math.max(avgDuration, 1 /
|
|
234
|
+
: 1 / 30;
|
|
235
|
+
duration = Math.max(avgDuration, 1 / 30);
|
|
239
236
|
}
|
|
240
237
|
// Clamp duration to reasonable bounds (min 1ms, max 10 seconds per frame)
|
|
241
238
|
duration = Math.max(0.001, Math.min(duration, 10));
|
|
@@ -279,6 +276,8 @@ export function createCDPRecorder(page, options) {
|
|
|
279
276
|
}
|
|
280
277
|
|
|
281
278
|
// Use concat demuxer for timestamp-aware assembly
|
|
279
|
+
// Output at 30fps CFR - FFmpeg will duplicate frames as needed to fill time
|
|
280
|
+
// This creates a seekable video while preserving the correct timing from the concat durations
|
|
282
281
|
await runFFmpeg([
|
|
283
282
|
"-y",
|
|
284
283
|
"-f", "concat",
|
|
@@ -286,8 +285,8 @@ export function createCDPRecorder(page, options) {
|
|
|
286
285
|
"-i", concatFilePath,
|
|
287
286
|
...encodingArgs,
|
|
288
287
|
"-pix_fmt", "yuv420p",
|
|
289
|
-
"-r",
|
|
290
|
-
"-
|
|
288
|
+
"-r", "30", // Output at constant 30fps for seekability
|
|
289
|
+
"-fps_mode", "cfr", // Constant framerate output
|
|
291
290
|
outputPath,
|
|
292
291
|
]);
|
|
293
292
|
|
|
@@ -317,9 +316,7 @@ export function getCDPRecordingHelpText() {
|
|
|
317
316
|
return `
|
|
318
317
|
High-Quality Recording Options:
|
|
319
318
|
--hq-video Use CDP-based high-quality recording instead of Playwright
|
|
320
|
-
Captures frames
|
|
319
|
+
Captures frames with timestamps and assembles with real-time timing
|
|
321
320
|
--hq-format <format> Frame format: jpeg (default) or png (lossless, larger files)
|
|
322
|
-
--hq-quality <1-100> JPEG quality (default: 100, ignored for PNG)
|
|
323
|
-
--hq-fps <fps> Output framerate (default: actual capture rate for real-time)
|
|
324
|
-
Override only if you want to change playback speed`;
|
|
321
|
+
--hq-quality <1-100> JPEG quality (default: 100, ignored for PNG)`;
|
|
325
322
|
}
|
|
@@ -466,7 +466,6 @@ The CDP-based recorder captures frames directly from Chrome DevTools Protocol an
|
|
|
466
466
|
--hq-video # Enable CDP-based high-quality recording
|
|
467
467
|
--hq-format <format> # Frame format: jpeg (default) or png
|
|
468
468
|
--hq-quality <1-100> # JPEG quality (default: 100, ignored for PNG)
|
|
469
|
-
--hq-fps <fps> # Override output framerate (default: actual capture rate for real-time)
|
|
470
469
|
```
|
|
471
470
|
|
|
472
471
|
### Frame Formats
|
|
@@ -478,9 +477,9 @@ The CDP-based recorder captures frames directly from Chrome DevTools Protocol an
|
|
|
478
477
|
|
|
479
478
|
### How It Works
|
|
480
479
|
|
|
481
|
-
1. **Frame Capture**: Uses Chrome's `Page.startScreencast` CDP method
|
|
480
|
+
1. **Frame Capture**: Uses Chrome's `Page.startScreencast` CDP method with timestamps
|
|
482
481
|
2. **Frame Storage**: Saves frames as JPEG (quality 100) or lossless PNG
|
|
483
|
-
3. **
|
|
482
|
+
3. **Timestamp-Aware Assembly**: FFmpeg assembles frames using per-frame durations to preserve real-time playback (waits stay as waits, actions stay as actions)
|
|
484
483
|
4. **Final Output**: Quality settings applied at concat step
|
|
485
484
|
|
|
486
485
|
### Examples
|
|
@@ -466,7 +466,6 @@ The CDP-based recorder captures frames directly from Chrome DevTools Protocol an
|
|
|
466
466
|
--hq-video # Enable CDP-based high-quality recording
|
|
467
467
|
--hq-format <format> # Frame format: jpeg (default) or png
|
|
468
468
|
--hq-quality <1-100> # JPEG quality (default: 100, ignored for PNG)
|
|
469
|
-
--hq-fps <fps> # Override output framerate (default: actual capture rate for real-time)
|
|
470
469
|
```
|
|
471
470
|
|
|
472
471
|
### Frame Formats
|
|
@@ -478,9 +477,9 @@ The CDP-based recorder captures frames directly from Chrome DevTools Protocol an
|
|
|
478
477
|
|
|
479
478
|
### How It Works
|
|
480
479
|
|
|
481
|
-
1. **Frame Capture**: Uses Chrome's `Page.startScreencast` CDP method
|
|
480
|
+
1. **Frame Capture**: Uses Chrome's `Page.startScreencast` CDP method with timestamps
|
|
482
481
|
2. **Frame Storage**: Saves frames as JPEG (quality 100) or lossless PNG
|
|
483
|
-
3. **
|
|
482
|
+
3. **Timestamp-Aware Assembly**: FFmpeg assembles frames using per-frame durations to preserve real-time playback (waits stay as waits, actions stay as actions)
|
|
484
483
|
4. **Final Output**: Quality settings applied at concat step
|
|
485
484
|
|
|
486
485
|
### Examples
|