OpenCut/apps/web/src/core/index.ts

104 lines
3.0 KiB
TypeScript

import { PlaybackManager } from "./managers/playback-manager";
import { TimelineManager } from "./managers/timeline-manager";
import { SceneManager } from "./managers/scene-manager";
import { ProjectManager } from "./managers/project-manager";
import { MediaManager } from "./managers/media-manager";
import { RendererManager } from "./managers/renderer-manager";
import { CommandManager } from "./managers/commands";
import { buildScene } from "@/services/renderer/scene-builder";
import { SceneExporter } from "@/services/renderer/scene-exporter";
import type { ExportOptions } from "@/types/export";
import { DEFAULT_FPS } from "@/constants/editor-constants";
export class EditorCore {
private static instance: EditorCore | null = null;
public readonly command: CommandManager;
public readonly playback: PlaybackManager;
public readonly timeline: TimelineManager;
public readonly scene: SceneManager;
public readonly project: ProjectManager;
public readonly media: MediaManager;
public readonly renderer: RendererManager;
private constructor() {
this.command = new CommandManager();
this.playback = new PlaybackManager(this);
this.timeline = new TimelineManager(this);
this.scene = new SceneManager(this);
this.project = new ProjectManager(this);
this.media = new MediaManager(this);
this.renderer = new RendererManager(this);
}
static getInstance(): EditorCore {
if (!EditorCore.instance) {
EditorCore.instance = new EditorCore();
}
return EditorCore.instance;
}
static reset(): void {
EditorCore.instance = null;
}
async export({
format,
quality,
includeAudio = true,
onProgress,
}: ExportOptions): Promise<{
success: boolean;
buffer?: ArrayBuffer;
error?: string;
}> {
const project = this.project.getActive();
if (!project) {
return { success: false, error: "No active project" };
}
const duration = this.timeline.getTotalDuration();
if (duration === 0) {
return { success: false, error: "Timeline is empty" };
}
try {
const sceneGraph = buildScene({
tracks: this.timeline.getTracks(),
mediaFiles: this.media.getMediaFiles(),
duration,
canvasSize: project.canvasSize,
backgroundColor: project.backgroundColor,
});
const exporter = new SceneExporter({
width: project.canvasSize.width,
height: project.canvasSize.height,
fps: project.fps ?? DEFAULT_FPS,
format,
quality,
includeAudio,
});
if (onProgress) {
exporter.on("progress", onProgress);
}
const buffer = await exporter.export(sceneGraph);
if (onProgress) {
exporter.off("progress", onProgress);
}
if (!buffer) {
return { success: false, error: "Export was cancelled" };
}
return { success: true, buffer };
} catch (error) {
const message = error instanceof Error ? error.message : "Export failed";
return { success: false, error: message };
}
}
}