refactor: simplify review fixes for WebM PR

- Use static import for copyFileSync (was unnecessary dynamic import)
- Shallow-copy config before mutating forceScreenshot (prevents
  caller-provided config from being permanently modified)
- Consolidate isWebm/isWebmRender/outputFormat into single early
  declaration in renderOrchestrator
- Fix debug output extension for WebM (was hardcoded .mp4)
- Log unexpected audio extraction errors instead of silently swallowing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
James
2026-03-27 03:40:35 +00:00
co-authored by Claude Opus 4.6
parent 684b103ba4
commit 83d11ac595
3 changed files with 16 additions and 15 deletions
+1 -3
View File
@@ -6,7 +6,7 @@
*/ */
import { spawn } from "child_process"; import { spawn } from "child_process";
import { existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from "fs"; import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from "fs";
import { join, dirname } from "path"; import { join, dirname } from "path";
import { DEFAULT_CONFIG, type EngineConfig } from "../config.js"; import { DEFAULT_CONFIG, type EngineConfig } from "../config.js";
import { type GpuEncoder, getCachedGpuEncoder, getGpuEncoderName } from "../utils/gpuEncoder.js"; import { type GpuEncoder, getCachedGpuEncoder, getGpuEncoderName } from "../utils/gpuEncoder.js";
@@ -414,8 +414,6 @@ export async function applyFaststart(
): Promise<MuxResult> { ): Promise<MuxResult> {
// faststart is MP4-only (moves moov atom to file start for streaming) // faststart is MP4-only (moves moov atom to file start for streaming)
if (outputPath.endsWith(".webm")) { if (outputPath.endsWith(".webm")) {
// For WebM, just copy the file as-is
const { copyFileSync } = await import("fs");
if (inputPath !== outputPath) copyFileSync(inputPath, outputPath); if (inputPath !== outputPath) copyFileSync(inputPath, outputPath);
return { success: true, outputPath, durationMs: 0 }; return { success: true, outputPath, durationMs: 0 };
} }
+6 -2
View File
@@ -333,8 +333,12 @@ function extractMonoPcm16(videoPath: string): Int16Array {
return new Int16Array(0); return new Int16Array(0);
} }
return new Int16Array(stdout.buffer, stdout.byteOffset, Math.floor(stdout.byteLength / 2)); return new Int16Array(stdout.buffer, stdout.byteOffset, Math.floor(stdout.byteLength / 2));
} catch { } catch (err) {
// No audio stream in the video (e.g., WebM without audio) // No audio stream (e.g., WebM without audio) — log but don't fail
const msg = err instanceof Error ? err.message : String(err);
if (!msg.includes("does not contain any stream")) {
logPretty(`Audio extraction warning: ${msg.slice(0, 200)}`, "⚠️");
}
return new Int16Array(0); return new Int16Array(0);
} }
} }
@@ -300,9 +300,11 @@ export async function executeRenderJob(
let restoreLogger: (() => void) | null = null; let restoreLogger: (() => void) | null = null;
const perfStages: Record<string, number> = {}; const perfStages: Record<string, number> = {};
const perfOutputPath = join(workDir, "perf-summary.json"); const perfOutputPath = join(workDir, "perf-summary.json");
const cfg = job.config.producerConfig ?? resolveConfig(); const cfg = { ...(job.config.producerConfig ?? resolveConfig()) };
const outputFormat = (job.config.format ?? "mp4") as "mp4" | "webm";
const isWebm = outputFormat === "webm";
// WebM/transparency requires screenshot mode — beginFrame doesn't support alpha channel // WebM/transparency requires screenshot mode — beginFrame doesn't support alpha channel
if (job.config.format === "webm") { if (isWebm) {
cfg.forceScreenshot = true; cfg.forceScreenshot = true;
} }
const enableChunkedEncode = cfg.enableChunkedEncode; const enableChunkedEncode = cfg.enableChunkedEncode;
@@ -363,7 +365,6 @@ export async function executeRenderJob(
}); });
assertNotAborted(); assertNotAborted();
const isWebm = job.config.format === "webm";
const captureOpts: CaptureOptions = { const captureOpts: CaptureOptions = {
width, width,
height, height,
@@ -600,19 +601,17 @@ export async function executeRenderJob(
const framesDir = join(workDir, "captured-frames"); const framesDir = join(workDir, "captured-frames");
if (!existsSync(framesDir)) mkdirSync(framesDir, { recursive: true }); if (!existsSync(framesDir)) mkdirSync(framesDir, { recursive: true });
const outputFormat = job.config.format ?? "mp4";
const isWebmRender = outputFormat === "webm";
const captureOptions: CaptureOptions = { const captureOptions: CaptureOptions = {
width, width,
height, height,
fps: job.config.fps, fps: job.config.fps,
format: isWebmRender ? "png" : "jpeg", format: isWebm ? "png" : "jpeg",
quality: isWebmRender ? undefined : job.config.quality === "draft" ? 80 : 95, quality: isWebm ? undefined : job.config.quality === "draft" ? 80 : 95,
}; };
const workerCount = calculateOptimalWorkers(job.totalFrames!, job.config.workers, cfg); const workerCount = calculateOptimalWorkers(job.totalFrames!, job.config.workers, cfg);
const videoExt = isWebmRender ? ".webm" : ".mp4"; const videoExt = isWebm ? ".webm" : ".mp4";
const videoOnlyPath = join(workDir, `video-only${videoExt}`); const videoOnlyPath = join(workDir, `video-only${videoExt}`);
const preset = getEncoderPreset(job.config.quality, outputFormat); const preset = getEncoderPreset(job.config.quality, outputFormat);
@@ -846,7 +845,7 @@ export async function executeRenderJob(
const stage5Start = Date.now(); const stage5Start = Date.now();
updateJobStatus(job, "encoding", "Encoding video", 75, onProgress); updateJobStatus(job, "encoding", "Encoding video", 75, onProgress);
const frameExt = isWebmRender ? "png" : "jpg"; const frameExt = isWebm ? "png" : "jpg";
const framePattern = `frame_%06d.${frameExt}`; const framePattern = `frame_%06d.${frameExt}`;
const encoderOpts = { const encoderOpts = {
fps: job.config.fps, fps: job.config.fps,
@@ -962,7 +961,7 @@ export async function executeRenderJob(
if (job.config.debug) { if (job.config.debug) {
// Copy output MP4 into debug dir for easy access // Copy output MP4 into debug dir for easy access
if (existsSync(outputPath)) { if (existsSync(outputPath)) {
const debugOutput = join(workDir, "output.mp4"); const debugOutput = join(workDir, isWebm ? "output.webm" : "output.mp4");
copyFileSync(outputPath, debugOutput); copyFileSync(outputPath, debugOutput);
} }
} else { } else {