Add cancel + progress UI, EngineToggle, and Docker deployment

This commit is contained in:
Lucas Winther
2026-07-14 19:32:10 +02:00
parent be82ecfe57
commit 0084e0435a
16 changed files with 972 additions and 60 deletions
+24 -2
View File
@@ -42,9 +42,16 @@ export interface EngineTranscribeOptions {
* Browser engine: token fragments; server engine: whole segments.
*/
onPartial?: (fragment: string) => void;
/**
* How far the pass has progressed through the audio. Browser engine only —
* faster-whisper's stream carries no window boundaries, so the server
* engine never calls it (the UI degrades to segments-as-feedback).
*/
onProgress?: (progress: { processedSeconds: number; totalSeconds: number }) => void;
/**
* Abort the run. Honored by the server engine (the request is cancelled
* server-side too); the browser worker cannot abort a pass yet (M6).
* server-side too); the browser worker cannot abort a pass — cancel there
* is worker termination via `BrowserEngine.failAll` (D-018).
*/
signal?: AbortSignal;
}
@@ -83,6 +90,7 @@ interface PendingRequest {
resolve: (result: EngineTranscribeResult) => void;
reject: (error: Error) => void;
onPartial?: (fragment: string) => void;
onProgress?: (progress: { processedSeconds: number; totalSeconds: number }) => void;
}
/**
@@ -116,11 +124,19 @@ export class BrowserEngine implements Engine {
): Promise<EngineTranscribeResult> {
const requestId = `engine-${this.instance}-${++this.nextRequestId}`;
return new Promise((resolve, reject) => {
this.pending.set(requestId, { resolve, reject, onPartial: options.onPartial });
this.pending.set(requestId, {
resolve,
reject,
onPartial: options.onPartial,
onProgress: options.onProgress,
});
const message: TranscribeMessage = {
type: "transcribe",
audio,
requestId,
// Id-carrying requests default to no streaming in the worker (the
// live-pass rule) — ask for it explicitly when a consumer listens.
...((options.onPartial || options.onProgress) && { stream: true }),
...(options.language !== undefined &&
options.language !== "auto" && { language: options.language }),
...(options.task !== undefined && { task: options.task }),
@@ -146,6 +162,12 @@ export class BrowserEngine implements Engine {
case "partial":
request.onPartial?.(data.text);
break;
case "transcribe-progress":
request.onProgress?.({
processedSeconds: data.processedSeconds,
totalSeconds: data.totalSeconds,
});
break;
case "result":
this.pending.delete(data.requestId);
request.resolve({ text: data.text, chunks: data.chunks });