The source is chosen on screen: the microphone or the system capture loop, that is, whatever the PC is playing. Audio comes in at sixteen thousand hertz, is read in two hundred millisecond frames, is mixed to mono and accumulates until it reaches the chunk size. Four seconds is a measured compromise, not a round number: with two seconds there is less delay, but the model loses context and translates a long sentence worse; with six or eight it gains context at the cost of latency. Four is the point where a conversation stays followable.
The queue has a maximum capacity of two chunks. When it fills, the oldest is dropped and the new one comes in. It is the decision I like most in the project: if the model runs slow, the subtitle does not pile up or fall a whole minute behind, it simply shows the present. A subtitle from forty seconds ago is no use at all.
Recognition runs with faster-whisper on CTranslate2 and three parameters worth more than the whole code: voice detection on with three hundred milliseconds of minimum silence, beam of five, and memory of previous text turned off. That last one is what avoids the classic Whisper failure, where it starts repeating and inventing, clinging to what it said in the previous cut. The model is loaded on the worker thread, never on the interface thread, so the window responds while the model wakes up.
On top of the window: a rounded rectangle drawn by hand with QPainter, dragging to place it where it does not cover anything, and a "click-through" mode that lets the mouse reach what is underneath. Without that, an app like this gets in the way in two minutes.
microphone · system audio loop
→ read 200 ms @ 16 kHz · mix to mono
→ 4 s chunk → queue (max 2, oldest dropped)
→ Whisper Small · INT8 · CPU · ja → en · beam 5 · VAD 300 ms
→ [if Spanish is requested] neural translator en → es · beam 4
→ borderless floating window, always on top, click-through