feat(core): add module scaffolding and provider registries

This commit is contained in:
kyasuda
2026-02-10 13:16:01 -08:00
committed by sudacode
parent 531f8027bd
commit 09e142279a
19 changed files with 822 additions and 0 deletions

95
src/subsync/engines.ts Normal file
View File

@@ -0,0 +1,95 @@
export type SubsyncEngine = "alass" | "ffsubsync";
export interface SubsyncCommandResult {
ok: boolean;
code: number | null;
stderr: string;
stdout: string;
error?: string;
}
export interface SubsyncEngineExecutionContext {
referenceFilePath: string;
videoPath: string;
inputSubtitlePath: string;
outputPath: string;
audioStreamIndex: number | null;
resolveExecutablePath: (
configuredPath: string,
commandName: string,
) => string;
resolvedPaths: {
alassPath: string;
ffsubsyncPath: string;
};
runCommand: (command: string, args: string[]) => Promise<SubsyncCommandResult>;
}
export interface SubsyncEngineProvider {
engine: SubsyncEngine;
execute: (
context: SubsyncEngineExecutionContext,
) => Promise<SubsyncCommandResult>;
}
type SubsyncEngineProviderFactory = () => SubsyncEngineProvider;
const subsyncEngineProviderFactories = new Map<SubsyncEngine, SubsyncEngineProviderFactory>();
export function registerSubsyncEngineProvider(
engine: SubsyncEngine,
factory: SubsyncEngineProviderFactory,
): void {
if (subsyncEngineProviderFactories.has(engine)) {
return;
}
subsyncEngineProviderFactories.set(engine, factory);
}
export function createSubsyncEngineProvider(
engine: SubsyncEngine,
): SubsyncEngineProvider | null {
const factory = subsyncEngineProviderFactories.get(engine);
if (!factory) return null;
return factory();
}
function registerDefaultSubsyncEngineProviders(): void {
registerSubsyncEngineProvider("alass", () => ({
engine: "alass",
execute: async (context: SubsyncEngineExecutionContext) => {
const alassPath = context.resolveExecutablePath(
context.resolvedPaths.alassPath,
"alass",
);
return context.runCommand(alassPath, [
context.referenceFilePath,
context.inputSubtitlePath,
context.outputPath,
]);
},
}));
registerSubsyncEngineProvider("ffsubsync", () => ({
engine: "ffsubsync",
execute: async (context: SubsyncEngineExecutionContext) => {
const ffsubsyncPath = context.resolveExecutablePath(
context.resolvedPaths.ffsubsyncPath,
"ffsubsync",
);
const args = [
context.videoPath,
"-i",
context.inputSubtitlePath,
"-o",
context.outputPath,
];
if (context.audioStreamIndex !== null) {
args.push("--reference-stream", `0:${context.audioStreamIndex}`);
}
return context.runCommand(ffsubsyncPath, args);
},
}));
}
registerDefaultSubsyncEngineProviders();