Start on live transcription and python sidecar (faster-whisper)

This commit is contained in:
Lucas Winther committed 2026-07-10 09:28:42 +02:00
1 parent 15bf14728a
commit 033ea32968
14 files changed
+1376 -61

No files matched your search

+27 -5
View File
@@ -61,6 +61,12 @@ export interface TranscribeMessage {
language?: string;
/** Only meaningful for multilingual models. Defaults to "transcribe". */
task?: WhisperTask;
/**
* Optional correlation id, echoed on the partial/result/error messages this
* request produces (D-016). The live-transcription loop uses it to match
* responses to segment passes; the file flow omits it and is unchanged.
*/
requestId?: string;
}
export type UiToWorkerMessage = LoadMessage | TranscribeMessage;
@@ -96,6 +102,8 @@ export type LoadProgressMessage =
export interface PartialMessage {
type: "partial";
text: string;
/** Echo of the originating transcribe request's id, if it carried one. */
requestId?: string;
}
/** One timestamped segment of the final transcript. */
@@ -109,12 +117,16 @@ export interface ResultMessage {
type: "result";
text: string;
chunks: TranscriptChunk[];
/** Echo of the originating transcribe request's id, if it carried one. */
requestId?: string;
}
export interface ErrorMessage {
type: "error";
stage: "load" | "transcribe";
message: string;
/** Echo of the failing transcribe request's id, if it carried one. */
requestId?: string;
}
export type WorkerToUiMessage =
@@ -131,6 +143,10 @@ function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
function isOptionalString(value: unknown): value is string | undefined {
return value === undefined || typeof value === "string";
}
const DEVICES: readonly string[] = ["webgpu", "wasm"];
const DTYPES: readonly string[] = ["fp32", "fp16", "q8", "q4"];
@@ -165,10 +181,11 @@ export function isUiToWorkerMessage(value: unknown): value is UiToWorkerMessage
case "transcribe":
return (
value.audio instanceof Float32Array &&
(value.language === undefined || typeof value.language === "string") &&
isOptionalString(value.language) &&
(value.task === undefined ||
value.task === "transcribe" ||
value.task === "translate")
value.task === "translate") &&
isOptionalString(value.requestId)
);
default:
return false;
@@ -197,13 +214,18 @@ export function isWorkerToUiMessage(value: unknown): value is WorkerToUiMessage
return false;
}
case "partial":
return typeof value.text === "string";
return typeof value.text === "string" && isOptionalString(value.requestId);
case "result":
return typeof value.text === "string" && Array.isArray(value.chunks);
return (
typeof value.text === "string" &&
Array.isArray(value.chunks) &&
isOptionalString(value.requestId)
);
case "error":
return (
typeof value.message === "string" &&
(value.stage === "load" || value.stage === "transcribe")
(value.stage === "load" || value.stage === "transcribe") &&
isOptionalString(value.requestId)
);
default:
return false;