summaryrefslogtreecommitdiff
path: root/apps/web/src/services/transcription/index.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-01-31 22:19:11 +0100
committerMaze Winther <mazewinther@gmail.com>2026-01-31 22:19:11 +0100
commitf820d9a8948b97460ebdfdaa6b42b6d510e2b3cf (patch)
tree460b4cd9ac403fe5591bb0b5b4064e1662d08077 /apps/web/src/services/transcription/index.ts
parent7878c8bb7b83bce568ced990903b8195a9dd4605 (diff)
downloadopencut-f820d9a8948b97460ebdfdaa6b42b6d510e2b3cf.tar.gz
refactor services structure
Diffstat (limited to 'apps/web/src/services/transcription/index.ts')
-rw-r--r--apps/web/src/services/transcription/index.ts186
1 files changed, 0 insertions, 186 deletions
diff --git a/apps/web/src/services/transcription/index.ts b/apps/web/src/services/transcription/index.ts
deleted file mode 100644
index 37c650da..00000000
--- a/apps/web/src/services/transcription/index.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-import type {
- TranscriptionResult,
- TranscriptionProgress,
- TranscriptionModelId,
-} from "@/types/transcription";
-import {
- DEFAULT_TRANSCRIPTION_MODEL,
- TRANSCRIPTION_MODELS,
-} from "@/constants/transcription-constants";
-import type { WorkerMessage, WorkerResponse } from "./worker";
-import type { LanguageCode } from "@/types/language";
-
-type ProgressCallback = (progress: TranscriptionProgress) => void;
-
-class TranscriptionService {
- private worker: Worker | null = null;
- private currentModelId: TranscriptionModelId | null = null;
- private isInitialized = false;
- private isInitializing = false;
-
- async transcribe({
- audioData,
- language,
- modelId = DEFAULT_TRANSCRIPTION_MODEL,
- onProgress,
- }: {
- audioData: Float32Array;
- language?: LanguageCode;
- modelId?: TranscriptionModelId;
- onProgress?: ProgressCallback;
- }): Promise<TranscriptionResult> {
- await this.ensureWorker({ modelId, onProgress });
-
- return new Promise((resolve, reject) => {
- if (!this.worker) {
- reject(new Error("Worker not initialized"));
- return;
- }
-
- const handleMessage = (event: MessageEvent<WorkerResponse>) => {
- const response = event.data;
-
- switch (response.type) {
- case "transcribe-progress":
- onProgress?.({
- status: "transcribing",
- progress: response.progress,
- message: "Transcribing audio...",
- });
- break;
-
- case "transcribe-complete":
- this.worker?.removeEventListener("message", handleMessage);
- resolve({
- text: response.text,
- segments: response.segments,
- language,
- });
- break;
-
- case "transcribe-error":
- this.worker?.removeEventListener("message", handleMessage);
- reject(new Error(response.error));
- break;
-
- case "cancelled":
- this.worker?.removeEventListener("message", handleMessage);
- reject(new Error("Transcription cancelled"));
- break;
- }
- };
-
- this.worker.addEventListener("message", handleMessage);
-
- this.worker.postMessage({
- type: "transcribe",
- audio: audioData,
- language,
- } satisfies WorkerMessage);
- });
- }
-
- cancel() {
- this.worker?.postMessage({ type: "cancel" } satisfies WorkerMessage);
- }
-
- private async ensureWorker({
- modelId,
- onProgress,
- }: {
- modelId: TranscriptionModelId;
- onProgress?: ProgressCallback;
- }): Promise<void> {
- const needsNewModel = this.currentModelId !== modelId;
-
- if (this.worker && this.isInitialized && !needsNewModel) {
- return;
- }
-
- if (this.isInitializing && !needsNewModel) {
- await this.waitForInit();
- return;
- }
-
- this.terminate();
- this.isInitializing = true;
- this.isInitialized = false;
-
- const model = TRANSCRIPTION_MODELS.find((m) => m.id === modelId);
- if (!model) {
- throw new Error(`Unknown model: ${modelId}`);
- }
-
- this.worker = new Worker(new URL("./worker.ts", import.meta.url), {
- type: "module",
- });
-
- return new Promise((resolve, reject) => {
- if (!this.worker) {
- reject(new Error("Failed to create worker"));
- return;
- }
-
- const handleMessage = (event: MessageEvent<WorkerResponse>) => {
- const response = event.data;
-
- switch (response.type) {
- case "init-progress":
- onProgress?.({
- status: "loading-model",
- progress: response.progress,
- message: `Loading ${model.name} model...`,
- });
- break;
-
- case "init-complete":
- this.worker?.removeEventListener("message", handleMessage);
- this.isInitialized = true;
- this.isInitializing = false;
- this.currentModelId = modelId;
- resolve();
- break;
-
- case "init-error":
- this.worker?.removeEventListener("message", handleMessage);
- this.isInitializing = false;
- this.terminate();
- reject(new Error(response.error));
- break;
- }
- };
-
- this.worker.addEventListener("message", handleMessage);
-
- this.worker.postMessage({
- type: "init",
- modelId: model.huggingFaceId,
- } satisfies WorkerMessage);
- });
- }
-
- private waitForInit(): Promise<void> {
- return new Promise((resolve) => {
- const checkInit = () => {
- if (this.isInitialized) {
- resolve();
- } else if (!this.isInitializing) {
- resolve();
- } else {
- setTimeout(checkInit, 100);
- }
- };
- checkInit();
- });
- }
-
- terminate() {
- this.worker?.terminate();
- this.worker = null;
- this.isInitialized = false;
- this.isInitializing = false;
- this.currentModelId = null;
- }
-}
-
-export const transcriptionService = new TranscriptionService();