9f42ee2460
Private, offline speech-to-text that runs Whisper on the user's own device — free, no account, no per-minute fees. Replaces Otter.ai / Rev. - Pure, tested engine: chunking, overlap timestamp-stitching, exports (SRT/VTT/TXT/MD/JSON), WAV codec, resampler, job queue, model catalog (142 tests). - Platform-abstracted TranscriptionEngine: transformers.js on web (loaded from CDN at runtime to dodge Metro's onnxruntime-web bundling limits), whisper.rn on native. Shared pipeline orchestrates decode -> chunk -> transcribe -> stitch. - Cross-platform StorageRepo (Dexie web / expo-sqlite native), Zod-validated. - UI: library + search, import, live-progress transcription, synced click-to-seek editor, multi-format export; model picker + privacy in settings. - Web ships as a single-page PWA with COOP/COEP isolation for threaded WASM; Docker (nginx) image + Traefik compose for wisp.briggen.dev. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
// The transcription engine interface: the single abstraction that hides the
|
|
// platform-specific Whisper backend (transformers.js on web, whisper.rn on
|
|
// native) behind one stable contract. The pure orchestration pipeline
|
|
// (pipeline.ts) is written entirely against this interface so it can be unit
|
|
// tested with a fake engine and never imports any heavy/native dependency.
|
|
//
|
|
// IMPORTANT contract detail: `transcribeChunk` returns CHUNK-LOCAL times
|
|
// (0-based, relative to the start of the chunk it was handed). The pipeline is
|
|
// responsible for offsetting those into absolute media time and stitching the
|
|
// overlapping windows together (see pipeline.ts + stitch.ts).
|
|
|
|
import type {
|
|
Backend,
|
|
ModelId,
|
|
PcmAudio,
|
|
Segment,
|
|
TranscribeOptions,
|
|
} from '../types';
|
|
|
|
/**
|
|
* What an engine discovered about the device it is running on. Used by the UI
|
|
* to gate model choices and to decide whether live-mic capture is available.
|
|
*/
|
|
export interface EngineCapabilities {
|
|
/** The compute backend the engine resolved to (e.g. 'webgpu', 'cpu'). */
|
|
backend: Backend;
|
|
/** Whether this engine can transcribe from a live microphone stream. */
|
|
supportsLiveMic: boolean;
|
|
/** Largest model we'd recommend running on this device/backend. */
|
|
maxRecommendedModel: ModelId;
|
|
}
|
|
|
|
/**
|
|
* A platform-agnostic Whisper engine. Both `engineImpl.web.ts` and
|
|
* `engineImpl.native.ts` export a singleton `engine` satisfying this.
|
|
*/
|
|
export interface TranscriptionEngine {
|
|
/** Which platform family this engine targets. */
|
|
readonly platform: 'web' | 'native';
|
|
|
|
/** Probe the device. May be async (e.g. WebGPU adapter request). */
|
|
capabilities(): Promise<EngineCapabilities>;
|
|
|
|
/**
|
|
* Ensure `modelId` is loaded and ready. `onProgress` (if given) receives a
|
|
* fraction in [0, 1] during download/initialization. Implementations should
|
|
* be idempotent: calling again for an already-loaded model is a no-op.
|
|
*/
|
|
loadModel(modelId: ModelId, onProgress?: (p: number) => void): Promise<void>;
|
|
|
|
/** Synchronous check: is this model already loaded in memory? */
|
|
isModelLoaded(modelId: ModelId): boolean;
|
|
|
|
/**
|
|
* Transcribe a single already-decoded 16 kHz mono chunk.
|
|
* Returns segments with CHUNK-LOCAL times (seconds, 0-based). The caller
|
|
* offsets and stitches; engines must NOT add the chunk's media offset.
|
|
*/
|
|
transcribeChunk(audio: PcmAudio, opts: TranscribeOptions): Promise<Segment[]>;
|
|
}
|