Transcribe and clean up on this machine, without installing anything first

whisper-server is started on --inference-path /v1/audio/transcriptions,
which is exactly the path api.py already builds for the hosted providers,
and llama-server answers /chat/completions the way OpenRouter does. So the
local half is one more base URL rather than a second code path: worker.py,
filetranscribe.py and meeting.py are untouched, and dictation, subtitles
and meetings all work here on the first try.

Three findings worth naming, none of them in the new code:

whisper.cpp cuts segments on tokens, which in Turkish lands inside a word
about as often as between two. Pasted raw that gives "akraba değ\niller.";
in a subtitle it gives a cue reading "değ". Whisper marks the start of a
word with a leading space, so a piece that does not begin with one
continues the word above it.

A small model will repeat the transcript until the context is full, and
every one of those tokens is a second of somebody waiting: measured at 206
seconds, and 25 with a ceiling on the reply. Hosted models are left alone,
where the same runaway is rare and a ceiling would cut the minutes short.

A server outlives SIGTERM and SIGKILL holding its model in memory. Signals
are now turned into an event Qt delivers, since Qt blocks in C where a
Python handler never runs, and a pid file lets the next start sweep up
what a SIGKILL left behind.

The minutes keep their own provider rather than following cleanup's. The
two jobs are not the same size: a 4B model here will strip the filler words
out of a dictation and will not write up an hour long meeting.

The suite runs offline now: a test that reaches the network says so instead
of quietly going there.
This commit is contained in:
yusufipk
2026-08-01 20:00:35 +03:00
parent c0b892f53c
commit 2cfbbb2d99
16 changed files with 1194 additions and 120 deletions
+1 -1
View File
@@ -234,7 +234,7 @@ class Chain(DikteTest):
self.assertEqual(row["raw"], "uh, book it for Thursday")
self.assertEqual(row["text"], "Book it for Thursday.")
self.assertEqual(row["duration"], 2.0)
self.assertEqual(row["model"], self.conf["transcribe_model"])
self.assertEqual(row["model"], self.conf.transcribe_target().model)
self.assertEqual(row["mode"], "")
def test_a_command_is_recorded_as_one(self):