Skip to content

Commit 32cbb2c

Browse files
committed
Added stripped out stuff from listener back in
1 parent 17ffff6 commit 32cbb2c

File tree

2 files changed

+65
-15
lines changed

2 files changed

+65
-15
lines changed

Magic_AI_Storybook/listener.py

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,111 @@
22
#
33
# SPDX-License-Identifier: MIT
44

5+
from queue import Queue
56
import time
67

78
import speech_recognition as sr
89

910

1011
class Listener:
11-
def __init__(self, api_key, energy_threshold=300, record_timeout=30):
12+
def __init__(
13+
self, api_key, energy_threshold=300, phrase_timeout=3.0, record_timeout=30
14+
):
1215
self.listener_handle = None
1316
self.microphone = sr.Microphone()
1417
self.recognizer = sr.Recognizer()
1518
self.recognizer.energy_threshold = energy_threshold
19+
self.recognizer.dynamic_energy_threshold = False
20+
self.recognizer.pause_threshold = 1
21+
self.last_sample = bytes()
22+
self.phrase_time = time.monotonic()
23+
self.phrase_timeout = phrase_timeout
1624
with self.microphone as source:
1725
self.recognizer.adjust_for_ambient_noise(
1826
source
1927
) # we only need to calibrate once, before we start listening
2028
self.record_timeout = record_timeout
29+
self.phrase_complete = False
30+
self.data_queue = Queue()
2131
self.listener_handle = None
22-
self.audio = None
2332
self.api_key = api_key
2433

2534
def listen(self, ready_callback=None):
35+
print("Start listening...")
36+
self.phrase_complete = False
37+
start = time.monotonic()
2638
self._start_listening()
2739
if ready_callback:
2840
ready_callback()
29-
while self.listener_handle and self.audio is None:
30-
time.sleep(0.1)
41+
while (
42+
self.listener_handle
43+
and not self.speech_waiting()
44+
or not self.phrase_complete
45+
):
46+
if self.phrase_time and time.monotonic() > start + self.phrase_timeout:
47+
self.last_sample = bytes()
48+
self.phrase_complete = True
49+
self.phrase_time = time.monotonic() - start
3150
self.stop_listening()
3251

33-
def _save_audio_callback(self, _recognizer, audio):
34-
self.audio = audio
52+
def _save_audio_callback(self, _, audio):
53+
print("Saving audio")
54+
data = audio.get_raw_data()
55+
self.data_queue.put(data)
56+
57+
def _get_audio(self):
58+
"""Concatenate and convert the queued raw data back to audio and return it"""
59+
start = time.monotonic()
60+
if self.speech_waiting():
61+
self.phrase_complete = False
62+
if self.phrase_time and time.monotonic() > start + self.phrase_timeout:
63+
self.last_sample = bytes()
64+
self.phrase_complete = True
65+
self.phrase_time = time.monotonic() - start
66+
67+
# Concatenate our current audio data with the latest audio data.
68+
while self.speech_waiting():
69+
data = self.data_queue.get()
70+
self.last_sample += data
71+
72+
# Use AudioData to convert the raw data to wav data.
73+
return sr.AudioData(
74+
self.last_sample,
75+
self.microphone.SAMPLE_RATE,
76+
self.microphone.SAMPLE_WIDTH,
77+
)
78+
return None
3579

3680
def _start_listening(self):
37-
self.listener_handle = self.recognizer.listen_in_background(
38-
self.microphone, self._save_audio_callback
39-
)
81+
if not self.listener_handle:
82+
self.listener_handle = self.recognizer.listen_in_background(
83+
self.microphone,
84+
self._save_audio_callback,
85+
phrase_time_limit=self.record_timeout,
86+
)
4087

4188
def stop_listening(self, wait_for_stop=False):
4289
if self.listener_handle:
4390
self.listener_handle(wait_for_stop=wait_for_stop)
4491
self.listener_handle = None
92+
print("Stop listening...")
4593

4694
def is_listening(self):
4795
return self.listener_handle is not None
4896

4997
def speech_waiting(self):
50-
return self.audio is not None
98+
return not self.data_queue.empty()
5199

52100
def recognize(self):
53-
if self.audio:
101+
audio = self._get_audio()
102+
if audio:
54103
# Transcribe the audio data to text using Whisper
55104
print("Recognizing...")
56105
attempts = 0
57106
while attempts < 3:
58107
try:
59108
result = self.recognizer.recognize_whisper_api(
60-
self.audio, api_key=self.api_key
109+
audio, api_key=self.api_key
61110
)
62111

63112
return result.strip()

Magic_AI_Storybook/story.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292

9393
# Speech Recognition Parameters
9494
ENERGY_THRESHOLD = 300 # Energy level for mic to detect
95+
PHRASE_TIMEOUT = 3.0 # Space between recordings for separating phrases
9596
RECORD_TIMEOUT = 30 # Maximum time in seconds to wait for speech
9697

9798
# Do some checks and Import API keys from API_KEYS_FILE
@@ -248,7 +249,9 @@ def start(self):
248249
self._prompt = f.read()
249250

250251
# Initialize the Listener
251-
self.listener = Listener(openai.api_key, ENERGY_THRESHOLD, RECORD_TIMEOUT)
252+
self.listener = Listener(
253+
openai.api_key, ENERGY_THRESHOLD, PHRASE_TIMEOUT, RECORD_TIMEOUT
254+
)
252255

253256
# Preload remaining images
254257
self._load_image("background", BACKGROUND_IMAGE)
@@ -636,7 +639,6 @@ def generate_new_story(self):
636639
if self._sleep_request:
637640
self._busy = False
638641
time.sleep(0.2)
639-
print("Not busy anymore")
640642
return
641643

642644
def show_waiting():
@@ -680,7 +682,6 @@ def _sleep(self):
680682
if self.listener.is_listening():
681683
self.listener.stop_listening()
682684
while self._busy:
683-
print("Still busy")
684685
time.sleep(0.1)
685686
self._sleep_request = False
686687

0 commit comments

Comments
 (0)