python-voiceio 0.8.1__tar.gz → 0.8.2__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.
Files changed (125) hide show
  1. {python_voiceio-0.8.1/python_voiceio.egg-info → python_voiceio-0.8.2}/PKG-INFO +1 -1
  2. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/pyproject.toml +1 -1
  3. {python_voiceio-0.8.1 → python_voiceio-0.8.2/python_voiceio.egg-info}/PKG-INFO +1 -1
  4. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_ibus_ping.py +6 -0
  5. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_transcriber.py +85 -0
  6. python_voiceio-0.8.2/voiceio/__init__.py +1 -0
  7. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/service.py +3 -0
  8. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/transcriber.py +18 -5
  9. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/worker.py +17 -1
  10. python_voiceio-0.8.1/voiceio/__init__.py +0 -1
  11. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/LICENSE +0 -0
  12. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/README.md +0 -0
  13. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/python_voiceio.egg-info/SOURCES.txt +0 -0
  14. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/python_voiceio.egg-info/dependency_links.txt +0 -0
  15. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/python_voiceio.egg-info/entry_points.txt +0 -0
  16. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/python_voiceio.egg-info/requires.txt +0 -0
  17. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/python_voiceio.egg-info/top_level.txt +0 -0
  18. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/setup.cfg +0 -0
  19. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_adjudicate.py +0 -0
  20. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_app_wiring.py +0 -0
  21. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_audio_quality.py +0 -0
  22. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_audit.py +0 -0
  23. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_autocorrect.py +0 -0
  24. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_autocorrect_state.py +0 -0
  25. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_backend_probes.py +0 -0
  26. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_cli.py +0 -0
  27. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_clipboard_read.py +0 -0
  28. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_commands.py +0 -0
  29. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_concurrency_lockdown.py +0 -0
  30. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_config.py +0 -0
  31. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_correct_batch.py +0 -0
  32. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_corrections.py +0 -0
  33. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_fallback.py +0 -0
  34. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_health.py +0 -0
  35. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_hints.py +0 -0
  36. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_history.py +0 -0
  37. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_ibus_pending.py +0 -0
  38. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_ibus_typer.py +0 -0
  39. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_llm.py +0 -0
  40. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_llm_api.py +0 -0
  41. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_numbers.py +0 -0
  42. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_platform.py +0 -0
  43. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_postcorrect.py +0 -0
  44. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_postprocess.py +0 -0
  45. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_prebuffer.py +0 -0
  46. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_prompt.py +0 -0
  47. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_recorder_integration.py +0 -0
  48. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_retention.py +0 -0
  49. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_robustness.py +0 -0
  50. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_security_hardening.py +0 -0
  51. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_snapshots.py +0 -0
  52. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_streaming.py +0 -0
  53. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_tts.py +0 -0
  54. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_vad.py +0 -0
  55. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_vocabulary.py +0 -0
  56. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_wizard.py +0 -0
  57. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/tests/test_wordfreq.py +0 -0
  58. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/__main__.py +0 -0
  59. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/app.py +0 -0
  60. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/audit.py +0 -0
  61. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/autocorrect.py +0 -0
  62. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/autocorrect_state.py +0 -0
  63. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/backends.py +0 -0
  64. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/cli.py +0 -0
  65. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/clipboard_read.py +0 -0
  66. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/commands.py +0 -0
  67. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/config.py +0 -0
  68. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/consent.py +0 -0
  69. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/corrections.py +0 -0
  70. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/demo.py +0 -0
  71. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/feedback.py +0 -0
  72. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/health.py +0 -0
  73. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/hints.py +0 -0
  74. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/history.py +0 -0
  75. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/hotkeys/__init__.py +0 -0
  76. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/hotkeys/base.py +0 -0
  77. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/hotkeys/chain.py +0 -0
  78. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/hotkeys/evdev.py +0 -0
  79. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/hotkeys/pynput_backend.py +0 -0
  80. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/hotkeys/socket_backend.py +0 -0
  81. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/ibus/__init__.py +0 -0
  82. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/ibus/engine.py +0 -0
  83. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/ibus/pending.py +0 -0
  84. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/llm.py +0 -0
  85. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/llm_api.py +0 -0
  86. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/models/__init__.py +0 -0
  87. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/models/silero_vad.onnx +0 -0
  88. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/numbers.py +0 -0
  89. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/pidlock.py +0 -0
  90. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/platform.py +0 -0
  91. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/postcorrect.py +0 -0
  92. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/postprocess.py +0 -0
  93. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/prompt.py +0 -0
  94. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/recorder.py +0 -0
  95. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/retention.py +0 -0
  96. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/snapshots.py +0 -0
  97. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/sounds/__init__.py +0 -0
  98. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/sounds/commit.wav +0 -0
  99. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/sounds/start.wav +0 -0
  100. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/sounds/stop.wav +0 -0
  101. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/streaming.py +0 -0
  102. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tray/__init__.py +0 -0
  103. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tray/_icons.py +0 -0
  104. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tray/_indicator.py +0 -0
  105. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tray/_pystray.py +0 -0
  106. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tts/__init__.py +0 -0
  107. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tts/base.py +0 -0
  108. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tts/chain.py +0 -0
  109. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tts/edge_engine.py +0 -0
  110. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tts/espeak.py +0 -0
  111. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tts/piper_engine.py +0 -0
  112. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/tts/player.py +0 -0
  113. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/typers/__init__.py +0 -0
  114. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/typers/base.py +0 -0
  115. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/typers/chain.py +0 -0
  116. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/typers/clipboard.py +0 -0
  117. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/typers/ibus.py +0 -0
  118. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/typers/pynput_type.py +0 -0
  119. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/typers/wtype.py +0 -0
  120. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/typers/xdotool.py +0 -0
  121. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/typers/ydotool.py +0 -0
  122. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/vad.py +0 -0
  123. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/vocabulary.py +0 -0
  124. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/wizard.py +0 -0
  125. {python_voiceio-0.8.1 → python_voiceio-0.8.2}/voiceio/wordfreq.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-voiceio
