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.
- {scribe_cli-0.7.7/scribe_cli.egg-info → scribe_cli-0.7.8}/PKG-INFO +3 -2
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/README.md +1 -1
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/pyproject.toml +1 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/_version.py +2 -2
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/app.py +51 -11
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/models.py +1 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/util.py +3 -41
- {scribe_cli-0.7.7 → scribe_cli-0.7.8/scribe_cli.egg-info}/PKG-INFO +3 -2
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/requires.txt +1 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/.github/workflows/pypi.yml +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/.gitignore +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/LICENSE +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/__init__.py +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/audio.py +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/install_desktop.py +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/keyboard.py +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/models.toml +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/saverecording.py +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe/testpynput.py +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/SOURCES.txt +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/dependency_links.txt +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/entry_points.txt +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_cli.egg-info/top_level.txt +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_data/__init__.py +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_data/share/icon.jpg +0 -0
- {scribe_cli-0.7.7 → scribe_cli-0.7.8}/scribe_data/templates/scribe.desktop +0 -0
- {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.
|
|
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
|
[]()
|
|
64
|
-
[](https://pypi.org/project/scribe-cli)
|
|
65
66
|
|
|
66
67
|
# Scribe
|
|
67
68
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[]()
|
|
2
|
-
[](https://pypi.org/project/scribe-cli)
|
|
3
3
|
|
|
4
4
|
# Scribe
|
|
5
5
|
|
|
@@ -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"
|
|
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
|
|
285
|
-
print(f"[q] quit")
|
|
286
|
-
print(f"[e] change model")
|
|
287
|
-
print(f"[x]
|
|
288
|
-
print(f"[
|
|
289
|
-
print(f"[
|
|
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]
|
|
294
|
-
|
|
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]', '
|
|
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 !!',
|
|
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.
|
|
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
|
[]()
|
|
64
|
-
[](https://pypi.org/project/scribe-cli)
|
|
65
66
|
|
|
66
67
|
# Scribe
|
|
67
68
|
|
|
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
|