RealTimeSTT 0.3.2__tar.gz → 0.3.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.
- {realtimestt-0.3.2 → realtimestt-0.3.3}/PKG-INFO +2 -2
- {realtimestt-0.3.2 → realtimestt-0.3.3}/README.md +1 -1
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT/audio_recorder_client.py +33 -9
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT.egg-info/PKG-INFO +2 -2
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_server.py +38 -18
- {realtimestt-0.3.2 → realtimestt-0.3.3}/setup.py +1 -1
- {realtimestt-0.3.2 → realtimestt-0.3.3}/LICENSE +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT/__init__.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT/audio_recorder - Kopie.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT/audio_recorder.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT/audio_recorder_client - Kopie (2).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT/audio_recorder_client - Kopie (3).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT/audio_recorder_client - Kopie.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT.egg-info/SOURCES.txt +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT.egg-info/dependency_links.txt +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT.egg-info/entry_points.txt +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT.egg-info/requires.txt +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/RealtimeSTT.egg-info/top_level.txt +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/__init__.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/install_packages.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_cli_client - Kopie (2).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_cli_client - Kopie (3).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_cli_client - Kopie (4).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_cli_client - Kopie (5).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_cli_client - Kopie.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_cli_client.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_cli_client_one_channel.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_cli_client_two_channels.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_server - Kopie (2).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_server - Kopie (3).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_server - Kopie (4).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_server - Kopie (5).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_server - Kopie (6).py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_server - Kopie.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_server_one_channel.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/stt_server_two_channels.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/server/xstt_server.py +0 -0
- {realtimestt-0.3.2 → realtimestt-0.3.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: RealtimeSTT
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: A fast Voice Activity Detection and Transcription System
|
|
5
5
|
Home-page: https://github.com/KoljaB/RealTimeSTT
|
|
6
6
|
Author: Kolja Beigel
|
|
@@ -55,7 +55,7 @@ https://github.com/user-attachments/assets/797e6552-27cd-41b1-a7f3-e5cbc72094f5
|
|
|
55
55
|
|
|
56
56
|
### Updates
|
|
57
57
|
|
|
58
|
-
Latest Version: v0.3.
|
|
58
|
+
Latest Version: v0.3.3
|
|
59
59
|
|
|
60
60
|
See [release history](https://github.com/KoljaB/RealtimeSTT/releases).
|
|
61
61
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
log_outgoing_chunks = False
|
|
2
|
+
debug_mode = False
|
|
2
3
|
|
|
3
4
|
from typing import Iterable, List, Optional, Union
|
|
4
5
|
from urllib.parse import urlparse
|
|
6
|
+
from datetime import datetime
|
|
5
7
|
import subprocess
|
|
6
8
|
import websocket
|
|
7
9
|
import threading
|
|
@@ -44,6 +46,18 @@ INIT_HANDLE_BUFFER_OVERFLOW = False
|
|
|
44
46
|
if platform.system() != 'Darwin':
|
|
45
47
|
INIT_HANDLE_BUFFER_OVERFLOW = True
|
|
46
48
|
|
|
49
|
+
# Define ANSI color codes for terminal output
|
|
50
|
+
class bcolors:
|
|
51
|
+
HEADER = '\033[95m' # Magenta
|
|
52
|
+
OKBLUE = '\033[94m' # Blue
|
|
53
|
+
OKCYAN = '\033[96m' # Cyan
|
|
54
|
+
OKGREEN = '\033[92m' # Green
|
|
55
|
+
WARNING = '\033[93m' # Yellow
|
|
56
|
+
FAIL = '\033[91m' # Red
|
|
57
|
+
ENDC = '\033[0m' # Reset to default
|
|
58
|
+
BOLD = '\033[1m'
|
|
59
|
+
UNDERLINE = '\033[4m'
|
|
60
|
+
|
|
47
61
|
class AudioToTextRecorderClient:
|
|
48
62
|
"""
|
|
49
63
|
A class responsible for capturing audio from the microphone, detecting
|
|
@@ -241,10 +255,10 @@ class AudioToTextRecorderClient:
|
|
|
241
255
|
if self.final_text_ready.wait(timeout=wait_interval):
|
|
242
256
|
break # Break if transcription is ready
|
|
243
257
|
|
|
244
|
-
if not self.realtime_text == self.submitted_realtime_text:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
258
|
+
# if not self.realtime_text == self.submitted_realtime_text:
|
|
259
|
+
# if self.on_realtime_transcription_update:
|
|
260
|
+
# self.on_realtime_transcription_update(self.realtime_text)
|
|
261
|
+
# self.submitted_realtime_text = self.realtime_text
|
|
248
262
|
|
|
249
263
|
total_wait_time += wait_interval
|
|
250
264
|
|
|
@@ -287,8 +301,6 @@ class AudioToTextRecorderClient:
|
|
|
287
301
|
Set the microphone on or off.
|
|
288
302
|
"""
|
|
289
303
|
self.muted = not microphone_on
|
|
290
|
-
#self.call_method("set_microphone", [microphone_on])
|
|
291
|
-
# self.use_microphone.value = microphone_on
|
|
292
304
|
|
|
293
305
|
def abort(self):
|
|
294
306
|
self.call_method("abort")
|
|
@@ -372,8 +384,6 @@ class AudioToTextRecorderClient:
|
|
|
372
384
|
args += ['--beam_size', str(self.beam_size)]
|
|
373
385
|
if self.beam_size_realtime is not None:
|
|
374
386
|
args += ['--beam_size_realtime', str(self.beam_size_realtime)]
|
|
375
|
-
if self.initial_prompt:
|
|
376
|
-
args += ['--initial_prompt', self.initial_prompt]
|
|
377
387
|
if self.wake_words is not None:
|
|
378
388
|
args += ['--wake_words', str(self.wake_words)]
|
|
379
389
|
if self.wake_words_sensitivity is not None:
|
|
@@ -403,11 +413,15 @@ class AudioToTextRecorderClient:
|
|
|
403
413
|
parsed_data_url = urlparse(self.data_url)
|
|
404
414
|
if parsed_data_url.port:
|
|
405
415
|
args += ['--data_port', str(parsed_data_url.port)]
|
|
416
|
+
if self.initial_prompt:
|
|
417
|
+
sanitized_prompt = self.initial_prompt.replace("\n", "\\n")
|
|
418
|
+
args += ['--initial_prompt', sanitized_prompt]
|
|
406
419
|
|
|
407
420
|
# Start the subprocess with the mapped arguments
|
|
408
421
|
if os.name == 'nt': # Windows
|
|
409
422
|
cmd = 'start /min cmd /c ' + subprocess.list2cmdline(args)
|
|
410
|
-
|
|
423
|
+
if debug_mode:
|
|
424
|
+
print(f"Opening server with cli command: {cmd}")
|
|
411
425
|
subprocess.Popen(cmd, shell=True)
|
|
412
426
|
else: # Unix-like systems
|
|
413
427
|
subprocess.Popen(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
|
|
@@ -570,6 +584,16 @@ class AudioToTextRecorderClient:
|
|
|
570
584
|
if data['text'] != self.realtime_text:
|
|
571
585
|
self.realtime_text = data['text']
|
|
572
586
|
|
|
587
|
+
timestamp = datetime.now().strftime('%H:%M:%S.%f')[:-3]
|
|
588
|
+
print(f"Realtime text [{timestamp}]: {bcolors.OKCYAN}{self.realtime_text}{bcolors.ENDC}")
|
|
589
|
+
|
|
590
|
+
if self.on_realtime_transcription_update:
|
|
591
|
+
# Call the callback in a new thread to avoid blocking
|
|
592
|
+
threading.Thread(
|
|
593
|
+
target=self.on_realtime_transcription_update,
|
|
594
|
+
args=(self.realtime_text,)
|
|
595
|
+
).start()
|
|
596
|
+
|
|
573
597
|
# Handle full sentences
|
|
574
598
|
elif data.get('type') == 'fullSentence':
|
|
575
599
|
self.final_text = data['text']
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: RealtimeSTT
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: A fast Voice Activity Detection and Transcription System
|
|
5
5
|
Home-page: https://github.com/KoljaB/RealTimeSTT
|
|
6
6
|
Author: Kolja Beigel
|
|
@@ -55,7 +55,7 @@ https://github.com/user-attachments/assets/797e6552-27cd-41b1-a7f3-e5cbc72094f5
|
|
|
55
55
|
|
|
56
56
|
### Updates
|
|
57
57
|
|
|
58
|
-
Latest Version: v0.3.
|
|
58
|
+
Latest Version: v0.3.3
|
|
59
59
|
|
|
60
60
|
See [release history](https://github.com/KoljaB/RealtimeSTT/releases).
|
|
61
61
|
|
|
@@ -69,8 +69,11 @@ The server will broadcast real-time transcription updates to all connected clien
|
|
|
69
69
|
extended_logging = True
|
|
70
70
|
send_recorded_chunk = False
|
|
71
71
|
log_incoming_chunks = False
|
|
72
|
+
stt_optimizations = False
|
|
72
73
|
|
|
73
74
|
|
|
75
|
+
from .install_packages import check_and_install_packages
|
|
76
|
+
from datetime import datetime
|
|
74
77
|
import asyncio
|
|
75
78
|
import base64
|
|
76
79
|
import sys
|
|
@@ -78,7 +81,6 @@ import sys
|
|
|
78
81
|
if sys.platform == 'win32':
|
|
79
82
|
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
|
80
83
|
|
|
81
|
-
from .install_packages import check_and_install_packages
|
|
82
84
|
|
|
83
85
|
check_and_install_packages([
|
|
84
86
|
{
|
|
@@ -177,13 +179,14 @@ def text_detected(text, loop):
|
|
|
177
179
|
|
|
178
180
|
text = preprocess_text(text)
|
|
179
181
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
182
|
+
if stt_optimizations:
|
|
183
|
+
sentence_end_marks = ['.', '!', '?', '。']
|
|
184
|
+
if text.endswith("..."):
|
|
185
|
+
recorder.post_speech_silence_duration = global_args.mid_sentence_detection_pause
|
|
186
|
+
elif text and text[-1] in sentence_end_marks and prev_text and prev_text[-1] in sentence_end_marks:
|
|
187
|
+
recorder.post_speech_silence_duration = global_args.end_of_sentence_detection_pause
|
|
188
|
+
else:
|
|
189
|
+
recorder.post_speech_silence_duration = global_args.unknown_sentence_detection_pause
|
|
187
190
|
|
|
188
191
|
prev_text = text
|
|
189
192
|
|
|
@@ -193,10 +196,14 @@ def text_detected(text, loop):
|
|
|
193
196
|
'text': text
|
|
194
197
|
})
|
|
195
198
|
asyncio.run_coroutine_threadsafe(audio_queue.put(message), loop)
|
|
199
|
+
|
|
200
|
+
# Get current timestamp in HH:MM:SS.nnn format
|
|
201
|
+
timestamp = datetime.now().strftime('%H:%M:%S.%f')[:-3]
|
|
202
|
+
|
|
196
203
|
if extended_logging:
|
|
197
|
-
print(f"Realtime text: {bcolors.OKCYAN}{text}{bcolors.ENDC}\n", flush=True, end="")
|
|
204
|
+
print(f" [{timestamp}] Realtime text: {bcolors.OKCYAN}{text}{bcolors.ENDC}\n", flush=True, end="")
|
|
198
205
|
else:
|
|
199
|
-
print(f"\r{bcolors.OKCYAN}{text}{bcolors.ENDC}", flush=True, end='')
|
|
206
|
+
print(f"\r[{timestamp}] {bcolors.OKCYAN}{text}{bcolors.ENDC}", flush=True, end='')
|
|
200
207
|
|
|
201
208
|
def on_recording_start(loop):
|
|
202
209
|
# Send a message to the client indicating recording has started
|
|
@@ -348,7 +355,7 @@ def parse_arguments():
|
|
|
348
355
|
parser.add_argument('--wake_word_timeout', type=float, default=5.0,
|
|
349
356
|
help='Maximum time in seconds that the system will wait for a wake word before timing out. After this timeout, the system stops listening for wake words until reactivated. Default is 5.0 seconds.')
|
|
350
357
|
|
|
351
|
-
parser.add_argument('--wake_word_activation_delay', type=float, default=
|
|
358
|
+
parser.add_argument('--wake_word_activation_delay', type=float, default=20,
|
|
352
359
|
help='The delay in seconds before the wake word detection is activated after the system starts listening. This prevents false positives during the start of a session. Default is 0.5 seconds.')
|
|
353
360
|
|
|
354
361
|
parser.add_argument('--wakeword_backend', type=str, default='pvporcupine',
|
|
@@ -369,8 +376,14 @@ def parse_arguments():
|
|
|
369
376
|
parser.add_argument('--use_extended_logging', action='store_true',
|
|
370
377
|
help='Writes extensive log messages for the recording worker, that processes the audio chunks.')
|
|
371
378
|
|
|
379
|
+
# Parse arguments
|
|
380
|
+
args = parser.parse_args()
|
|
381
|
+
|
|
382
|
+
# Replace escaped newlines with actual newlines in initial_prompt
|
|
383
|
+
if args.initial_prompt:
|
|
384
|
+
args.initial_prompt = args.initial_prompt.replace("\\n", "\n")
|
|
372
385
|
|
|
373
|
-
return
|
|
386
|
+
return args
|
|
374
387
|
|
|
375
388
|
def _recorder_thread(loop):
|
|
376
389
|
global recorder, prev_text, stop_recorder
|
|
@@ -390,10 +403,12 @@ def _recorder_thread(loop):
|
|
|
390
403
|
# Use the passed event loop here
|
|
391
404
|
asyncio.run_coroutine_threadsafe(audio_queue.put(message), loop)
|
|
392
405
|
|
|
406
|
+
timestamp = datetime.now().strftime('%H:%M:%S.%f')[:-3]
|
|
407
|
+
|
|
393
408
|
if extended_logging:
|
|
394
|
-
print(f"Full text: {bcolors.BOLD}Sentence:{bcolors.ENDC} {bcolors.OKGREEN}{full_sentence}{bcolors.ENDC}")
|
|
409
|
+
print(f" [{timestamp}] Full text: {bcolors.BOLD}Sentence:{bcolors.ENDC} {bcolors.OKGREEN}{full_sentence}{bcolors.ENDC}\n", flush=True, end="")
|
|
395
410
|
else:
|
|
396
|
-
print(f"\r{bcolors.BOLD}Sentence:{bcolors.ENDC} {bcolors.OKGREEN}{full_sentence}{bcolors.ENDC}\n")
|
|
411
|
+
print(f"\r[{timestamp}] {bcolors.BOLD}Sentence:{bcolors.ENDC} {bcolors.OKGREEN}{full_sentence}{bcolors.ENDC}\n")
|
|
397
412
|
try:
|
|
398
413
|
while not stop_recorder:
|
|
399
414
|
recorder.text(process_text)
|
|
@@ -445,8 +460,9 @@ async def control_handler(websocket, path):
|
|
|
445
460
|
value_formatted = f"{value:.2f}"
|
|
446
461
|
else:
|
|
447
462
|
value_formatted = value
|
|
463
|
+
timestamp = datetime.now().strftime('%H:%M:%S.%f')[:-3]
|
|
448
464
|
if extended_logging:
|
|
449
|
-
print(f"{bcolors.OKGREEN}Set recorder.{parameter} to: {bcolors.OKBLUE}{value_formatted}{bcolors.ENDC}")
|
|
465
|
+
print(f" [{timestamp}] {bcolors.OKGREEN}Set recorder.{parameter} to: {bcolors.OKBLUE}{value_formatted}{bcolors.ENDC}")
|
|
450
466
|
# Optionally send a response back to the client
|
|
451
467
|
await websocket.send(json.dumps({"status": "success", "message": f"Parameter {parameter} set to {value}"}))
|
|
452
468
|
else:
|
|
@@ -469,8 +485,9 @@ async def control_handler(websocket, path):
|
|
|
469
485
|
|
|
470
486
|
value_truncated = value_formatted[:39] + "…" if len(value_formatted) > 40 else value_formatted
|
|
471
487
|
|
|
488
|
+
timestamp = datetime.now().strftime('%H:%M:%S.%f')[:-3]
|
|
472
489
|
if extended_logging:
|
|
473
|
-
print(f"{bcolors.OKGREEN}Get recorder.{parameter}: {bcolors.OKBLUE}{value_truncated}{bcolors.ENDC}")
|
|
490
|
+
print(f" [{timestamp}] {bcolors.OKGREEN}Get recorder.{parameter}: {bcolors.OKBLUE}{value_truncated}{bcolors.ENDC}")
|
|
474
491
|
response = {"status": "success", "parameter": parameter, "value": value}
|
|
475
492
|
if request_id is not None:
|
|
476
493
|
response["request_id"] = request_id
|
|
@@ -490,7 +507,8 @@ async def control_handler(websocket, path):
|
|
|
490
507
|
args = command_data.get("args", [])
|
|
491
508
|
kwargs = command_data.get("kwargs", {})
|
|
492
509
|
method(*args, **kwargs)
|
|
493
|
-
|
|
510
|
+
timestamp = datetime.now().strftime('%H:%M:%S.%f')[:-3]
|
|
511
|
+
print(f" [{timestamp}] {bcolors.OKGREEN}Called method recorder.{bcolors.OKBLUE}{method_name}{bcolors.ENDC}")
|
|
494
512
|
await websocket.send(json.dumps({"status": "success", "message": f"Method {method_name} called"}))
|
|
495
513
|
else:
|
|
496
514
|
print(f"{bcolors.WARNING}Recorder does not have method {method_name}{bcolors.ENDC}")
|
|
@@ -541,8 +559,10 @@ async def broadcast_audio_messages():
|
|
|
541
559
|
message = await audio_queue.get()
|
|
542
560
|
for conn in list(data_connections):
|
|
543
561
|
try:
|
|
562
|
+
timestamp = datetime.now().strftime('%H:%M:%S.%f')[:-3]
|
|
563
|
+
|
|
544
564
|
if extended_logging:
|
|
545
|
-
print(f"
|
|
565
|
+
print(f" [{timestamp}] Sending message: {bcolors.OKBLUE}{message}{bcolors.ENDC}\n", flush=True, end="")
|
|
546
566
|
await conn.send(message)
|
|
547
567
|
except websockets.exceptions.ConnectionClosed:
|
|
548
568
|
data_connections.remove(conn)
|
|
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
|
|
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
|