Add desktop/server MP4 export pipeline, hardening, and render tests (v1.3.0)
Desktop MP4 export renders frames from a hidden BrowserWindow via capturePage, pipes PNGs to a bundled ffmpeg (libx264/yuv420p/+faststart), and writes the file through an atomic temp-file swap. It shares scene validation (shared/renderValidation.cjs) and the render.html renderer with the standalone Puppeteer server, which is hardened in parallel. Render worker & main (electron/): - abortable render loop with an inactivity watchdog and cancel plumbing - atomic temp-file + rename so a cancel/failure never truncates a pre-existing target (#7); stdin EPIPE / early-exit / backpressure-hang handled (#8) - HiDPI frames normalized to canvas size (#10); odd dimensions padded to even (#13, also server); backgroundThrottling disabled (#12) - reject canvases larger than the display (#11); single-render guard; isolated render session that blocks network requests (#5) Tests: - Electron harnesses (scripts/verify-*.cjs) for capture, export, cancel, timeout, assets, background, capture-fidelity, resolution, odd-dims, aggregated by verify-desktop-render.cjs - server smoke + e2e and shared validation unit tests - headless hook (src/devtools/headless.ts) to run the in-app suite under browser/electron hosts; pixel-diff util + capture fixtures (test/) - dev_docs plans: integration, fixes (#7-#13), and the e2e/capture strategy Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
46f9f32aef
commit
518d43855b
41 files changed
+3907
-86
No files matched your search
@@ -0,0 +1,30 @@
|
||||
import { app } from 'electron'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
export function resolveFfmpegPath(): string {
|
||||
const envPath = process.env.FFMPEG_PATH?.trim()
|
||||
if (envPath) return envPath
|
||||
|
||||
const exe = process.platform === 'win32' ? 'ffmpeg.exe' : 'ffmpeg'
|
||||
const bundledPath = path.join(process.resourcesPath, 'bin', process.platform, exe)
|
||||
if (isUsableBinary(bundledPath)) return bundledPath
|
||||
|
||||
return 'ffmpeg'
|
||||
}
|
||||
|
||||
export function missingFfmpegMessage(): string {
|
||||
if (app.isPackaged) {
|
||||
return 'ffmpeg is not bundled with this RUWIO build, or it cannot be executed. Install ffmpeg or set FFMPEG_PATH to export MP4.'
|
||||
}
|
||||
return 'ffmpeg was not found. Install ffmpeg or set FFMPEG_PATH to export MP4.'
|
||||
}
|
||||
|
||||
function isUsableBinary(file: string): boolean {
|
||||
try {
|
||||
fs.accessSync(file, process.platform === 'win32' ? fs.constants.F_OK : fs.constants.X_OK)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user