python-voiceio 0.8.1__py3-none-any.whl → 0.8.2__py3-none-any.whl
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.8.1.dist-info → python_voiceio-0.8.2.dist-info}/METADATA +1 -1
- {python_voiceio-0.8.1.dist-info → python_voiceio-0.8.2.dist-info}/RECORD +10 -10
- voiceio/__init__.py +1 -1
- voiceio/service.py +3 -0
- voiceio/transcriber.py +18 -5
- voiceio/worker.py +17 -1
- {python_voiceio-0.8.1.dist-info → python_voiceio-0.8.2.dist-info}/WHEEL +0 -0
- {python_voiceio-0.8.1.dist-info → python_voiceio-0.8.2.dist-info}/entry_points.txt +0 -0
- {python_voiceio-0.8.1.dist-info → python_voiceio-0.8.2.dist-info}/licenses/LICENSE +0 -0
- {python_voiceio-0.8.1.dist-info → python_voiceio-0.8.2.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
python_voiceio-0.8.
|
|
2
|
-
voiceio/__init__.py,sha256=
|
|
1
|
+
python_voiceio-0.8.2.dist-info/licenses/LICENSE,sha256=Gz61o8jFTAvZUZyB3nWDB3DQQVuipjfPkVu9W8hBHM0,1072
|
|
2
|
+
voiceio/__init__.py,sha256=B7GiO0rd49YwtLYjvPg4lmCZEDlMTonslQKdSImaMJk,22
|
|
3
3
|
voiceio/__main__.py,sha256=xT5QCGGreYMisHO7Lh_Y-xAQ2TOzG2D7npKknGNcWSY,53
|
|
4
4
|
voiceio/app.py,sha256=vO5Sk12CxT2aFtt14XP1Vyen_leUQcqYftswURjN58U,71360
|
|
5
5
|
voiceio/audit.py,sha256=vX3x-YAhmt6EZYRZd0_6wvTquZu5sxGMvH45BhSBnCk,14915
|
|
@@ -27,15 +27,15 @@ voiceio/postprocess.py,sha256=9grkq3I6XgiQV6ZQbIw2_fOUe57tzC7GBPvLXqhhdTs,2979
|
|
|
27
27
|
voiceio/prompt.py,sha256=9iza8KoQxvO_U9NPMJ8Ep7j-zkIs9nW8N5sacCRpsEk,2904
|
|
28
28
|
voiceio/recorder.py,sha256=p1r0mH_plBD3BHqBbIGV_m2N4Mj5RAF7LfMu8u6mk5I,12813
|
|
29
29
|
voiceio/retention.py,sha256=i_VWPCyykT4kQ1uKilTplpiIrACTYljn09BU1vL71A0,6019
|
|
30
|
-
voiceio/service.py,sha256=
|
|
30
|
+
voiceio/service.py,sha256=e3j5OxhuwEqcgXlmQ9AhgdNrrZPwCNfzj-BmABuBYRw,12145
|
|
31
31
|
voiceio/snapshots.py,sha256=bm-lzIeYucDUDlPBZiFiWd-jyB2I6Ft1jRANZCO6go4,2351
|
|
32
32
|
voiceio/streaming.py,sha256=mXkQEEMGMbABSRNG2H7MYObKUdCwfqMvNIZISGZ5uic,25360
|
|
33
|
-
voiceio/transcriber.py,sha256=
|
|
33
|
+
voiceio/transcriber.py,sha256=NWYMZpIhYccUBKzcFyMzjH1MTMNv4bG9op5Qw5reOhI,11608
|
|
34
34
|
voiceio/vad.py,sha256=72_ICk4jSuSPYvTHdHYtHzY8W5uaGEOz5FTdqkolJi8,5327
|
|
35
35
|
voiceio/vocabulary.py,sha256=eGV7QZs3tN6Cw5YpyoZsVEk2M5fJvie1n2XFi9CD4hw,6321
|
|
36
36
|
voiceio/wizard.py,sha256=AwjwrocrQp0DPSOMZ0m6z6G3hlo9VPceEwPzR9-xXe0,80227
|
|
37
37
|
voiceio/wordfreq.py,sha256=2UMjW1xIFqo5EchXzsXPizUhRb9N18CVgjnXso1wsgw,2382
|
|
38
|
-
voiceio/worker.py,sha256=
|
|
38
|
+
voiceio/worker.py,sha256=Ec_OChl6CCX1XHdNYdmx_4l4_sIRexyxih64-PBNhjs,3233
|
|
39
39
|
voiceio/hotkeys/__init__.py,sha256=rGXSGZLD2mS_Ep2HfVdRdkUKNr4xagySlL1FM00cYgk,735
|
|
40
40
|
voiceio/hotkeys/base.py,sha256=L3iBh368sjWpt64JZpocH9DibYEZ0V16-rYflLYbpZY,699
|
|
41
41
|
voiceio/hotkeys/chain.py,sha256=8pvPhipmxWwmGG9DRXy8dlEKTPFILxNzYO-adcvw5Ps,2800
|
|
@@ -71,8 +71,8 @@ voiceio/typers/pynput_type.py,sha256=DTtkT59M-EKOAlTNkvcZrRvf_Fq52OpI8S5t_8S-QAY
|
|
|
71
71
|
voiceio/typers/wtype.py,sha256=d1wG-HZdYDQxXIysV_Xvk9HixDpaJgl3VEoKbP5vhIs,1786
|
|
72
72
|
voiceio/typers/xdotool.py,sha256=dh1zhPqUT8ihJahJ7ZKm6PtfYY087UAzADx664DvQOM,1356
|
|
73
73
|
voiceio/typers/ydotool.py,sha256=dt0W9ot__W8LQG2so8vZLGIw9leK2Q6g3i-Voo0LXE4,5327
|
|
74
|
-
python_voiceio-0.8.
|
|
75
|
-
python_voiceio-0.8.
|
|
76
|
-
python_voiceio-0.8.
|
|
77
|
-
python_voiceio-0.8.
|
|
78
|
-
python_voiceio-0.8.
|
|
74
|
+
python_voiceio-0.8.2.dist-info/METADATA,sha256=tHzCPzNpT-x1-89kZF547QCd-Qo8_XqiL7NIsia6gNw,15877
|
|
75
|
+
python_voiceio-0.8.2.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
76
|
+
python_voiceio-0.8.2.dist-info/entry_points.txt,sha256=U64fA65zxzyLoC8bgbn2ztQVWHLsc0o0H0qCk1J9DMc,218
|
|
77
|
+
python_voiceio-0.8.2.dist-info/top_level.txt,sha256=piwtn309lD6uexQyXdZ-efAVBJF9y6Wfr48Z-8zkNhg,8
|
|
78
|
+
python_voiceio-0.8.2.dist-info/RECORD,,
|
voiceio/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.8.
|
|
1
|
+
__version__ = "0.8.2"
|
voiceio/service.py
CHANGED
|
@@ -61,6 +61,7 @@ PartOf=graphical-session.target
|
|
|
61
61
|
[Service]
|
|
62
62
|
Type=simple
|
|
63
63
|
ExecStart={bin_path}
|
|
64
|
+
Nice=10
|
|
64
65
|
Restart=on-failure
|
|
65
66
|
RestartSec=3
|
|
66
67
|
Environment=PYTHONUNBUFFERED=1
|
|
@@ -80,6 +81,8 @@ Documentation=https://github.com/Hugo0/voiceio
|
|
|
80
81
|
[Service]
|
|
81
82
|
Type=oneshot
|
|
82
83
|
ExecStart={bin_path} correct --auto --batch
|
|
84
|
+
Nice=15
|
|
85
|
+
IOSchedulingClass=idle
|
|
83
86
|
Environment=PYTHONUNBUFFERED=1
|
|
84
87
|
"""
|
|
85
88
|
|
voiceio/transcriber.py
CHANGED
|
@@ -29,6 +29,12 @@ class TranscriptionError(RuntimeError):
|
|
|
29
29
|
# never kills a long dictation mid-decode.
|
|
30
30
|
TIMEOUT_PER_SECOND = 1.5
|
|
31
31
|
MAX_RESTARTS = 3
|
|
32
|
+
# Ceiling on the worker's model-load handshake. A cached load is ~4s (worst
|
|
33
|
+
# observed: 53s), so this only trips on a genuinely stuck start — but it must
|
|
34
|
+
# also leave room for a cold first-run download. Unbounded, a start that hangs
|
|
35
|
+
# (blackholed network, see worker._load_model) holds the transcribe lock
|
|
36
|
+
# forever and every later dictation silently returns "".
|
|
37
|
+
WORKER_START_TIMEOUT = 300
|
|
32
38
|
# A crash-free stretch this long means earlier crashes were transient (suspend,
|
|
33
39
|
# device churn) rather than a fatal loop — reset the restart budget so three
|
|
34
40
|
# unrelated crashes spread over weeks don't permanently kill the daemon.
|
|
@@ -118,9 +124,13 @@ class Transcriber:
|
|
|
118
124
|
)
|
|
119
125
|
|
|
120
126
|
t0 = time.monotonic()
|
|
121
|
-
ready = self.
|
|
122
|
-
if ready != "READY":
|
|
123
|
-
|
|
127
|
+
ready = self._read_with_timeout(WORKER_START_TIMEOUT)
|
|
128
|
+
if ready is None or ready.strip() != "READY":
|
|
129
|
+
self._kill_worker()
|
|
130
|
+
detail = "timed out" if ready is None else f"said {ready.strip()!r}"
|
|
131
|
+
raise TranscriptionError(
|
|
132
|
+
f"worker failed to start ({detail} after {time.monotonic() - t0:.0f}s)"
|
|
133
|
+
)
|
|
124
134
|
elapsed = time.monotonic() - t0
|
|
125
135
|
log.info("Model ready (%.1fs)", elapsed)
|
|
126
136
|
|
|
@@ -199,9 +209,12 @@ class Transcriber:
|
|
|
199
209
|
result_line = self._read_with_timeout(timeout)
|
|
200
210
|
if result_line is None:
|
|
201
211
|
self.last_segments = []
|
|
202
|
-
log.warning("Transcription timed out after %.0fs,
|
|
212
|
+
log.warning("Transcription timed out after %.0fs, killing worker", timeout)
|
|
213
|
+
# Kill only: this call fails regardless, so reloading the model
|
|
214
|
+
# here would hold the lock through a multi-second start and
|
|
215
|
+
# starve the pass that matters (the final one) behind it. The
|
|
216
|
+
# next transcribe — or the health watchdog — restarts lazily.
|
|
203
217
|
self._kill_worker()
|
|
204
|
-
self._ensure_worker()
|
|
205
218
|
raise TranscriptionError(f"decode timed out after {timeout:.0f}s")
|
|
206
219
|
|
|
207
220
|
try:
|
voiceio/worker.py
CHANGED
|
@@ -27,9 +27,25 @@ def _init_pool_hashrate() -> str:
|
|
|
27
27
|
return "nice try"
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
def _load_model(args: dict) -> WhisperModel:
|
|
31
|
+
"""Load the model, preferring the local cache.
|
|
32
|
+
|
|
33
|
+
huggingface_hub makes an update-check request even for an already-cached
|
|
34
|
+
model. That connect has no timeout, so on a blackholed route (e.g. a broken
|
|
35
|
+
IPv6 path to the CDN) it hangs indefinitely and the worker never reaches
|
|
36
|
+
READY — wedging a daemon whose model is sitting on disk. Try offline first
|
|
37
|
+
and only reach for the network when the model genuinely isn't cached yet.
|
|
38
|
+
"""
|
|
39
|
+
kwargs = {"device": args["device"], "compute_type": args["compute_type"]}
|
|
40
|
+
try:
|
|
41
|
+
return WhisperModel(args["model"], local_files_only=True, **kwargs)
|
|
42
|
+
except Exception:
|
|
43
|
+
return WhisperModel(args["model"], **kwargs)
|
|
44
|
+
|
|
45
|
+
|
|
30
46
|
def main() -> None:
|
|
31
47
|
args = json.loads(sys.argv[1])
|
|
32
|
-
model =
|
|
48
|
+
model = _load_model(args)
|
|
33
49
|
|
|
34
50
|
# Warmup: first transcription is always slow
|
|
35
51
|
segs, _ = model.transcribe(np.zeros(16000, dtype=np.float32), language=args.get("language"), beam_size=1)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|