Files
Recordly/electron/ipc/ffmpeg/binary.ts
T
webadderall 099ce2bbb5 refactor: split handlers.ts into focused sub-modules
handlers.ts was ~5967 lines. Extracted into 22 focused modules:

- ipc/types.ts — shared TypeScript interfaces and types
- ipc/constants.ts — module-level constants
- ipc/state.ts — all mutable state with typed setters
- ipc/utils.ts — shared low-level utilities (getScreen, normalizePath, etc.)
- ipc/ffmpeg/binary.ts — ffmpeg binary resolution
- ipc/ffmpeg/filters.ts — audio sync/filter builders
- ipc/captions/parser.ts — SRT/Whisper JSON parsers
- ipc/captions/whisper.ts — Whisper model download/status
- ipc/captions/generate.ts — auto-caption generation
- ipc/paths/binaries.ts — native binary path resolution
- ipc/cursor/monitor.ts — cursor monitor process management
- ipc/cursor/telemetry.ts — cursor sampling and telemetry
- ipc/cursor/bounds.ts — window bounds capture and resolution
- ipc/cursor/interaction.ts — mouse hook and interaction capture
- ipc/recording/events.ts — recording lifecycle events
- ipc/recording/diagnostics.ts — media validation and diagnostics
- ipc/recording/prune.ts — auto-recording cleanup
- ipc/recording/ffmpeg.ts — FFmpeg screen capture
- ipc/recording/windows.ts — Windows native capture (WGC)
- ipc/recording/mac.ts — Mac ScreenCaptureKit integration
- ipc/export/native-video.ts — native video export sessions
- ipc/project/session.ts — recording session manifests
- ipc/project/manager.ts — project library and file management

handlers.ts reduced from 5967 → 2930 lines (registerIpcHandlers + helpers only)
2026-04-17 19:57:26 +10:00

77 lines
1.8 KiB
TypeScript

import { spawnSync } from "node:child_process";
import { existsSync } from "node:fs";
import { createRequire } from "node:module";
import { app } from "electron";
const nodeRequire = createRequire(import.meta.url);
export function loadFfmpegStatic(): string | null {
const moduleExports = nodeRequire("ffmpeg-static");
if (typeof moduleExports === "string") {
return moduleExports;
}
if (typeof moduleExports?.default === "string") {
return moduleExports.default as string;
}
return null;
}
export function resolveSystemFfmpegBinaryPath(): string | null {
const locator = process.platform === "win32" ? "where" : "which";
const result = spawnSync(locator, ["ffmpeg"], {
encoding: "utf-8",
windowsHide: true,
});
if (result.status === 0) {
const candidate = result.stdout
.split(/\r?\n/)
.map((line: string) => line.trim())
.find((line: string) => line.length > 0);
if (candidate) {
return candidate;
}
}
// Fallback: check common install paths directly (Electron's shell may lack full PATH)
if (process.platform !== "win32") {
const commonPaths = [
"/opt/homebrew/bin/ffmpeg",
"/usr/local/bin/ffmpeg",
"/usr/bin/ffmpeg",
];
for (const p of commonPaths) {
if (existsSync(p)) {
return p;
}
}
}
return null;
}
export function getFfmpegBinaryPath(): string {
const ffmpegStatic = loadFfmpegStatic();
if (ffmpegStatic && typeof ffmpegStatic === "string") {
const bundledPath = app.isPackaged
? ffmpegStatic.replace(/\.asar([/\\])/, ".asar.unpacked$1")
: ffmpegStatic;
if (existsSync(bundledPath)) {
return bundledPath;
}
}
const systemFfmpeg = resolveSystemFfmpegBinaryPath();
if (systemFfmpeg) {
return systemFfmpeg;
}
throw new Error(
"FFmpeg binary is unavailable. Install ffmpeg-static for this platform or make ffmpeg available on PATH.",
);
}