Nothing here yet.
Nothing here yet.
Fixed in 0.1.3, now on pub.dev. Testing it showed two problems, not one. On iOS, re-activating the audio session during the change was refused, so the mic could stop entirely; a route change now rebuilds only the engine. And the sentence in progress is now finished instead of dropped. The order you describe is how it works now. The ring only ever holds 16 kHz mono, because each tap callback converts before it writes. So on a route change the audio already buffered from the old route is drained into the endpointer first, the open sentence is emitted as a final result and queued for the decoder, and only then is the endpointer reset for the new input. The decoder runs separately, so the reset can't cancel a decode that's already queued. On stale callbacks: the old tap is removed and the engine stopped before the new converter is built, so a buffer in the old format shouldn't reach it. There's no explicit check, though, and checking each buffer's format against the converter's input is cheap, so I'll add one.
Great question, and you've found a real gap. On a route change (headset connected or removed, earbuds plugged in), iOS capture tears down the tap and the resampler and rebuilds them against the new input format, because AVAudioEngine won't pick up the new rate by itself. Capture keeps writing to the same ring buffer, so nothing downstream has to reconnect, and you can see the change as a short "recovering" state. On the Dart side, audio on either side of the switch isn't continuous, so voice detection and the endpointer are reset rather than stitching two moments into one. Today that reset throws away the sentence that was in progress instead of finishing it. Whatever the user said before the switch is lost, and a new sentence starts on the new mic. Finishing it properly is the right behaviour: decode what was heard before the switch as a final result, then start fresh. That's the next fix.
Good question. The two answers are different on purpose. While you’re speaking, the live text only grows: once a word has matched across two reads it’s never removed, even if a later read changes its mind. That’s what keeps the live text from flickering. When the sentence ends, the whole utterance is decoded again in one pass, and that result replaces the live text completely. So if anything was wrong in the live text, the final result corrects it. On the long pause: if you stop for more than about 400 ms, that counts as the end of the utterance. The first half gets its final result straight away, and the rest starts a new paragraph. A mid-phrase pause can therefore split a sentence in two, and the first half is decoded without the words that come after it. That’s the trade for getting text quickly. A longer hangover setting means fewer splits but a later final result.
Thank you! No per language tuning. Silero VAD does not report the language of the audio, only whether it is speech or not, so the same settings work for all languages. I ran long public recordings (earnings calls and podcasts) through the real pipeline with the defaults and they stood up to added noise. The tough case is when other people are talking in the background. That is speech, so the detector carries on. Steady noise like fans or traffic is okay. If your environment needs something different, then every threshold is in EndpointerConfig.
GoRouter perfectly works on Flutter web. To keep the login state on browser refresh you should save the state in some persistent storage and get it on app start perhaps you can use splash screen for it. In real-world applications people use may local storage to store access tokens or something to validate the login state.