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.
Files changed (27) hide show
  1. {scribe_cli-0.7.1/scribe_cli.egg-info → scribe_cli-0.7.3}/PKG-INFO +1 -1
  2. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/_version.py +2 -2
  3. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/app.py +39 -10
  4. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/models.py +13 -10
  5. {scribe_cli-0.7.1 → scribe_cli-0.7.3/scribe_cli.egg-info}/PKG-INFO +1 -1
  6. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/.github/workflows/pypi.yml +0 -0
  7. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/.gitignore +0 -0
  8. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/LICENSE +0 -0
  9. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/README.md +0 -0
  10. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/pyproject.toml +0 -0
  11. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/__init__.py +0 -0
  12. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/audio.py +0 -0
  13. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/install_desktop.py +0 -0
  14. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/keyboard.py +0 -0
  15. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/models.toml +0 -0
  16. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/saverecording.py +0 -0
  17. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/testpynput.py +0 -0
  18. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe/util.py +0 -0
  19. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/SOURCES.txt +0 -0
  20. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/dependency_links.txt +0 -0
  21. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/entry_points.txt +0 -0
  22. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/requires.txt +0 -0
  23. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_cli.egg-info/top_level.txt +0 -0
  24. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_data/__init__.py +0 -0
  25. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_data/share/icon.jpg +0 -0
  26. {scribe_cli-0.7.1 → scribe_cli-0.7.3}/scribe_data/templates/scribe.desktop +0 -0
  27. {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.1
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
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.7.1'
16
- __version_tuple__ = version_tuple = (0, 7, 1)
15
+ __version__ = version = '0.7.3'
16
+ __version_tuple__ = version_tuple = (0, 7, 3)
@@ -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
- print(f"Clicked {item}")
232
- # icon.icon = PIL.ImageOps.invert(icon.icon)
233
- # icon.icon = PIL.ImageOps.invert(image)
234
- # icon.update_menu()
235
- start_recording(micro, transcriber, **kwargs)
236
- # icon.icon = image
237
- # icon.update_menu()
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('name', image, "My App", menu)
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
- with microphone.open_stream():
59
- print(start_message)
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
- except KeyboardInterrupt:
88
- pass
90
+ except (KeyboardInterrupt, StopRecording):
91
+ pass
89
92
 
90
- finally:
91
- result = self.finalize()
92
- microphone.q.queue.clear()
93
- yield result
93
+ finally:
94
+ result = self.finalize()
95
+ microphone.q.queue.clear()
96
+ yield result
94
97
 
95
- print(stop_message)
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.1
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