Tie: Danish end-of-turn detector
Tie is Danish for "to fall silent". It is a sibling of Hviske (ASR) and Plapre (TTS).
A small audio-only model that answers one question for voice agents: the Danish speaker just went quiet. Are they done, or only pausing?
It listens to the last 8 seconds of audio, 200 ms into a pause, and returns P(done). No transcript is needed. The int8 ONNX model is 25 MB and takes 28 ms on 2 CPU threads per decision (15 ms on 4, 54 ms on 1).
Try it in the demo. It runs in your browser.
Results
Held-out test set of 96,110 pauses the model has never seen.
| AUC | F1 (50/50) | |
|---|---|---|
| Unambiguous pauses (12,120) | 0.963 | 0.907 |
| Same, int8 ONNX | 0.963 | 0.906 |
| All test pauses | 0.917 | 0.847 |
"Unambiguous pauses" are the test pauses where the right answer is clear. On those, the model gets 9 out of 10 decisions right at threshold 0.5. "50/50" weights turn ends and holds equally.
As a turn-taking policy
Respond 200 ms into the pause if P(done) > threshold, otherwise fall back to a 2 s silence timer (all test pauses, natural frequencies):
| Policy | Cuts off a speaker who was only pausing | Mean reply latency when they were done |
|---|---|---|
| silence timer 0.5 s | 47.2% | 0.50 s |
| silence timer 0.8 s | 18.6% | 0.80 s |
| model, threshold 0.5 | 13.4% | 0.55 s |
| model, threshold 0.8 | 9.0% | 0.72 s |
| model, threshold 0.9 | 6.7% | 0.88 s |
Usage
Input: audio, float32 [1, 128000]. This is 16 kHz mono: the last 8 s up to the decision point, left-padded with zeros if shorter. Output: p_done, the probability that the turn is over. Call it about 200 ms after the last word.
import numpy as np, onnxruntime as ort
sess = ort.InferenceSession("eot.int8.onnx", providers=["CPUExecutionProvider"])
w = audio_16k[-128000:].astype(np.float32); w = np.pad(w, (128000 - len(w), 0))[None]
p_done = sess.run(None, {"audio": w})[0].item()
example.py wraps this. eot.onnx is the fp32 export, identical to PyTorch. model.safetensors + model.py are the PyTorch weights and architecture. PyTorch forward returns a logit; the ONNX export applies the sigmoid.
Model
- Transformer audio encoder over 8 s of log-mel features, attention pooling, and a 2-layer MLP head.
- Binary cross-entropy loss.
- Exported to ONNX with the STFT as a fixed DFT convolution.
- Dynamic int8 quantization of the MatMul weights, per channel. Default per-tensor int8 lost 1.6 F1 points; per-channel loses 0.04.
Limitations
- Audio only. It hears prosody, not grammar. A speaker who stops mid-sentence with falling intonation can sound finished. Combining it with an ASR-based text signal should help.
- Natural speech. Synthetic (TTS) voices fool it. Phone-quality and far-field audio are untested.
- Ambiguous pauses. On pauses where even people would disagree, accuracy drops. The remaining errors look like genuine ambiguity in the audio.