python-voiceio 0.9.4__tar.gz → 0.9.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_voiceio-0.9.4/python_voiceio.egg-info → python_voiceio-0.9.5}/PKG-INFO +1 -1
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/pyproject.toml +1 -1
- {python_voiceio-0.9.4 → python_voiceio-0.9.5/python_voiceio.egg-info}/PKG-INFO +1 -1
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_vad.py +33 -10
- python_voiceio-0.9.5/voiceio/__init__.py +1 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/vad.py +13 -3
- python_voiceio-0.9.4/voiceio/__init__.py +0 -1
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/LICENSE +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/README.md +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/python_voiceio.egg-info/SOURCES.txt +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/python_voiceio.egg-info/dependency_links.txt +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/python_voiceio.egg-info/entry_points.txt +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/python_voiceio.egg-info/requires.txt +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/python_voiceio.egg-info/top_level.txt +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/setup.cfg +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_adjudicate.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_app_wiring.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_audio_quality.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_audit.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_autocorrect.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_autocorrect_state.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_backend_probes.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_cli.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_clipboard_read.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_commands.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_concurrency_lockdown.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_config.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_correct_batch.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_corrections.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_evaluate.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_fallback.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_health.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_hints.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_history.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_ibus_pending.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_ibus_ping.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_ibus_typer.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_llm.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_llm_api.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_numbers.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_platform.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_postcorrect.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_postprocess.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_prebuffer.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_prompt.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_recorder_integration.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_retention.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_robustness.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_security_hardening.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_snapshots.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_streaming.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_tokens.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_transcriber.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_tts.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_vocabulary.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_wizard.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/tests/test_wordfreq.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/__main__.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/app.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/audit.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/autocorrect.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/autocorrect_state.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/backends.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/cli.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/clipboard_read.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/commands.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/config.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/consent.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/corrections.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/demo.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/evaluate.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/feedback.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/health.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/hints.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/history.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/hotkeys/__init__.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/hotkeys/base.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/hotkeys/chain.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/hotkeys/evdev.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/hotkeys/pynput_backend.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/hotkeys/socket_backend.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/ibus/__init__.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/ibus/engine.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/ibus/pending.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/llm.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/llm_api.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/models/__init__.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/models/silero_vad.onnx +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/numbers.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/pidlock.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/platform.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/postcorrect.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/postprocess.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/prompt.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/recorder.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/retention.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/service.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/snapshots.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/sounds/__init__.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/sounds/commit.wav +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/sounds/start.wav +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/sounds/stop.wav +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/streaming.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tokens.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/transcriber.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tray/__init__.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tray/_icons.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tray/_indicator.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tray/_pystray.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tts/__init__.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tts/base.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tts/chain.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tts/edge_engine.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tts/espeak.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tts/piper_engine.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/tts/player.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/typers/__init__.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/typers/base.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/typers/chain.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/typers/clipboard.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/typers/ibus.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/typers/pynput_type.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/typers/wtype.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/typers/xdotool.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/typers/ydotool.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/vocab_stats.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/vocabulary.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/wizard.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/wordfreq.py +0 -0
- {python_voiceio-0.9.4 → python_voiceio-0.9.5}/voiceio/worker.py +0 -0
|
@@ -51,16 +51,39 @@ class TestSileroVad:
|
|
|
51
51
|
chunk = np.zeros(1024, dtype=np.float32)
|
|
52
52
|
assert vad.is_speech(chunk) is False
|
|
53
53
|
|
|
54
|
-
def
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
def test_v5_feeds_context_window(self, vad):
|
|
55
|
+
"""Regression: Silero v5 consumes 512+64=576 samples — the window plus
|
|
56
|
+
the previous window's 64-sample tail as context. Feeding a bare 512
|
|
57
|
+
(the pre-fix bug) makes the model score all real speech as silence
|
|
58
|
+
(measured: max prob 0.016 vs 1.0 with context)."""
|
|
59
|
+
if not vad._use_state:
|
|
60
|
+
pytest.skip("v4 model has no context requirement")
|
|
61
|
+
seen = []
|
|
62
|
+
real_run = vad._session.run
|
|
63
|
+
|
|
64
|
+
def spy(outs, inputs):
|
|
65
|
+
seen.append(inputs["input"])
|
|
66
|
+
return real_run(outs, inputs)
|
|
67
|
+
|
|
68
|
+
vad._session.run = spy
|
|
69
|
+
# Two distinct windows so we can check the context carries across.
|
|
70
|
+
w1 = np.arange(512, dtype=np.float32) / 512.0
|
|
71
|
+
w2 = np.arange(512, 1024, dtype=np.float32) / 512.0
|
|
72
|
+
vad.is_speech(w1)
|
|
73
|
+
vad.is_speech(w2)
|
|
74
|
+
assert seen[0].shape[-1] == 512 + 64 # 576, not a bare 512
|
|
75
|
+
# First call's context is zeros; second call's leading 64 samples must
|
|
76
|
+
# be the tail of the first window (state carried between steps).
|
|
77
|
+
assert np.allclose(seen[0][0, :64], 0.0)
|
|
78
|
+
assert np.allclose(seen[1][0, :64], w1[-64:])
|
|
79
|
+
|
|
80
|
+
def test_reset_clears_context(self, vad):
|
|
81
|
+
if not vad._use_state:
|
|
82
|
+
pytest.skip("v4 model has no context")
|
|
83
|
+
vad.is_speech(np.arange(512, dtype=np.float32) / 512.0)
|
|
84
|
+
assert not np.allclose(vad._context, 0.0) # context now populated
|
|
85
|
+
vad.reset()
|
|
86
|
+
assert np.allclose(vad._context, 0.0)
|
|
64
87
|
|
|
65
88
|
def test_reset_clears_state(self, vad):
|
|
66
89
|
chunk = np.zeros(1024, dtype=np.float32)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.9.5"
|
|
@@ -16,6 +16,11 @@ log = logging.getLogger(__name__)
|
|
|
16
16
|
_MODEL_PATH = Path(__file__).parent / "models" / "silero_vad.onnx"
|
|
17
17
|
_WINDOW_SIZE = 512 # Silero expects 512 samples at 16kHz (~32ms)
|
|
18
18
|
_SAMPLE_RATE = 16000
|
|
19
|
+
# Silero v5 consumes 576 samples per step: the 512-sample window PLUS the 64
|
|
20
|
+
# trailing samples of the previous window as context. Feeding a bare 512 makes
|
|
21
|
+
# the model score everything as non-speech (measured: max prob 0.016 vs 1.0
|
|
22
|
+
# with context). The official ONNX wrapper prepends this outside the graph.
|
|
23
|
+
_CONTEXT_SIZE = 64
|
|
19
24
|
|
|
20
25
|
|
|
21
26
|
@runtime_checkable
|
|
@@ -46,6 +51,8 @@ class SileroVad:
|
|
|
46
51
|
state_meta = [inp for inp in self._session.get_inputs() if inp.name == "state"][0]
|
|
47
52
|
state_dim = state_meta.shape[2] # 128 for v5
|
|
48
53
|
self._state = np.zeros((2, 1, state_dim), dtype=np.float32)
|
|
54
|
+
# v5 context: the previous window's trailing 64 samples.
|
|
55
|
+
self._context = np.zeros(_CONTEXT_SIZE, dtype=np.float32)
|
|
49
56
|
else:
|
|
50
57
|
self._h = np.zeros((2, 1, 64), dtype=np.float32)
|
|
51
58
|
self._c = np.zeros((2, 1, 64), dtype=np.float32)
|
|
@@ -56,6 +63,7 @@ class SileroVad:
|
|
|
56
63
|
def reset(self) -> None:
|
|
57
64
|
if self._use_state:
|
|
58
65
|
self._state = np.zeros_like(self._state)
|
|
66
|
+
self._context = np.zeros(_CONTEXT_SIZE, dtype=np.float32)
|
|
59
67
|
else:
|
|
60
68
|
self._h = np.zeros_like(self._h)
|
|
61
69
|
self._c = np.zeros_like(self._c)
|
|
@@ -76,13 +84,15 @@ class SileroVad:
|
|
|
76
84
|
return speech
|
|
77
85
|
|
|
78
86
|
def _infer(self, window: np.ndarray) -> float:
|
|
79
|
-
input_data = window.reshape(1, -1)
|
|
80
87
|
sr = np.array(_SAMPLE_RATE, dtype=np.int64)
|
|
81
88
|
if self._use_state:
|
|
82
|
-
|
|
89
|
+
# Prepend the previous window's tail; the model needs 512+64=576.
|
|
90
|
+
x = np.concatenate([self._context, window])
|
|
91
|
+
self._context = window[-_CONTEXT_SIZE:].copy()
|
|
92
|
+
ort_inputs = {"input": x.reshape(1, -1), "state": self._state, "sr": sr}
|
|
83
93
|
out, self._state = self._session.run(None, ort_inputs)
|
|
84
94
|
else:
|
|
85
|
-
ort_inputs = {"input":
|
|
95
|
+
ort_inputs = {"input": window.reshape(1, -1), "h": self._h, "c": self._c, "sr": sr}
|
|
86
96
|
out, self._h, self._c = self._session.run(None, ort_inputs)
|
|
87
97
|
return float(out.squeeze())
|
|
88
98
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.9.4"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|