Add cancel + progress UI, EngineToggle, and Docker deployment
This commit is contained in:
@@ -19,6 +19,7 @@ import { resolveDefaultDtype } from "../lib/models";
|
||||
import {
|
||||
deviceAttempts,
|
||||
isUiToWorkerMessage,
|
||||
TranscribeProgressTracker,
|
||||
type DeviceCapabilities,
|
||||
type DevicePreference,
|
||||
type InferenceDevice,
|
||||
@@ -209,6 +210,12 @@ function load(message: LoadMessage): Promise<AutomaticSpeechRecognitionPipeline>
|
||||
// Transcription
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Audio sample rate the whole app standardizes on (D-012). */
|
||||
const SAMPLE_RATE = 16_000;
|
||||
/** Chunked-pipeline window / overlap, in seconds (Whisper's usual 30/5). */
|
||||
const CHUNK_LENGTH_S = 30;
|
||||
const STRIDE_LENGTH_S = 5;
|
||||
|
||||
async function transcribe(message: TranscribeMessage): Promise<void> {
|
||||
if (active === null) {
|
||||
post({
|
||||
@@ -222,11 +229,39 @@ async function transcribe(message: TranscribeMessage): Promise<void> {
|
||||
const asr = await active.promise;
|
||||
|
||||
const options: Record<string, unknown> = {
|
||||
chunk_length_s: 30,
|
||||
stride_length_s: 5,
|
||||
chunk_length_s: CHUNK_LENGTH_S,
|
||||
stride_length_s: STRIDE_LENGTH_S,
|
||||
return_timestamps: true,
|
||||
};
|
||||
if (message.requestId === undefined) {
|
||||
if (message.stream ?? message.requestId === undefined) {
|
||||
// File-flow pass (id-less, or routed through BrowserEngine with an
|
||||
// explicit stream flag, D-010): stream partial tokens and report audio
|
||||
// progress. The streamer's chunk timestamps are window-relative; the
|
||||
// tracker maps them to monotone absolute seconds (see protocol.ts).
|
||||
// Live passes skip both — they resolve wholesale via "result" (D-016).
|
||||
const totalSeconds = message.audio.length / SAMPLE_RATE;
|
||||
const tracker = new TranscribeProgressTracker(
|
||||
totalSeconds,
|
||||
CHUNK_LENGTH_S,
|
||||
CHUNK_LENGTH_S - 2 * STRIDE_LENGTH_S,
|
||||
);
|
||||
const postProgress = (processedSeconds: number | null) => {
|
||||
if (processedSeconds === null) return;
|
||||
post({
|
||||
type: "transcribe-progress",
|
||||
processedSeconds,
|
||||
totalSeconds,
|
||||
requestId: message.requestId,
|
||||
});
|
||||
};
|
||||
// Immediate 0/total so the UI shows the audio length before the first
|
||||
// (possibly slow) token arrives.
|
||||
post({
|
||||
type: "transcribe-progress",
|
||||
processedSeconds: 0,
|
||||
totalSeconds,
|
||||
requestId: message.requestId,
|
||||
});
|
||||
options.streamer = new WhisperTextStreamer(
|
||||
// The ASR pipeline for Whisper models always carries a WhisperTokenizer.
|
||||
asr.tokenizer as ConstructorParameters<typeof WhisperTextStreamer>[0],
|
||||
@@ -234,6 +269,9 @@ async function transcribe(message: TranscribeMessage): Promise<void> {
|
||||
skip_prompt: true,
|
||||
callback_function: (text: string) =>
|
||||
post({ type: "partial", text, requestId: message.requestId }),
|
||||
on_chunk_start: (time: number) => postProgress(tracker.timestamp(time)),
|
||||
on_chunk_end: (time: number) => postProgress(tracker.timestamp(time)),
|
||||
on_finalize: () => postProgress(tracker.finalizeWindow()),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user