diff --git a/src/app/api/tts/segments/ensure/route.ts b/src/app/api/tts/segments/ensure/route.ts index aa80c1e..e16c084 100644 --- a/src/app/api/tts/segments/ensure/route.ts +++ b/src/app/api/tts/segments/ensure/route.ts @@ -150,6 +150,11 @@ async function deleteEntryIfUnused(userId: string, segmentEntryId: string): Prom export async function POST(request: NextRequest) { let didCreateDeviceIdCookie = false; let deviceIdToSet: string | null = null; + let computeBackendPromise: ReturnType | null = null; + const getComputeBackend = async () => { + if (!computeBackendPromise) computeBackendPromise = getCompute(); + return computeBackendPromise; + }; try { if (!isS3Configured()) return s3NotConfiguredResponse(); @@ -372,7 +377,8 @@ export async function POST(request: NextRequest) { // previously unavailable, retry alignment using the current segment text. if (!alignment) { try { - const aligned = (await getCompute().alignWords({ + const computeBackend = await getComputeBackend(); + const aligned = (await computeBackend.alignWords({ audioObjectKey: existing.audioKey, text: segment.text, })).alignments; @@ -523,7 +529,8 @@ export async function POST(request: NextRequest) { let alignment: TTSSegmentManifestItem['alignment'] = null; try { const whisperBytes = Uint8Array.from(persistedBuffer); - const aligned = (await getCompute().alignWords({ + const computeBackend = await getComputeBackend(); + const aligned = (await computeBackend.alignWords({ audioBuffer: whisperBytes.buffer, audioObjectKey: audioKey, text: segment.text, diff --git a/src/lib/server/compute/index.ts b/src/lib/server/compute/index.ts index 4424f1f..5442429 100644 --- a/src/lib/server/compute/index.ts +++ b/src/lib/server/compute/index.ts @@ -2,21 +2,23 @@ import type { ComputeBackend, ComputeMode } from '@/lib/server/compute/types'; import { isComputeModeAvailable, readComputeMode } from '@/lib/server/compute/mode'; import { WorkerComputeBackend } from '@/lib/server/compute/worker'; -let backend: ComputeBackend | null = null; +let backendPromise: Promise | null = null; -function createBackend(): ComputeBackend { +async function createBackend(): Promise { const mode: ComputeMode = readComputeMode(); if (mode === 'worker') return new WorkerComputeBackend(); - // Intentionally lazy-load local compute to avoid tracing heavy ONNX - // dependencies unless the backend is actually local. - // eslint-disable-next-line @typescript-eslint/no-require-imports - const { LocalComputeBackend } = require('@/lib/server/compute/local') as typeof import('@/lib/server/compute/local'); + const { LocalComputeBackend } = await import('@/lib/server/compute/local'); return new LocalComputeBackend(); } -export function getCompute(): ComputeBackend { - if (!backend) backend = createBackend(); - return backend; +export async function getCompute(): Promise { + if (!backendPromise) { + backendPromise = createBackend().catch((error) => { + backendPromise = null; + throw error; + }); + } + return backendPromise; } export function isComputeAvailable(): boolean { diff --git a/src/lib/server/jobs/parsePdfJob.ts b/src/lib/server/jobs/parsePdfJob.ts index 1410949..c64cea9 100644 --- a/src/lib/server/jobs/parsePdfJob.ts +++ b/src/lib/server/jobs/parsePdfJob.ts @@ -28,7 +28,8 @@ export async function parsePdfJob(input: ParsePdfJobInput): Promise { .set({ parseStatus: 'running' }) .where(and(eq(documents.id, input.documentId), eq(documents.userId, input.userId))); - const parsed = await getCompute().parsePdfLayout({ + const compute = await getCompute(); + const parsed = await compute.parsePdfLayout({ documentId: input.documentId, namespace: input.namespace, documentObjectKey: documentKey(input.documentId, input.namespace),