scribe-cli 0.7.1__tar.gz → 0.7.3__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.
- {scribe_cli-0.7.1/scribe_cli.egg-info → scribe_cli-0.7.3}/PKG-INFO +1 -1
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/_version.py +2 -2
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/app.py +39 -10
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/models.py +13 -10
- {scribe_cli-0.7.1 → scribe_cli-0.7.3/scribe_cli.egg-info}/PKG-INFO +1 -1
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/.github/workflows/pypi.yml +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/.gitignore +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/LICENSE +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/README.md +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/pyproject.toml +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/__init__.py +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/audio.py +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/install_desktop.py +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/keyboard.py +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/models.toml +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/saverecording.py +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/testpynput.py +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/util.py +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/SOURCES.txt +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/dependency_links.txt +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/entry_points.txt +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/requires.txt +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/top_level.txt +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_data/__init__.py +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_data/share/icon.jpg +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_data/templates/scribe.desktop +0 -0
- {scribe_cli-0.7.1 → scribe_cli-0.7.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: scribe-cli
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3
|
|
4
4
|
Summary: scribe is a local speech recognition tool that provides real-time transcription using vosk and whisper AI.
|
|
5
5
|
Author-email: Mahé Perrette <mahe.perrette@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -3,7 +3,7 @@ import tomllib
|
|
|
3
3
|
import argparse
|
|
4
4
|
from scribe.audio import Microphone
|
|
5
5
|
from scribe.util import print_partial, clear_line, prompt_choices, check_dependencies, ansi_link, colored
|
|
6
|
-
from scribe.models import VoskTranscriber, WhisperTranscriber
|
|
6
|
+
from scribe.models import VoskTranscriber, WhisperTranscriber, StopRecording
|
|
7
7
|
|
|
8
8
|
with open(Path(__file__).parent / "models.toml", "rb") as f:
|
|
9
9
|
language_config_default = tomllib.load(f)
|
|
@@ -212,6 +212,23 @@ def start_recording(micro, transcriber, clipboard=True, keyboard=False, latency=
|
|
|
212
212
|
print("Copied to clipboard.")
|
|
213
213
|
|
|
214
214
|
|
|
215
|
+
def interrupt_app_thread(icon):
|
|
216
|
+
"""Thanks Le Chat for this solution: https://stackoverflow.com/a/325528/2192272
|
|
217
|
+
"""
|
|
218
|
+
import ctypes
|
|
219
|
+
thread = icon._recording_thread
|
|
220
|
+
# Raise an exception in the thread using ctypes
|
|
221
|
+
thread_id = thread.ident
|
|
222
|
+
if thread_id is not None:
|
|
223
|
+
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
|
|
224
|
+
ctypes.c_long(thread_id),
|
|
225
|
+
ctypes.py_object(StopRecording)
|
|
226
|
+
)
|
|
227
|
+
if res > 1:
|
|
228
|
+
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
|
|
229
|
+
print("Failure to raise exception in thread")
|
|
230
|
+
|
|
231
|
+
|
|
215
232
|
def create_app(micro, transcriber, **kwargs):
|
|
216
233
|
import pystray
|
|
217
234
|
from pystray import Menu as pystrayMenu, MenuItem as Item
|
|
@@ -219,31 +236,43 @@ def create_app(micro, transcriber, **kwargs):
|
|
|
219
236
|
import PIL.ImageOps
|
|
220
237
|
|
|
221
238
|
import scribe_data
|
|
239
|
+
import threading
|
|
222
240
|
|
|
223
241
|
# Load an image from a file
|
|
224
242
|
image = Image.open(Path(scribe_data.__file__).parent / "share" / "icon.jpg")
|
|
225
243
|
|
|
226
244
|
def callback_quit(icon, item):
|
|
227
245
|
icon.visible = False
|
|
246
|
+
## Here we need to stop the recording thread
|
|
247
|
+
callback_stop_recording(icon, item)
|
|
228
248
|
icon.stop()
|
|
229
249
|
|
|
250
|
+
def callback_stop_recording(icon, item):
|
|
251
|
+
## Here we need to stop the recording thread
|
|
252
|
+
interrupt_app_thread(icon)
|
|
253
|
+
icon._recording_thread.join()
|
|
254
|
+
|
|
230
255
|
def callback_record(icon, item):
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
256
|
+
icon._recording_thread = threading.Thread(target=start_recording, args=(micro, transcriber), kwargs=kwargs)
|
|
257
|
+
icon._recording_thread.start()
|
|
258
|
+
|
|
259
|
+
def is_recording(item):
|
|
260
|
+
return hasattr(icon, "_recording_thread") and icon._recording_thread.is_alive()
|
|
261
|
+
|
|
262
|
+
def is_not_recording(item):
|
|
263
|
+
return not is_recording(item)
|
|
264
|
+
|
|
238
265
|
|
|
239
266
|
# Create a menu
|
|
240
267
|
menu = pystrayMenu(
|
|
241
|
-
Item('Record', callback_record),
|
|
268
|
+
# Item('Record', callback_record),
|
|
269
|
+
Item("Record", callback_record, visible=is_not_recording),
|
|
270
|
+
Item("Stop", callback_stop_recording, visible=is_recording),
|
|
242
271
|
Item('Quit', callback_quit),
|
|
243
272
|
)
|
|
244
273
|
|
|
245
274
|
# Create the system tray icon
|
|
246
|
-
icon = pystray.Icon('
|
|
275
|
+
icon = pystray.Icon('scribe', image, "scribe", menu)
|
|
247
276
|
|
|
248
277
|
return icon
|
|
249
278
|
|
|
@@ -15,6 +15,8 @@ def is_silent(data, silence_thresh=-40):
|
|
|
15
15
|
VOSK_MODELS_FOLDER = os.path.join(os.environ.get("HOME"),
|
|
16
16
|
".local/share/vosk/language-models")
|
|
17
17
|
|
|
18
|
+
class StopRecording(Exception):
|
|
19
|
+
pass
|
|
18
20
|
|
|
19
21
|
class AbstractTranscriber:
|
|
20
22
|
backend = None
|
|
@@ -55,10 +57,11 @@ class AbstractTranscriber:
|
|
|
55
57
|
|
|
56
58
|
self.reset()
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
try:
|
|
61
|
+
|
|
62
|
+
with microphone.open_stream():
|
|
63
|
+
print(start_message)
|
|
60
64
|
|
|
61
|
-
try:
|
|
62
65
|
while True:
|
|
63
66
|
while not microphone.q.empty():
|
|
64
67
|
data = microphone.q.get()
|
|
@@ -84,15 +87,15 @@ class AbstractTranscriber:
|
|
|
84
87
|
if self.is_overtime():
|
|
85
88
|
raise KeyboardInterrupt("Overtime: {:.2f} seconds".format(self.get_elapsed()))
|
|
86
89
|
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
except (KeyboardInterrupt, StopRecording):
|
|
91
|
+
pass
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
finally:
|
|
94
|
+
result = self.finalize()
|
|
95
|
+
microphone.q.queue.clear()
|
|
96
|
+
yield result
|
|
94
97
|
|
|
95
|
-
|
|
98
|
+
print(stop_message)
|
|
96
99
|
|
|
97
100
|
|
|
98
101
|
def get_vosk_model(model, download_root=None, url=None):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: scribe-cli
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3
|
|
4
4
|
Summary: scribe is a local speech recognition tool that provides real-time transcription using vosk and whisper AI.
|
|
5
5
|
Author-email: Mahé Perrette <mahe.perrette@gmail.com>
|
|
6
6
|
License: MIT License
|
|
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
|