@t3lnet/sceneforge 1.0.29 → 1.0.30

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, hqFps ? { fps: hqFps } : {});
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, assembleOptions = {}) {
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 / outputFps;
238
- duration = Math.max(avgDuration, 1 / outputFps);
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));
@@ -286,8 +283,7 @@ export function createCDPRecorder(page, options) {
286
283
  "-i", concatFilePath,
287
284
  ...encodingArgs,
288
285
  "-pix_fmt", "yuv420p",
289
- "-r", String(outputFps), // Output framerate (for smooth playback)
290
- "-vsync", "vfr", // Variable framerate to preserve timing
286
+ "-fps_mode", "vfr", // Variable framerate to preserve timing
291
287
  outputPath,
292
288
  ]);
293
289
 
@@ -317,9 +313,7 @@ export function getCDPRecordingHelpText() {
317
313
  return `
318
314
  High-Quality Recording Options:
319
315
  --hq-video Use CDP-based high-quality recording instead of Playwright
320
- Captures frames at maximum quality and assembles with FFmpeg
316
+ Captures frames with timestamps and assembles with real-time timing
321
317
  --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`;
318
+ --hq-quality <1-100> JPEG quality (default: 100, ignored for PNG)`;
325
319
  }
@@ -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. **Video Assembly**: FFmpeg assembles frames with lossless intermediate encoding
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. **Video Assembly**: FFmpeg assembles frames with lossless intermediate encoding
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t3lnet/sceneforge",
3
- "version": "1.0.29",
3
+ "version": "1.0.30",
4
4
  "description": "SceneForge runner and generation utilities for YAML-driven demos",
5
5
  "license": "MIT",
6
6
  "author": "T3LNET",