RealTimeSTT 0.1.6__tar.gz → 0.1.7__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RealTimeSTT
3
- Version: 0.1.6
3
+ Version: 0.1.7
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
@@ -16,8 +16,8 @@ Requires-Dist: faster-whisper>=0.7.1
16
16
  Requires-Dist: pvporcupine==1.9.5
17
17
  Requires-Dist: webrtcvad>=2.0.10
18
18
  Requires-Dist: halo>=0.0.31
19
- Requires-Dist: torch==2.0.1
20
- Requires-Dist: torchaudio==2.0.2
19
+ Requires-Dist: torch>=2.0.1
20
+ Requires-Dist: torchaudio>=2.0.2
21
21
 
22
22
 
23
23
  # RealtimeSTT
@@ -37,9 +37,14 @@ https://github.com/KoljaB/RealtimeSTT/assets/7604638/207cb9a2-4482-48e7-9d2b-072
37
37
 
38
38
  ### Updates
39
39
 
40
+ #### v0.1.7
41
+ - Bugfix for Mac OS Installation (multiprocessing / queue.size())
42
+ - KeyboardInterrupt handling (now abortable with CTRL+C)
43
+ - Bugfix for spinner handling (could lead to exception in some cases)
44
+
40
45
  #### v0.1.6
41
- - implements context manager protocol (recorder can be used in a `with` statement)
42
- - bugfix in shutdown method
46
+ - Implements context manager protocol (recorder can be used in a `with` statement)
47
+ - Bugfix for resource management in shutdown method
43
48
 
44
49
  #### v0.1.5
45
50
 
@@ -16,9 +16,14 @@ https://github.com/KoljaB/RealtimeSTT/assets/7604638/207cb9a2-4482-48e7-9d2b-072
16
16
 
17
17
  ### Updates
18
18
 
19
+ #### v0.1.7
20
+ - Bugfix for Mac OS Installation (multiprocessing / queue.size())
21
+ - KeyboardInterrupt handling (now abortable with CTRL+C)
22
+ - Bugfix for spinner handling (could lead to exception in some cases)
23
+
19
24
  #### v0.1.6
20
- - implements context manager protocol (recorder can be used in a `with` statement)
21
- - bugfix in shutdown method
25
+ - Implements context manager protocol (recorder can be used in a `with` statement)
26
+ - Bugfix for resource management in shutdown method
22
27
 
23
28
  #### v0.1.5
24
29
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RealTimeSTT
3
- Version: 0.1.6
3
+ Version: 0.1.7
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
@@ -16,8 +16,8 @@ Requires-Dist: faster-whisper>=0.7.1
16
16
  Requires-Dist: pvporcupine==1.9.5
17
17
  Requires-Dist: webrtcvad>=2.0.10
18
18
  Requires-Dist: halo>=0.0.31
19
- Requires-Dist: torch==2.0.1
20
- Requires-Dist: torchaudio==2.0.2
19
+ Requires-Dist: torch>=2.0.1
20
+ Requires-Dist: torchaudio>=2.0.2
21
21
 
22
22
 
23
23
  # RealtimeSTT
@@ -37,9 +37,14 @@ https://github.com/KoljaB/RealtimeSTT/assets/7604638/207cb9a2-4482-48e7-9d2b-072
37
37
 
38
38
  ### Updates
39
39
 
40
+ #### v0.1.7
41
+ - Bugfix for Mac OS Installation (multiprocessing / queue.size())
42
+ - KeyboardInterrupt handling (now abortable with CTRL+C)
43
+ - Bugfix for spinner handling (could lead to exception in some cases)
44
+
40
45
  #### v0.1.6
41
- - implements context manager protocol (recorder can be used in a `with` statement)
42
- - bugfix in shutdown method
46
+ - Implements context manager protocol (recorder can be used in a `with` statement)
47
+ - Bugfix for resource management in shutdown method
43
48
 
44
49
  #### v0.1.5
45
50
 
@@ -3,5 +3,5 @@ faster-whisper>=0.7.1
3
3
  pvporcupine==1.9.5
4
4
  webrtcvad>=2.0.10
5
5
  halo>=0.0.31
6
- torch==2.0.1
7
- torchaudio==2.0.2
6
+ torch>=2.0.1
7
+ torchaudio>=2.0.2
@@ -20,7 +20,7 @@ Author: Kolja Beigel
20
20
 
