- whisper.ts: add getModelStatus(); fix submitJob() to retry on 503 using
Retry-After header instead of throwing; optional onModelWaiting callback
lets the pipeline surface model state to the UI during the wait
- pipeline.ts: pass onModelWaiting callback → emits model_warming SSE event
so the job detail page can show 'Warming up model…' while waiting
- types.ts: add ModelStateTag union and ModelStatus interface
- api/model/status: GET route proxies whisper /model/status (falls back to
{state:'unloaded'} if whisper unreachable)
- api/model/events: GET route relays whisper SSE stream to the browser;
AbortController tied to request.signal cleans up on disconnect
- layout.svelte: status pill is now live — initial fetch + EventSource on
/api/model/events; dot colour + label reflect real model state with a
pulsing animation while loading or waiting_for_gpu
- jobs/[id]/+page.svelte: handle model_warming event type → show a yellow
'Warming up model…' sub-label with spinner inside the progress card
- whisper.test.ts: update submitJob mocks to status:202 to match real API
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
73 lines
1.5 KiB
TypeScript
73 lines
1.5 KiB
TypeScript
export type AudioMode = 'auto' | 'standard' | 'aggressive' | 'none';
|
|
|
|
export type ModelStateTag = 'unloaded' | 'loading' | 'waiting_for_gpu' | 'ready';
|
|
|
|
export interface ModelStatus {
|
|
state: ModelStateTag;
|
|
loaded_at?: string;
|
|
vram_needed_mb?: number;
|
|
vram_free_mb?: number;
|
|
retry_in_secs?: number;
|
|
vram_used_mb?: number;
|
|
vram_total_mb?: number;
|
|
}
|
|
|
|
export type JobStatus = 'pending' | 'downloading' | 'preparing' | 'transcribing' | 'processing' | 'done' | 'failed' | 'cancelled';
|
|
|
|
export interface Segment {
|
|
index: number;
|
|
start: number;
|
|
end: number;
|
|
text: string;
|
|
words: Word[];
|
|
}
|
|
|
|
export interface Word {
|
|
start: number;
|
|
end: number;
|
|
word: string;
|
|
probability?: number;
|
|
}
|
|
|
|
export interface Job {
|
|
id: string;
|
|
status: JobStatus;
|
|
title: string;
|
|
source: string;
|
|
audioMode: AudioMode;
|
|
meanVolume: number | null;
|
|
whisperJobId: string | null;
|
|
progress: number;
|
|
outputDir: string | null;
|
|
segmentsJson: string | null;
|
|
error: string | null;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface WhisperJob {
|
|
id: string;
|
|
status: 'queued' | 'running' | 'done' | 'failed' | 'cancelled';
|
|
language: string | null;
|
|
task: string;
|
|
duration_secs: number | null;
|
|
progress: number;
|
|
segments: Segment[];
|
|
error: string | null;
|
|
created_at: string;
|
|
completed_at: string | null;
|
|
}
|
|
|
|
export interface PushSubscription {
|
|
id: number;
|
|
endpoint: string;
|
|
p256dh: string;
|
|
auth: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
export interface AudioAnalysis {
|
|
meanVolume: number;
|
|
maxVolume: number;
|
|
}
|