conversations come back as conversations
A probe on the torch stage worker (~/dockers/torch-worker) runs beside every transcription and decides what the recording is: solo dictation returns as paragraphs exactly as before, several voices return speaker-labeled with conversation: true. Nobody declares which — the caller cannot know. Transcription and the worker each get a serial FIFO queue on their own resource, so the probe costs a solo memo nothing and multi-user traffic stays fair. The worker is optional and best-effort throughout: unreachable or failing, everything still transcribes, just never labeled. Speaker attribution is segment-granularity by maximal turn overlap — whisper.cpp's own timestamps, no alignment stage. If boundaries prove sloppy, wav2vec2 alignment returns as a worker endpoint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
// Two serial queues, one per compute resource, shared by every user of the platform.
|
||||
//
|
||||
// The whisper.cpp server and the torch worker each run one job at a time — both saturate their
|
||||
// device, so concurrency inside them buys nothing. What the platform owes its users is fairness
|
||||
// and calm under simultaneous requests: jobs enter here and run strictly in arrival order, and a
|
||||
// slow episode ahead of you delays you but never breaks you.
|
||||
//
|
||||
// The two queues are deliberately independent: a probe or diarization runs on the torch worker
|
||||
// WHILE someone else's transcription runs on Whisper. That is what makes the conversation check
|
||||
// free for solo memos — it happens on the other resource's time.
|
||||
//
|
||||
// v2 (planned, not built): feature-aware ordering — short memos ahead of hour-long episodes,
|
||||
// probes ahead of full diarizations. The queue object is the seam where that goes; callers will
|
||||
// not change.
|
||||
|
||||
export class SerialQueue {
|
||||
private tail: Promise<unknown> = Promise.resolve();
|
||||
private depth = 0;
|
||||
|
||||
/** Jobs currently running or waiting. */
|
||||
get pending(): number {
|
||||
return this.depth;
|
||||
}
|
||||
|
||||
run<T>(job: () => Promise<T>): Promise<T> {
|
||||
this.depth += 1;
|
||||
const result = this.tail.then(job).finally(() => {
|
||||
this.depth -= 1;
|
||||
});
|
||||
// The chain itself must survive a failed job — the failure belongs to the caller who
|
||||
// submitted it, not to everyone queued behind them.
|
||||
this.tail = result.catch(() => undefined);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const whisperQueue = new SerialQueue();
|
||||
export const workerQueue = new SerialQueue();
|
||||
Reference in New Issue
Block a user