diff --git a/app/engine.js b/app/engine.js index 262de8b..d7e5559 100644 --- a/app/engine.js +++ b/app/engine.js @@ -1931,23 +1931,34 @@ async function pump() { * drains does not recover on its own. */ /* - * 0.85 and a backlog of five, both measured rather than chosen. + * SLOWER THAN THE AUDIO IT COVERS, AND LANDING LATE. * - * The Mini's sentences ran 4.4 s against 4.5 s of audio — nominally FASTER - * than real time, while the queue sat at 46 and the lag climbed past 150 s. - * Per-sentence time alone therefore misses it: the work outside this timer - * (segmenting, the preview model sharing the GPU, the scheduler) is enough - * to lose on its own. The margin catches "near enough to real time to be - * losing"; the queue depth is the proof that it actually is, and keeps one - * slow sentence on a healthy machine from touching anything. + * This used to fire only past 8 s, on the reasoning that 8 s meant slower + * than people talk. That held when a chunk could be 8 s long; chunks are + * capped at HARD_CUT_MAX, 5.5 s, so a 4.4 s sentence is already losing and + * never came near the old threshold. + * + * Both numbers below were measured on a campus M4 Pro, and the second one + * only after a first attempt got it wrong. 0.85, because that Mac ran 4.4 s + * against 4.5 s of audio — nominally FASTER than real time while losing + * badly, since the work outside this timer (segmenting, the preview model + * sharing the GPU, the scheduler) loses on its own. + * + * The second test was a queue depth, and watching that Mac go red disproved + * it: the queue sat at 2-3 while the lag held at 15 s and the verdict was + * already red. A machine can be persistently late without ever stacking work + * up — it finishes each sentence just slightly too slowly, for ever. So the + * test is how far behind the speaker the sentence actually landed, which is + * what the operator is complaining about in the first place. */ - const losingGround = jobAudioMs > 0 && took > jobAudioMs * 0.85 && queue.length >= 5; + const behindMs = Date.now() - job.at; + const losingGround = jobAudioMs > 0 && took > jobAudioMs * 0.85 && behindMs > 8000; if (took > 8000 || losingGround) { state.slowRun = (state.slowRun || 0) + 1; if (state.slowRun >= 3 && !respawning && lighterAsr(state.asrModelInUse || state.cfg.asrModel)) { state.slowRun = 0; log('transcription is slower than people are speaking (' + took + ' ms for ' + - Math.round(jobAudioMs) + ' ms of audio, ' + queue.length + ' waiting) — ' + + Math.round(jobAudioMs) + ' ms of audio, ' + Math.round(behindMs / 1000) + 's behind) — ' + 'stepping down to a lighter model', 'err'); respawnWorker(state.asrWorker); } diff --git a/app/package.json b/app/package.json index 562b348..74df696 100644 --- a/app/package.json +++ b/app/package.json @@ -2,7 +2,7 @@ "name": "church-translate-engine", "productName": "Church Translate", "version": "3.23.2", - "buildNumber": 117, + "buildNumber": 118, "private": true, "description": "Live sermon translation — self-contained: captures audio, transcribes, translates, and serves the congregation page itself", "main": "main.js", @@ -106,7 +106,7 @@ ] }, "asar": false, - "buildVersion": "117", + "buildVersion": "118", "win": { "target": [ {