( framesDir: string, framePattern: string, outputPath: string, options: EncoderOptions, signal?: AbortSignal, config?: Partial<Pick<EngineConfig, "ffmpegEncodeTimeout">>, )
| 432 | } |
| 433 | |
| 434 | export async function encodeFramesFromDir( |
| 435 | framesDir: string, |
| 436 | framePattern: string, |
| 437 | outputPath: string, |
| 438 | options: EncoderOptions, |
| 439 | signal?: AbortSignal, |
| 440 | config?: Partial<Pick<EngineConfig, "ffmpegEncodeTimeout">>, |
| 441 | ): Promise<EncodeResult> { |
| 442 | const startTime = Date.now(); |
| 443 | |
| 444 | const outputDir = dirname(outputPath); |
| 445 | if (!existsSync(outputDir)) mkdirSync(outputDir, { recursive: true }); |
| 446 | |
| 447 | const files = readdirSync(framesDir).filter((f) => f.match(/\.(jpg|jpeg|png)$/i)); |
| 448 | const frameCount = files.length; |
| 449 | |
| 450 | if (frameCount === 0) { |
| 451 | return { |
| 452 | success: false, |
| 453 | outputPath, |
| 454 | durationMs: Date.now() - startTime, |
| 455 | framesEncoded: 0, |
| 456 | fileSize: 0, |
| 457 | error: "[FFmpeg] No frame files found in directory", |
| 458 | }; |
| 459 | } |
| 460 | |
| 461 | let gpuEncoder: GpuEncoder = null; |
| 462 | if (options.useGpu) { |
| 463 | gpuEncoder = await getCachedGpuEncoder(); |
| 464 | } |
| 465 | |
| 466 | const inputPath = join(framesDir, framePattern); |
| 467 | const inputArgs = ["-framerate", fpsToFfmpegArg(options.fps), "-i", inputPath]; |
| 468 | const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder); |
| 469 | |
| 470 | return new Promise((resolve) => { |
| 471 | const ffmpeg = spawn(getFfmpegBinary(), args); |
| 472 | trackChildProcess(ffmpeg); |
| 473 | let stderr = ""; |
| 474 | const onAbort = () => { |
| 475 | ffmpeg.kill("SIGTERM"); |
| 476 | }; |
| 477 | if (signal) { |
| 478 | if (signal.aborted) { |
| 479 | ffmpeg.kill("SIGTERM"); |
| 480 | } else { |
| 481 | signal.addEventListener("abort", onAbort, { once: true }); |
| 482 | } |
| 483 | } |
| 484 | |
| 485 | const encodeTimeout = config?.ffmpegEncodeTimeout ?? DEFAULT_CONFIG.ffmpegEncodeTimeout; |
| 486 | let timedOut = false; |
| 487 | const timer = setTimeout(() => { |
| 488 | timedOut = true; |
| 489 | ffmpeg.kill("SIGTERM"); |
| 490 | }, encodeTimeout); |
| 491 |
no test coverage detected