3
- Version: 0.8.1
3
+ Version: 0.8.2
4
4
  Summary: Voice dictation for Linux. Speak → text, locally, instantly.
5
5
  Author: Hugo Montenegro
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-voiceio"
7
- version = "0.8.1"
7
+ version = "0.8.2"
8
8
  description = "Voice dictation for Linux. Speak → text, locally, instantly."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-voiceio
3
- Version: 0.8.1
3
+ Version: 0.8.2
4
4
  Summary: Voice dictation for Linux. Speak → text, locally, instantly.
5
5
  Author: Hugo Montenegro
6
6
  License-Expression: MIT
@@ -4,10 +4,16 @@ socket path silently starves the healthy instance)."""
4
4
  from __future__ import annotations
5
5
 
6
6
  import socket
7
+ import sys
7
8
  import threading
8
9
 
10
+ import pytest
11
+
9
12
  import voiceio.ibus as ibus_mod
10
13
 
14
+ # IBus (and AF_UNIX DGRAM + Linux abstract autobind) is Linux-only.
15
+ pytestmark = pytest.mark.skipif(sys.platform != "linux", reason="IBus is Linux-only")
16
+
11
17
 
12
18
  def test_no_socket_returns_false(tmp_path, monkeypatch):
13
19
  monkeypatch.setattr(ibus_mod, "SOCKET_PATH", tmp_path / "nope.sock")
@@ -166,3 +166,88 @@ class TestTimeoutRaises:
166
166
  with pytest.raises(TranscriptionError):
167
167
  t.transcribe(np.zeros(16000, dtype=np.float32))
168
168
  assert t.last_segments == []
169
+
170
+
171
+ class TestWorkerStartTimeout:
172
+ """A worker that never reports READY must not wedge the daemon.
173
+
174
+ faster-whisper's model load contacts huggingface_hub even for a cached
175
+ model; on a blackholed route that connect hangs indefinitely. An unbounded
176
+ READY handshake then holds the transcribe lock forever and every later
177
+ dictation silently returns "".
178
+ """
179
+
180
+ def test_start_raises_instead_of_hanging(self):
181
+ import threading
182
+ from voiceio.transcriber import Transcriber, TranscriptionError
183
+
184
+ mock_proc = MagicMock()
185
+ mock_proc.poll.return_value = None
186
+ mock_proc.stdout.readline.side_effect = lambda: threading.Event().wait()
187
+
188
+ with patch("voiceio.transcriber.subprocess.Popen", return_value=mock_proc), \
189
+ patch("voiceio.transcriber.WORKER_START_TIMEOUT", 0.1):
190
+ with pytest.raises(TranscriptionError, match="failed to start"):
191
+ Transcriber(ModelConfig())
192
+
193
+ # The hung process is reaped, not leaked.
194
+ assert mock_proc.terminate.called or mock_proc.kill.called
195
+
196
+ def test_start_raises_on_garbage_handshake(self):
197
+ from voiceio.transcriber import Transcriber, TranscriptionError
198
+
199
+ mock_proc = MagicMock()
200
+ mock_proc.poll.return_value = None
201
+ mock_proc.stdout.readline.return_value = "Traceback: boom\n"
202
+
203
+ with patch("voiceio.transcriber.subprocess.Popen", return_value=mock_proc):
204
+ with pytest.raises(TranscriptionError, match="failed to start"):
205
+ Transcriber(ModelConfig())
206
+
207
+
208
+ class TestDecodeTimeoutIsLazy:
209
+ """The timed-out call fails regardless, so reloading the model inline would
210
+ hold the lock through a multi-second start and starve the final pass."""
211
+
212
+ def test_decode_timeout_does_not_reload_inline(self):
213
+ import numpy as np
214
+ from voiceio.transcriber import Transcriber, TranscriptionError
215
+
216
+ mock_proc = MagicMock()
217
+ mock_proc.stdout.readline.return_value = "READY\n"
218
+ mock_proc.poll.return_value = None
219
+ with patch("voiceio.transcriber.subprocess.Popen", return_value=mock_proc):
220
+ t = Transcriber(ModelConfig())
221
+
222
+ with patch.object(t, "_read_with_timeout", return_value=None), \
223
+ patch.object(t, "_kill_worker") as kill, \
224
+ patch.object(t, "_ensure_worker") as ensure:
225
+ with pytest.raises(TranscriptionError):
226
+ t.transcribe(np.zeros(16000, dtype=np.float32))
227
+
228
+ assert kill.called
229
+ # Only the entry call — never a second, restarting one.
230
+ assert ensure.call_count == 1
231
+
232
+
233
+ class TestWorkerModelLoad:
234
+ """A cached model must load without touching the network."""
235
+
236
+ ARGS = {"model": "small", "device": "auto", "compute_type": "int8"}
237
+
238
+ def test_prefers_local_cache(self):
239
+ from voiceio import worker
240
+
241
+ with patch("voiceio.worker.WhisperModel") as wm:
242
+ worker._load_model(dict(self.ARGS))
243
+ assert wm.call_args.kwargs["local_files_only"] is True
244
+
245
+ def test_falls_back_to_network_when_not_cached(self):
246
+ from voiceio import worker
247
+
248
+ sentinel = object()
249
+ with patch("voiceio.worker.WhisperModel",
250
+ side_effect=[OSError("not cached"), sentinel]) as wm:
251
+ got = worker._load_model(dict(self.ARGS))
252
+ assert got is sentinel
253
+ assert "local_files_only" not in wm.call_args.kwargs
@@ -0,0 +1 @@
1
+ __version__ = "0.8.2"
@@ -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
 
@@ -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._proc.stdout.readline().strip()
122
- if ready != "READY":
123
- raise RuntimeError(f"Worker failed to start: {ready}")
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, restarting worker", timeout)
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:
@@ -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 = WhisperModel(args["model"], device=args["device"], compute_type=args["compute_type"])
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)
@@ -1 +0,0 @@
1
- __version__ = "0.8.1"
File without changes
File without changes
File without changes