scribe-cli 0.7.7__tar.gz → 0.7.8__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.7/scribe_cli.egg-info → scribe_cli-0.7.8}/PKG-INFO +3 -2
  2. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/README.md +1 -1
  3. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/pyproject.toml +1 -0
  4. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/_version.py +2 -2
  5. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/app.py +51 -11
  6. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/models.py +1 -0
  7. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/util.py +3 -41
  8. {scribe_cli-0.7.7 → scribe_cli-0.7.8/scribe_cli.egg-info}/PKG-INFO +3 -2
  9. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/requires.txt +1 -0
  10. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/.github/workflows/pypi.yml +0 -0
  11. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/.gitignore +0 -0
  12. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/LICENSE +0 -0
  13. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/__init__.py +0 -0
  14. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/audio.py +0 -0
  15. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/install_desktop.py +0 -0
  16. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/keyboard.py +0 -0
  17. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/models.toml +0 -0
  18. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/saverecording.py +0 -0
  19. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/testpynput.py +0 -0
  20. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/SOURCES.txt +0 -0
  21. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/dependency_links.txt +0 -0
  22. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/entry_points.txt +0 -0
  23. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/top_level.txt +0 -0
  24. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_data/__init__.py +0 -0
  25. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_data/share/icon.jpg +0 -0
  26. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_data/templates/scribe.desktop +0 -0
  27. {scribe_cli-0.7.7 → scribe_cli-0.7.8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: scribe-cli
3
- Version: 0.7.7
3
+ Version: 0.7.8
4
4
  Summary: scribe is a local speech recognition tool that provides real-time transcription using vosk and whisper AI, with the goal of serving as a virtual keyboard on a computer
5
5
  Author-email: Mahé Perrette <mahe.perrette@gmail.com>
6
6
  License: MIT License
@@ -45,6 +45,7 @@ Requires-Dist: tqdm
45
45
  Requires-Dist: requests
46
46
  Requires-Dist: pyperclip
47
47
  Requires-Dist: unidecode
48
+ Requires-Dist: termcolor
48
49
  Provides-Extra: keyboard
49
50
  Requires-Dist: pynput; extra == "keyboard"
50
51
  Provides-Extra: whisper
@@ -61,7 +62,7 @@ Requires-Dist: vosk; extra == "all"
61
62
  Requires-Dist: pystray; extra == "all"
62
63
 
63
64
  [![python](https://img.shields.io/badge/python-3.12-blue.svg)]()
64
- [![pypi](https://github.com/perrette/scribe/actions/workflows/pypi.yml/badge.svg)](https://pypi.org/project/scribe-cli)
65
+ [![pypi](https://img.shields.io/pypi/v/scribe-cli)](https://pypi.org/project/scribe-cli)
65
66
 
66
67
  # Scribe
67
68
 
@@ -1,5 +1,5 @@
1
1
  [![python](https://img.shields.io/badge/python-3.12-blue.svg)]()
2
- [![pypi](https://github.com/perrette/scribe/actions/workflows/pypi.yml/badge.svg)](https://pypi.org/project/scribe-cli)
2
+ [![pypi](https://img.shields.io/pypi/v/scribe-cli)](https://pypi.org/project/scribe-cli)
3
3
 
4
4
  # Scribe
5
5
 
@@ -19,6 +19,7 @@ dependencies = [
19
19
  "requests",
20
20
  "pyperclip",
21
21
  "unidecode",
22
+ "termcolor",
22
23
  ]
23
24
 
24
25
  classifiers = [
@@ -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.7'
16
- __version_tuple__ = version_tuple = (0, 7, 7)
15
+ __version__ = version = '0.7.8'
16
+ __version_tuple__ = version_tuple = (0, 7, 8)
@@ -37,8 +37,27 @@ def pick_specialist_model(model, language, backend):
37
37
  return model
38
38
 
39
39
 
40
+ class DummyTranscriber:
41
+
42
+ def __init__(self, backend, model_name):
43
+ self.backend = backend
44
+ self.model_name = model_name
45
+
46
+ def start_recording(self, micro, **kwargs):
47
+ while True:
48
+ try:
49
+ yield {"text": input()}
50
+ except KeyboardInterrupt:
51
+ break
52
+
53
+ def __getattr__(self, item):
54
+ return None
55
+
40
56
  def get_transcriber(o, prompt=True):
41
57
 
58
+ if o.dummy:
59
+ return DummyTranscriber("whisper", "dummy")
60
+
42
61
  if o.backend:
43
62
  checked_backend = check_dependencies(o.backend)
44
63
  if not checked_backend:
@@ -143,6 +162,8 @@ def get_parser():
143
162
  parser.add_argument("-l", "--language", choices=list(language_config["vosk"]),
144
163
  help="An alias for preselected models when using the vosk backend, or 'en' for the English version of whisper models.")
145
164
 
165
+ parser.add_argument("--dummy", action="store_true", help=argparse.SUPPRESS)
166
+
146
167
  parser.add_argument("--no-prompt", action="store_false", dest="prompt", help="Disable prompts for backend and model selection and jump to recording")
147
168
  parser.add_argument("--app", action="store_true", help="Start in app mode (relies on pystray)")
148
169
 
@@ -279,25 +300,37 @@ def main(args=None):
279
300
  while True:
280
301
  if transcriber is None:
281
302
  transcriber = get_transcriber(o, prompt=o.prompt)
282
- print(f">>> Model {transcriber.model_name} from {transcriber.backend} selected. Keyboard [{'on' if o.keyboard else 'off'}]. Clipboard [{'on' if o.clipboard else 'off'}] <<<")
303
+ print(f"Model [{colored(transcriber.model_name, 'light_blue', attrs=['bold'])}] from [{colored(transcriber.backend, 'light_blue', attrs=['bold'])}] selected.")
283
304
  if o.prompt:
284
- print(f"Choose any of the following actions (or any command-line toggle flag by name)")
285
- print(f"[q] quit")
286
- print(f"[e] change model")
287
- print(f"[x] toggle app [{toggle[o.app]}] -> [{toggle[not o.app]}]")
288
- print(f"[k] toggle keyboard [{toggle[o.keyboard]}] -> [{toggle[not o.keyboard]}]")
289
- print(f"[c] toggle clipboard [{toggle[o.clipboard]}] -> [{toggle[not o.clipboard]}]")
305
+ print(f"Choose any of the following actions")
306
+ print(f"{colored('[q]', 'light_yellow')} quit")
307
+ print(f"{colored('[e]', 'light_yellow')} change model")
308
+ print(f"{colored('[x]', 'light_yellow')} app is {colored(o.app, 'light_blue')} toggle?")
309
+ print(f"{colored('[c]', 'light_yellow')} clipboard is {colored(o.clipboard, 'light_blue')} toggle?")
310
+ print(f"{colored('[k]', 'light_yellow')} keyboard is {colored(o.keyboard, 'light_blue')} toggle?")
311
+ if o.keyboard:
312
+ print(f"{colored('[latency]', 'light_yellow')} between keystrokes is {colored(o.latency, 'light_blue')} s")
290
313
  if transcriber.backend == "whisper":
291
- print(f"[t] change duration (currently {transcriber.timeout}s)")
292
- print(f"[b] change silence duration (currently {transcriber.silence_duration}s)")
293
- print(f"[a] toggle auto-restart after silence [{toggle[transcriber.restart_after_silence]}] -> [{toggle[not transcriber.restart_after_silence]}]")
294
- print(colored(f"Press [Enter] to start recording.", "BOLD"))
314
+ print(f"{colored('[t]', 'light_yellow')} change duration (currently {colored(transcriber.timeout, 'light_blue')} s)")
315
+ print(f"{colored('[b]', 'light_yellow')} change silence duration (currently {colored(transcriber.silence_duration, 'light_blue')} s)")
316
+ print(f"{colored('[a]', 'light_yellow')} auto-restart after silence is {colored(transcriber.restart_after_silence, 'light_blue')} toggle?")
317
+ exclude_flags = ["keyboard", "clipboard", "app", "prompt", "restart_after_silence"]
318
+ display_flags = [a.dest for a in parser._actions if a.help != argparse.SUPPRESS]
319
+ for key, value in vars(o).items():
320
+ if key not in display_flags or key in exclude_flags or not isinstance(value, bool):
321
+ continue
322
+ print(f"{colored(f'[{key}]', 'light_yellow')} is {colored(value, 'light_blue')} toggle?")
323
+
324
+ print(colored(f"Press [Enter] to start recording.", attrs=["bold"]))
295
325
 
296
326
  key = input()
297
327
  if key == "q":
298
328
  exit(0)
299
329
  if key == "e":
300
330
  transcriber = None
331
+ o.model = None
332
+ o.backend = None
333
+ o.language = None
301
334
  continue
302
335
  if key == "k":
303
336
  o.keyboard = not o.keyboard
@@ -318,6 +351,13 @@ def main(args=None):
318
351
  except:
319
352
  print("Invalid duration. Must be an integer.")
320
353
  continue
354
+ if key == "latency":
355
+ ans = input(f"Enter new keyboard latency in seconds (current: {o.latency}): ")
356
+ try:
357
+ o.latency = float(ans)
358
+ except:
359
+ print("Invalid latency. Must be a float.")
360
+ continue
321
361
  if key == "b":
322
362
  ans = input(f"Enter new silence break duration in seconds (current: {transcriber.silence_duration}): ")
323
363
  try:
@@ -102,6 +102,7 @@ class AbstractTranscriber:
102
102
  def get_vosk_model(model, download_root=None, url=None):
103
103
  """Load the Vosk recognizer"""
104
104
  import vosk
105
+ vosk.SetLogLevel(-1)
105
106
  if download_root is None:
106
107
  download_root = VOSK_MODELS_FOLDER
107
108
  model_path = os.path.join(download_root, model)
@@ -3,26 +3,7 @@ import re
3
3
  import tqdm
4
4
  import shutil
5
5
  from functools import partial
6
-
7
-
8
- class bcolors:
9
- # https://stackoverflow.com/a/287944/2192272
10
- HEADER = '\033[95m'
11
- OKBLUE = '\033[94m'
12
- OKGREEN = '\033[92m'
13
- WARNING = '\033[93m'
14
- FAIL = '\033[91m'
15
- ENDC = '\033[0m'
16
- BOLD = '\033[1m'
17
- UNDERLINE = '\033[4m'
18
-
19
- def strip_colors(s):
20
- for name, c in vars(bcolors).items():
21
- if name.startswith("_"):
22
- continue
23
- s = s.replace(c, '')
24
- return s
25
-
6
+ from termcolor import colored
26
7
 
27
8
  def ansi_link(uri, label=None):
28
9
  """https://stackoverflow.com/a/71309268/2192272
@@ -36,25 +17,6 @@ def ansi_link(uri, label=None):
36
17
 
37
18
  return escape_mask.format(parameters, uri, label)
38
19
 
39
- def colored(text, color):
40
- if hasattr(bcolors, color):
41
- color = getattr(bcolors, color)
42
- return f"{color}{text}{bcolors.ENDC}"
43
-
44
-
45
- ANSI_LINK_RE = re.compile(r'(?P<ansi_sequence>\033]8;(?P<parameter>.*?);(?P<uri>.*?)\033\\(?P<label>.*?)\033]8;;\033\\)')
46
-
47
- def strip_ansi_link(s):
48
- for m in ANSI_LINK_RE.findall(s):
49
- s = s.replace(m[0], m[3])
50
- return s
51
-
52
-
53
- def strip_all(s):
54
- s = strip_colors(s)
55
- s = strip_ansi_link(s)
56
- return s
57
-
58
20
 
59
21
  # Function to clear the terminal line
60
22
  def clear_line():
@@ -119,9 +81,9 @@ def format_choice(enum, default=None, unavailable=None):
119
81
  value_str = value
120
82
 
121
83
  if (default is not None and value == default) or (default is None and i == 0):
122
- return f' ' + colored(f'({i+1}) {value_str} [Press Enter]', 'BOLD')
84
+ return f' ' + colored(f'({i+1}) {value_str} [Press Enter]', attrs=['bold'])
123
85
  elif unavailable and value in unavailable:
124
- return f' ' + colored(f'{" "} {value_str} -> unavailable !!', 'FAIL')
86
+ return f' ' + colored(f'{" "} {value_str} -> unavailable !!', attrs=["strike"])
125
87
  else:
126
88
  return f' ({i+1}) {value_str}'
127
89
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: scribe-cli
3
- Version: 0.7.7
3
+ Version: 0.7.8
4
4
  Summary: scribe is a local speech recognition tool that provides real-time transcription using vosk and whisper AI, with the goal of serving as a virtual keyboard on a computer
5
5
  Author-email: Mahé Perrette <mahe.perrette@gmail.com>
6
6
  License: MIT License
@@ -45,6 +45,7 @@ Requires-Dist: tqdm
45
45
  Requires-Dist: requests
46
46
  Requires-Dist: pyperclip
47
47
  Requires-Dist: unidecode
48
+ Requires-Dist: termcolor
48
49
  Provides-Extra: keyboard
49
50
  Requires-Dist: pynput; extra == "keyboard"
50
51
  Provides-Extra: whisper
@@ -61,7 +62,7 @@ Requires-Dist: vosk; extra == "all"
61
62
  Requires-Dist: pystray; extra == "all"
62
63
 
63
64
  [![python](https://img.shields.io/badge/python-3.12-blue.svg)]()
64
- [![pypi](https://github.com/perrette/scribe/actions/workflows/pypi.yml/badge.svg)](https://pypi.org/project/scribe-cli)
65
+ [![pypi](https://img.shields.io/pypi/v/scribe-cli)](https://pypi.org/project/scribe-cli)
65
66
 
66
67
  # Scribe
67
68
 
@@ -4,6 +4,7 @@ tqdm
4
4
  requests
5
5
  pyperclip
6
6
  unidecode
7
+ termcolor
7
8
 
8
9
  [all]
9
10
  pynput
File without changes
File without changes
File without changes
File without changes