21
21
  """
22
22
 
23
- from multiprocessing import Process, Pipe, Queue, Event
23
+ from multiprocessing import Process, Pipe, Event, Manager
24
24
  import faster_whisper
25
25
  import collections
26
26
  import numpy as np
@@ -172,7 +172,8 @@ class AudioToTextRecorder:
172
172
  self.allowed_latency_limit = ALLOWED_LATENCY_LIMIT
173
173
 
174
174
  self.level = level
175
- self.audio_queue = Queue()
175
+ manager = Manager()
176
+ self.audio_queue = manager.Queue()
176
177
  self.buffer_size = BUFFER_SIZE
177
178
  self.sample_rate = SAMPLE_RATE
178
179
  self.recording_start_time = 0
@@ -228,13 +229,14 @@ class AudioToTextRecorder:
228
229
  logging.info(f"Starting RealTimeSTT")
229
230
 
230
231
  # Start transcription process
232
+ self.interrupt_stop_event = Event()
231
233
  self.main_transcription_ready_event = Event()
232
234
  self.parent_transcription_pipe, child_transcription_pipe = Pipe()
233
- self.transcript_process = Process(target=AudioToTextRecorder._transcription_worker, args=(child_transcription_pipe, model, self.main_transcription_ready_event, self.shutdown_event))
235
+ self.transcript_process = Process(target=AudioToTextRecorder._transcription_worker, args=(child_transcription_pipe, model, self.main_transcription_ready_event, self.shutdown_event, self.interrupt_stop_event))
234
236
  self.transcript_process.start()
235
237
 
236
238
  # Start audio data reading process
237
- self.reader_process = Process(target=AudioToTextRecorder._audio_data_worker, args=(self.audio_queue, self.sample_rate, self.buffer_size, self.shutdown_event))
239
+ self.reader_process = Process(target=AudioToTextRecorder._audio_data_worker, args=(self.audio_queue, self.sample_rate, self.buffer_size, self.shutdown_event, self.interrupt_stop_event))
238
240
  self.reader_process.start()
239
241
 
240
242
  # Initialize the realtime transcription model
@@ -325,7 +327,7 @@ class AudioToTextRecorder:
325
327
 
326
328
 
327
329
  @staticmethod
328
- def _transcription_worker(conn, model_path, ready_event, shutdown_event):
330
+ def _transcription_worker(conn, model_path, ready_event, shutdown_event, interrupt_stop_event):
329
331
  """
330
332
  Worker method that handles the continuous process of transcribing audio data.
331
333
 
@@ -362,25 +364,30 @@ class AudioToTextRecorder:
362
364
  logging.debug('Faster_whisper main speech to text transcription model initialized successfully')
363
365
 
364
366
  while not shutdown_event.is_set():
365
- if conn.poll(0.5):
366
- audio, language = conn.recv()
367
- try:
368
- segments = model.transcribe(audio, language=language if language else None)[0]
369
- transcription = " ".join(seg.text for seg in segments).strip()
370
- conn.send(('success', transcription))
371
- except faster_whisper.WhisperError as e:
372
- logging.error(f"Whisper transcription error: {e}")
373
- conn.send(('error', str(e)))
374
- except Exception as e:
375
- logging.error(f"General transcription error: {e}")
376
- conn.send(('error', str(e)))
377
- else:
378
- # If there's no data, sleep for a short while to prevent busy waiting
379
- time.sleep(0.02)
367
+ try:
368
+ if conn.poll(0.5):
369
+ audio, language = conn.recv()
370
+ try:
371
+ segments = model.transcribe(audio, language=language if language else None)[0]
372
+ transcription = " ".join(seg.text for seg in segments).strip()
373
+ conn.send(('success', transcription))
374
+ except faster_whisper.WhisperError as e:
375
+ logging.error(f"Whisper transcription error: {e}")
376
+ conn.send(('error', str(e)))
377
+ except Exception as e:
378
+ logging.error(f"General transcription error: {e}")
379
+ conn.send(('error', str(e)))
380
+ else:
381
+ # If there's no data, sleep for a short while to prevent busy waiting
382
+ time.sleep(0.02)
383
+ except KeyboardInterrupt:
384
+ interrupt_stop_event.set()
385
+ logging.debug('Transcription worker process finished due to KeyboardInterrupt')
386
+ break
380
387
 
381
388
 
382
389
  @staticmethod
