RealTimeSTT 0.3.100__tar.gz → 0.3.101__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.100/realtimestt.egg-info → realtimestt-0.3.101}/PKG-INFO +3 -4
- {realtimestt-0.3.100 → realtimestt-0.3.101}/RealtimeSTT/audio_recorder.py +69 -37
- {realtimestt-0.3.100 → realtimestt-0.3.101}/RealtimeSTT/audio_recorder_client.py +17 -9
- {realtimestt-0.3.100 → realtimestt-0.3.101}/RealtimeSTT_server/stt_server.py +4 -9
- {realtimestt-0.3.100 → realtimestt-0.3.101/realtimestt.egg-info}/PKG-INFO +3 -4
- {realtimestt-0.3.100 → realtimestt-0.3.101}/realtimestt.egg-info/requires.txt +2 -3
- {realtimestt-0.3.100 → realtimestt-0.3.101}/requirements.txt +2 -3
- {realtimestt-0.3.100 → realtimestt-0.3.101}/setup.py +1 -1
- {realtimestt-0.3.100 → realtimestt-0.3.101}/LICENSE +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/MANIFEST.in +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/README.md +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/RealtimeSTT/__init__.py +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/RealtimeSTT/audio_input.py +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/RealtimeSTT/warmup_audio.wav +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/RealtimeSTT_server/__init__.py +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/RealtimeSTT_server/install_packages.py +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/RealtimeSTT_server/stt_cli_client.py +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/realtimestt.egg-info/SOURCES.txt +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/realtimestt.egg-info/dependency_links.txt +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/realtimestt.egg-info/entry_points.txt +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/realtimestt.egg-info/top_level.txt +0 -0
- {realtimestt-0.3.100 → realtimestt-0.3.101}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: realtimestt
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.101
|
|
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
|
|
@@ -17,11 +17,10 @@ Requires-Dist: webrtcvad-wheels==2.0.14
|
|
|
17
17
|
Requires-Dist: halo==0.0.31
|
|
18
18
|
Requires-Dist: torch
|
|
19
19
|
Requires-Dist: torchaudio
|
|
20
|
-
Requires-Dist: scipy==1.15.
|
|
20
|
+
Requires-Dist: scipy==1.15.2
|
|
21
21
|
Requires-Dist: openwakeword>=0.4.0
|
|
22
|
-
Requires-Dist: websockets==
|
|
22
|
+
Requires-Dist: websockets==15.0.1
|
|
23
23
|
Requires-Dist: websocket-client==1.8.0
|
|
24
|
-
Requires-Dist: numpy<2.0.0
|
|
25
24
|
Requires-Dist: soundfile==0.13.1
|
|
26
25
|
Dynamic: author
|
|
27
26
|
Dynamic: author-email
|
|
@@ -279,7 +279,7 @@ class AudioToTextRecorder:
|
|
|
279
279
|
on_vad_detect_stop=None,
|
|
280
280
|
|
|
281
281
|
# Wake word parameters
|
|
282
|
-
wakeword_backend: str = "
|
|
282
|
+
wakeword_backend: str = "",
|
|
283
283
|
openwakeword_model_paths: str = None,
|
|
284
284
|
openwakeword_inference_framework: str = "onnx",
|
|
285
285
|
wake_words: str = "",
|
|
@@ -641,6 +641,7 @@ class AudioToTextRecorder:
|
|
|
641
641
|
self.early_transcription_on_silence = early_transcription_on_silence
|
|
642
642
|
self.use_extended_logging = use_extended_logging
|
|
643
643
|
self.faster_whisper_vad_filter = faster_whisper_vad_filter
|
|
644
|
+
self.awaiting_speech_end = False
|
|
644
645
|
|
|
645
646
|
# ----------------------------------------------------------------------------
|
|
646
647
|
# Named logger configuration
|
|
@@ -771,7 +772,7 @@ class AudioToTextRecorder:
|
|
|
771
772
|
"transcription model initialized successfully")
|
|
772
773
|
|
|
773
774
|
# Setup wake word detection
|
|
774
|
-
if wake_words or wakeword_backend in {'oww', 'openwakeword', 'openwakewords'}:
|
|
775
|
+
if wake_words or wakeword_backend in {'oww', 'openwakeword', 'openwakewords', 'pvp', 'pvporcupine'}:
|
|
775
776
|
self.wakeword_backend = wakeword_backend
|
|
776
777
|
|
|
777
778
|
self.wake_words_list = [
|
|
@@ -1439,41 +1440,15 @@ class AudioToTextRecorder:
|
|
|
1439
1440
|
self.shutdown()
|
|
1440
1441
|
raise # Re-raise the exception after cleanup
|
|
1441
1442
|
|
|
1442
|
-
def transcribe(self):
|
|
1443
|
-
"""
|
|
1444
|
-
Transcribes audio captured by this class instance using the
|
|
1445
|
-
`faster_whisper` model.
|
|
1446
|
-
|
|
1447
|
-
Automatically starts recording upon voice activity if not manually
|
|
1448
|
-
started using `recorder.start()`.
|
|
1449
|
-
Automatically stops recording upon voice deactivity if not manually
|
|
1450
|
-
stopped with `recorder.stop()`.
|
|
1451
|
-
Processes the recorded audio to generate transcription.
|
|
1452
|
-
|
|
1453
|
-
Args:
|
|
1454
|
-
on_transcription_finished (callable, optional): Callback function
|
|
1455
|
-
to be executed when transcription is ready.
|
|
1456
|
-
If provided, transcription will be performed asynchronously,
|
|
1457
|
-
and the callback will receive the transcription as its argument.
|
|
1458
|
-
If omitted, the transcription will be performed synchronously,
|
|
1459
|
-
and the result will be returned.
|
|
1460
1443
|
|
|
1461
|
-
|
|
1462
|
-
str: The transcription of the recorded audio.
|
|
1463
|
-
|
|
1464
|
-
Raises:
|
|
1465
|
-
Exception: If there is an error during the transcription process.
|
|
1466
|
-
"""
|
|
1467
|
-
self._set_state("transcribing")
|
|
1468
|
-
audio_copy = copy.deepcopy(self.audio)
|
|
1444
|
+
def perform_final_transcription(self, audio_bytes=None):
|
|
1469
1445
|
start_time = 0
|
|
1470
1446
|
with self.transcription_lock:
|
|
1471
|
-
|
|
1472
1447
|
try:
|
|
1473
1448
|
if self.transcribe_count == 0:
|
|
1474
1449
|
logger.debug("Adding transcription request, no early transcription started")
|
|
1475
1450
|
start_time = time.time() # Start timing
|
|
1476
|
-
self.parent_transcription_pipe.send((
|
|
1451
|
+
self.parent_transcription_pipe.send((audio_bytes, self.language))
|
|
1477
1452
|
self.transcribe_count += 1
|
|
1478
1453
|
|
|
1479
1454
|
while self.transcribe_count > 0:
|
|
@@ -1493,7 +1468,7 @@ class AudioToTextRecorder:
|
|
|
1493
1468
|
segments, info = result
|
|
1494
1469
|
self.detected_language = info.language if info.language_probability > 0 else None
|
|
1495
1470
|
self.detected_language_probability = info.language_probability
|
|
1496
|
-
self.last_transcription_bytes = copy.deepcopy(
|
|
1471
|
+
self.last_transcription_bytes = copy.deepcopy(audio_bytes)
|
|
1497
1472
|
self.last_transcription_bytes_b64 = base64.b64encode(self.last_transcription_bytes.tobytes()).decode('utf-8')
|
|
1498
1473
|
transcription = self._preprocess_output(segments)
|
|
1499
1474
|
end_time = time.time() # End timing
|
|
@@ -1512,6 +1487,43 @@ class AudioToTextRecorder:
|
|
|
1512
1487
|
logger.error(f"Error during transcription: {str(e)}", exc_info=True)
|
|
1513
1488
|
raise e
|
|
1514
1489
|
|
|
1490
|
+
|
|
1491
|
+
def transcribe(self):
|
|
1492
|
+
"""
|
|
1493
|
+
Transcribes audio captured by this class instance using the
|
|
1494
|
+
`faster_whisper` model.
|
|
1495
|
+
|
|
1496
|
+
Automatically starts recording upon voice activity if not manually
|
|
1497
|
+
started using `recorder.start()`.
|
|
1498
|
+
Automatically stops recording upon voice deactivity if not manually
|
|
1499
|
+
stopped with `recorder.stop()`.
|
|
1500
|
+
Processes the recorded audio to generate transcription.
|
|
1501
|
+
|
|
1502
|
+
Args:
|
|
1503
|
+
on_transcription_finished (callable, optional): Callback function
|
|
1504
|
+
to be executed when transcription is ready.
|
|
1505
|
+
If provided, transcription will be performed asynchronously,
|
|
1506
|
+
and the callback will receive the transcription as its argument.
|
|
1507
|
+
If omitted, the transcription will be performed synchronously,
|
|
1508
|
+
and the result will be returned.
|
|
1509
|
+
|
|
1510
|
+
Returns (if no callback is set):
|
|
1511
|
+
str: The transcription of the recorded audio.
|
|
1512
|
+
|
|
1513
|
+
Raises:
|
|
1514
|
+
Exception: If there is an error during the transcription process.
|
|
1515
|
+
"""
|
|
1516
|
+
audio_copy = copy.deepcopy(self.audio)
|
|
1517
|
+
self._set_state("transcribing")
|
|
1518
|
+
if self.on_transcription_start:
|
|
1519
|
+
abort_value = self.on_transcription_start(audio_copy)
|
|
1520
|
+
if not abort_value:
|
|
1521
|
+
return self.perform_final_transcription(audio_copy)
|
|
1522
|
+
return None
|
|
1523
|
+
else:
|
|
1524
|
+
return self.perform_final_transcription(audio_copy)
|
|
1525
|
+
|
|
1526
|
+
|
|
1515
1527
|
def _process_wakeword(self, data):
|
|
1516
1528
|
"""
|
|
1517
1529
|
Processes audio data to detect wake words.
|
|
@@ -2084,6 +2096,7 @@ class AudioToTextRecorder:
|
|
|
2084
2096
|
(time.time() - self.recording_start_time > self.min_length_of_recording):
|
|
2085
2097
|
|
|
2086
2098
|
self.speech_end_silence_start = time.time()
|
|
2099
|
+
self.awaiting_speech_end = True
|
|
2087
2100
|
|
|
2088
2101
|
if self.use_extended_logging:
|
|
2089
2102
|
logger.debug('Debug: Checking early transcription conditions')
|
|
@@ -2104,6 +2117,7 @@ class AudioToTextRecorder:
|
|
|
2104
2117
|
self.allowed_to_early_transcribe = False
|
|
2105
2118
|
|
|
2106
2119
|
else:
|
|
2120
|
+
self.awaiting_speech_end = False
|
|
2107
2121
|
if self.use_extended_logging:
|
|
2108
2122
|
logger.debug('Debug: Handling speech detection')
|
|
2109
2123
|
if self.speech_end_silence_start:
|
|
@@ -2118,6 +2132,7 @@ class AudioToTextRecorder:
|
|
|
2118
2132
|
if self.speech_end_silence_start and time.time() - \
|
|
2119
2133
|
self.speech_end_silence_start >= \
|
|
2120
2134
|
self.post_speech_silence_duration:
|
|
2135
|
+
|
|
2121
2136
|
if self.on_vad_stop:
|
|
2122
2137
|
self.on_vad_stop()
|
|
2123
2138
|
|
|
@@ -2151,6 +2166,8 @@ class AudioToTextRecorder:
|
|
|
2151
2166
|
logger.debug('Debug: Setting failed_stop_attempt to True')
|
|
2152
2167
|
failed_stop_attempt = True
|
|
2153
2168
|
|
|
2169
|
+
self.awaiting_speech_end = False
|
|
2170
|
+
|
|
2154
2171
|
if self.use_extended_logging:
|
|
2155
2172
|
logger.debug('Debug: Checking if recording stopped')
|
|
2156
2173
|
if not self.is_recording and was_recording:
|
|
@@ -2206,6 +2223,8 @@ class AudioToTextRecorder:
|
|
|
2206
2223
|
logger.debug('Debug: Exiting _recording_worker method')
|
|
2207
2224
|
|
|
2208
2225
|
|
|
2226
|
+
|
|
2227
|
+
|
|
2209
2228
|
def _realtime_worker(self):
|
|
2210
2229
|
"""
|
|
2211
2230
|
Performs real-time transcription if the feature is enabled.
|
|
@@ -2225,14 +2244,29 @@ class AudioToTextRecorder:
|
|
|
2225
2244
|
if not self.enable_realtime_transcription:
|
|
2226
2245
|
return
|
|
2227
2246
|
|
|
2228
|
-
#
|
|
2247
|
+
# Track time of last transcription
|
|
2248
|
+
last_transcription_time = time.time()
|
|
2249
|
+
|
|
2229
2250
|
while self.is_running:
|
|
2230
2251
|
|
|
2231
|
-
# Check if the recording is active
|
|
2232
2252
|
if self.is_recording:
|
|
2233
2253
|
|
|
2234
|
-
#
|
|
2235
|
-
|
|
2254
|
+
# MODIFIED SLEEP LOGIC:
|
|
2255
|
+
# Wait until realtime_processing_pause has elapsed,
|
|
2256
|
+
# but check often so we can respond to changes quickly.
|
|
2257
|
+
while (
|
|
2258
|
+
time.time() - last_transcription_time
|
|
2259
|
+
) < self.realtime_processing_pause:
|
|
2260
|
+
time.sleep(0.001)
|
|
2261
|
+
if not self.is_running or not self.is_recording:
|
|
2262
|
+
break
|
|
2263
|
+
|
|
2264
|
+
if self.awaiting_speech_end:
|
|
2265
|
+
time.sleep(0.001)
|
|
2266
|
+
continue
|
|
2267
|
+
|
|
2268
|
+
# Update transcription time
|
|
2269
|
+
last_transcription_time = time.time()
|
|
2236
2270
|
|
|
2237
2271
|
# Convert the buffer frames to a NumPy array
|
|
2238
2272
|
audio_array = np.frombuffer(
|
|
@@ -2557,8 +2591,6 @@ class AudioToTextRecorder:
|
|
|
2557
2591
|
if self.spinner and self.halo:
|
|
2558
2592
|
self.halo._interval = 500
|
|
2559
2593
|
elif new_state == "transcribing":
|
|
2560
|
-
if self.on_transcription_start:
|
|
2561
|
-
self.on_transcription_start()
|
|
2562
2594
|
self._set_spinner("transcribing")
|
|
2563
2595
|
if self.spinner and self.halo:
|
|
2564
2596
|
self.halo._interval = 50
|
|
@@ -257,10 +257,13 @@ class AudioToTextRecorderClient:
|
|
|
257
257
|
|
|
258
258
|
|
|
259
259
|
if self.server_already_running:
|
|
260
|
-
self.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
260
|
+
if not self.connection_established.wait(timeout=10):
|
|
261
|
+
print("Server connection not established within 10 seconds.")
|
|
262
|
+
else:
|
|
263
|
+
self.set_parameter("language", self.language)
|
|
264
|
+
print(f"Language set to {self.language}")
|
|
265
|
+
self.set_parameter("wake_word_activation_delay", self.wake_word_activation_delay)
|
|
266
|
+
print(f"Wake word activation delay set to {self.wake_word_activation_delay}")
|
|
264
267
|
|
|
265
268
|
def text(self, on_transcription_finished=None):
|
|
266
269
|
self.realtime_text = ""
|
|
@@ -490,11 +493,16 @@ class AudioToTextRecorderClient:
|
|
|
490
493
|
print("STT server start command issued. Please wait a moment for it to initialize.", file=sys.stderr)
|
|
491
494
|
|
|
492
495
|
def is_server_running(self):
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
496
|
+
try:
|
|
497
|
+
# Attempt a proper WebSocket handshake to the control URL.
|
|
498
|
+
from websocket import create_connection
|
|
499
|
+
ws = create_connection(self.control_url, timeout=3)
|
|
500
|
+
ws.close()
|
|
501
|
+
return True
|
|
502
|
+
except Exception as e:
|
|
503
|
+
if self.debug_mode:
|
|
504
|
+
print(f"Server connectivity check failed: {e}")
|
|
505
|
+
return False
|
|
498
506
|
|
|
499
507
|
def ensure_server_running(self):
|
|
500
508
|
if not self.is_server_running():
|
|
@@ -290,14 +290,12 @@ def text_detected(text, loop):
|
|
|
290
290
|
print(f"\r[{timestamp}] {bcolors.OKCYAN}{text}{bcolors.ENDC}", flush=True, end='')
|
|
291
291
|
|
|
292
292
|
def on_recording_start(loop):
|
|
293
|
-
# Send a message to the client indicating recording has started
|
|
294
293
|
message = json.dumps({
|
|
295
294
|
'type': 'recording_start'
|
|
296
295
|
})
|
|
297
296
|
asyncio.run_coroutine_threadsafe(audio_queue.put(message), loop)
|
|
298
297
|
|
|
299
298
|
def on_recording_stop(loop):
|
|
300
|
-
# Send a message to the client indicating recording has stopped
|
|
301
299
|
message = json.dumps({
|
|
302
300
|
'type': 'recording_stop'
|
|
303
301
|
})
|
|
@@ -316,28 +314,24 @@ def on_vad_detect_stop(loop):
|
|
|
316
314
|
asyncio.run_coroutine_threadsafe(audio_queue.put(message), loop)
|
|
317
315
|
|
|
318
316
|
def on_wakeword_detected(loop):
|
|
319
|
-
# Send a message to the client when wake word detection starts
|
|
320
317
|
message = json.dumps({
|
|
321
318
|
'type': 'wakeword_detected'
|
|
322
319
|
})
|
|
323
320
|
asyncio.run_coroutine_threadsafe(audio_queue.put(message), loop)
|
|
324
321
|
|
|
325
322
|
def on_wakeword_detection_start(loop):
|
|
326
|
-
# Send a message to the client when wake word detection starts
|
|
327
323
|
message = json.dumps({
|
|
328
324
|
'type': 'wakeword_detection_start'
|
|
329
325
|
})
|
|
330
326
|
asyncio.run_coroutine_threadsafe(audio_queue.put(message), loop)
|
|
331
327
|
|
|
332
328
|
def on_wakeword_detection_end(loop):
|
|
333
|
-
# Send a message to the client when wake word detection ends
|
|
334
329
|
message = json.dumps({
|
|
335
330
|
'type': 'wakeword_detection_end'
|
|
336
331
|
})
|
|
337
332
|
asyncio.run_coroutine_threadsafe(audio_queue.put(message), loop)
|
|
338
333
|
|
|
339
|
-
def on_transcription_start(loop):
|
|
340
|
-
# Send a message to the client when transcription starts
|
|
334
|
+
def on_transcription_start(_audio_bytes, loop):
|
|
341
335
|
message = json.dumps({
|
|
342
336
|
'type': 'transcription_start'
|
|
343
337
|
})
|
|
@@ -460,8 +454,8 @@ def parse_arguments():
|
|
|
460
454
|
parser.add_argument('--wake_word_timeout', type=float, default=5.0,
|
|
461
455
|
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.')
|
|
462
456
|
|
|
463
|
-
parser.add_argument('--wake_word_activation_delay', type=float, default=
|
|
464
|
-
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
|
|
457
|
+
parser.add_argument('--wake_word_activation_delay', type=float, default=0,
|
|
458
|
+
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 seconds.')
|
|
465
459
|
|
|
466
460
|
parser.add_argument('--wakeword_backend', type=str, default='none',
|
|
467
461
|
help='The backend used for wake word detection. You can specify different backends such as "default" or any custom implementations depending on your setup. Default is "pvporcupine".')
|
|
@@ -776,6 +770,7 @@ async def main_async():
|
|
|
776
770
|
'use_main_model_for_realtime': args.use_main_model_for_realtime,
|
|
777
771
|
'spinner': False,
|
|
778
772
|
'use_microphone': False,
|
|
773
|
+
|
|
779
774
|
'on_realtime_transcription_update': make_callback(loop, text_detected),
|
|
780
775
|
'on_recording_start': make_callback(loop, on_recording_start),
|
|
781
776
|
'on_recording_stop': make_callback(loop, on_recording_stop),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: realtimestt
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.101
|
|
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
|
|
@@ -17,11 +17,10 @@ Requires-Dist: webrtcvad-wheels==2.0.14
|
|
|
17
17
|
Requires-Dist: halo==0.0.31
|
|
18
18
|
Requires-Dist: torch
|
|
19
19
|
Requires-Dist: torchaudio
|
|
20
|
-
Requires-Dist: scipy==1.15.
|
|
20
|
+
Requires-Dist: scipy==1.15.2
|
|
21
21
|
Requires-Dist: openwakeword>=0.4.0
|
|
22
|
-
Requires-Dist: websockets==
|
|
22
|
+
Requires-Dist: websockets==15.0.1
|
|
23
23
|
Requires-Dist: websocket-client==1.8.0
|
|
24
|
-
Requires-Dist: numpy<2.0.0
|
|
25
24
|
Requires-Dist: soundfile==0.13.1
|
|
26
25
|
Dynamic: author
|
|
27
26
|
Dynamic: author-email
|
|
@@ -14,7 +14,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
14
14
|
|
|
15
15
|
setuptools.setup(
|
|
16
16
|
name="realtimestt",
|
|
17
|
-
version="0.3.
|
|
17
|
+
version="0.3.101",
|
|
18
18
|
author="Kolja Beigel",
|
|
19
19
|
author_email="kolja.beigel@web.de",
|
|
20
20
|
description="A fast Voice Activity Detection and Transcription System",
|
|
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
|