383
- def _audio_data_worker(audio_queue, sample_rate, buffer_size, shutdown_event):
390
+ def _audio_data_worker(audio_queue, sample_rate, buffer_size, shutdown_event, interrupt_stop_event):
384
391
  """
385
392
  Worker method that handles the audio recording process.
386
393
 
@@ -433,7 +440,11 @@ class AudioToTextRecorder:
433
440
  print (f"Error: {e}")
434
441
  continue
435
442
 
436
- audio_queue.put(data)
443
+ audio_queue.put(data)
444
+
445
+ except KeyboardInterrupt:
446
+ interrupt_stop_event.set()
447
+ logging.debug('Audio data worker process finished due to KeyboardInterrupt')
437
448
  finally:
438
449
  stream.stop_stream()
439
450
  stream.close()
@@ -463,14 +474,16 @@ class AudioToTextRecorder:
463
474
  self.start_recording_on_voice_activity = True
464
475
 
465
476
  # Wait until recording starts
466
- self.start_recording_event.wait()
477
+ while not self.interrupt_stop_event.is_set():
478
+ if (self.start_recording_event.wait(timeout=0.5)): break
467
479
 
468
480
  # If recording is ongoing, wait for voice inactivity to finish recording.
469
481
  if self.is_recording:
470
482
  self.stop_recording_on_voice_deactivity = True
471
483
 
472
484
  # Wait until recording stops
473
- self.stop_recording_event.wait()
485
+ while not self.interrupt_stop_event.is_set():
486
+ if (self.stop_recording_event.wait(timeout=0.5)): break
474
487
 
475
488
  # Convert recorded frames to the appropriate audio format.
476
489
  audio_array = np.frombuffer(b''.join(self.frames), dtype=np.int16)
@@ -536,7 +549,7 @@ class AudioToTextRecorder:
536
549
 
537
550
  self.wait_audio()
538
551
 
539
- if self.is_shut_down:
552
+ if self.is_shut_down or self.interrupt_stop_event.is_set():
540
553
  return ""
541
554
 
542
555
  if on_transcription_finished:
@@ -660,16 +673,23 @@ class AudioToTextRecorder:
660
673
  # Continuously monitor audio for voice activity
661
674
  while self.is_running:
662
675
 
663
- data = self.audio_queue.get()
676
+ try:
664
677
 
665
- # Handle queue overflow
666
- queue_overflow_logged = False
667
- while self.audio_queue.qsize() > self.allowed_latency_limit:
668
- if not queue_overflow_logged:
669
- logging.warning(f"Audio queue size exceeds latency limit. Current size: {self.audio_queue.qsize()}. Discarding old audio chunks.")
670
- queue_overflow_logged = True
671
678
  data = self.audio_queue.get()
672
679
 
680
+ # Handle queue overflow
681
+ queue_overflow_logged = False
682
+ while self.audio_queue.qsize() > self.allowed_latency_limit:
683
+ if not queue_overflow_logged:
684
+ logging.warning(f"Audio queue size exceeds latency limit. Current size: {self.audio_queue.qsize()}. Discarding old audio chunks.")
685
+ queue_overflow_logged = True
686
+ data = self.audio_queue.get()
687
+
688
+ except BrokenPipeError:
689
+ print ("BrokenPipeError _recording_worker")
690
+ self.is_running = False
691
+ break
692
+
673
693
  if not self.is_recording:
674
694
  # Handle not recording state
675
695
 
@@ -790,8 +810,9 @@ class AudioToTextRecorder:
790
810
 
791
811
 
792
812
  except Exception as e:
793
- logging.error(f"Unhandled exeption in _recording_worker: {e}")
794
- raise
813
+ if not self.interrupt_stop_event.is_set():
814
+ logging.error(f"Unhandled exeption in _recording_worker: {e}")
815
+ raise
795
816
 
796
817
 
797
818
  def _realtime_worker(self):
@@ -988,23 +1009,23 @@ class AudioToTextRecorder:
988
1009
  if self.on_vad_detect_start:
989
1010
  self.on_vad_detect_start()
990
1011
  self._set_spinner("speak now")
991
- if self.spinner:
1012
+ if self.spinner and self.halo:
992
1013
  self.halo._interval = 250
993
1014
  elif new_state == "wakeword":
994
1015
  if self.on_wakeword_detection_start:
995
1016
  self.on_wakeword_detection_start()
996
1017
  self._set_spinner(f"say {self.wake_words}")
997
- if self.spinner:
1018
+ if self.spinner and self.halo:
998
1019
  self.halo._interval = 500
999
1020
  elif new_state == "transcribing":
1000
1021
  if self.on_transcription_start:
1001
1022
  self.on_transcription_start()
1002
1023
  self._set_spinner("transcribing")
1003
- if self.spinner:
1024
+ if self.spinner and self.halo:
1004
1025
  self.halo._interval = 50
1005
1026
  elif new_state == "recording":
1006
1027
  self._set_spinner("recording")
1007
- if self.spinner:
1028
+ if self.spinner and self.halo:
1008
1029
  self.halo._interval = 100
1009
1030
  elif new_state == "inactive":
1010
1031
  if self.spinner and self.halo:
@@ -9,7 +9,7 @@ with open('requirements.txt') as f:
9
9
 
10
10
  setuptools.setup(
11
11
  name="RealTimeSTT",
12
- version="0.1.6",
12
+ version="0.1.7",
13
13
  author="Kolja Beigel",
14
14
  author_email="kolja.beigel@web.de",
15
15
  description="A fast Voice Activity Detection and Transcription System",
File without changes