Merge branch 'master' of gitlab.com:hugvey/hugvey
This commit is contained in:
commit
d904facbe7
1 changed files with 48 additions and 46 deletions
|
@ -33,7 +33,7 @@ class GoogleVoiceClient(object):
|
|||
self.hugvey = hugvey
|
||||
self.language_code = language_code
|
||||
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = credential_file
|
||||
|
||||
|
||||
# Create a thread-safe buffer of audio data
|
||||
self.buffer = queue.Queue()
|
||||
self.isRunning = threading.Event()
|
||||
|
@ -41,53 +41,53 @@ class GoogleVoiceClient(object):
|
|||
self.target_rate = 16000
|
||||
self.cv_laststate = None
|
||||
self.restart = False
|
||||
|
||||
|
||||
|
||||
|
||||
self.task = threading.Thread(target=self.run, name=f"hugvey#{self.hugvey.id}v")
|
||||
self.task.setDaemon(True)
|
||||
self.task.start()
|
||||
self.subsequentMutedFrames = 0
|
||||
|
||||
|
||||
self.lastNonFinalTranscript = None
|
||||
|
||||
|
||||
def pause(self):
|
||||
self.isRunning.clear()
|
||||
self.restart = True
|
||||
|
||||
|
||||
def resume(self):
|
||||
self.buffer = queue.Queue() # have a clear queue when resuming
|
||||
self.isRunning.set()
|
||||
|
||||
|
||||
def generator(self):
|
||||
self.logger.debug('start generator')
|
||||
while not self.toBeShutdown and self.isRunning.is_set():
|
||||
try:
|
||||
# set a timeout, as not to wait infinitely for the buffer when
|
||||
# we actually want to restart
|
||||
# we actually want to restart
|
||||
yield self.buffer.get(timeout=.3)
|
||||
except queue.Empty as e:
|
||||
self.logger.debug('empty mic buffer - restart?')
|
||||
# print(self.isRunning.isSet())
|
||||
self.logger.info('stop generator')
|
||||
self.restart = False # don't trigger double restart
|
||||
|
||||
|
||||
# raise RequireRestart("Restart required (generator)")
|
||||
|
||||
|
||||
def setLanguage(self, language_code):
|
||||
if self.language_code == language_code:
|
||||
return
|
||||
|
||||
|
||||
self.logger.info("Change language from {} to {}".format(self.language_code, language_code))
|
||||
self.language_code = language_code
|
||||
self.isRunning.clear()
|
||||
self.restart = True
|
||||
|
||||
|
||||
def run(self):
|
||||
self.isRunning.set()
|
||||
|
||||
|
||||
# Leave this here to avoid "Too many files open" errors.
|
||||
self.speech_client = speech.SpeechClient()
|
||||
|
||||
|
||||
while not self.toBeShutdown:
|
||||
config = types.RecognitionConfig(
|
||||
encoding=enums.RecognitionConfig.AudioEncoding.LINEAR16,
|
||||
|
@ -96,59 +96,59 @@ class GoogleVoiceClient(object):
|
|||
self.streaming_config = types.StreamingRecognitionConfig(
|
||||
config=config,
|
||||
interim_results=True)
|
||||
|
||||
|
||||
try:
|
||||
self.logger.log(LOG_BS,"wait for Google Voice")
|
||||
if not self.isRunning.wait(timeout=1):
|
||||
continue # re-ceck toBeShutdown
|
||||
self.logger.debug("Starting Google Voice")
|
||||
|
||||
|
||||
|
||||
|
||||
audio_generator = self.generator()
|
||||
requests = (types.StreamingRecognizeRequest(audio_content=content)
|
||||
for content in audio_generator)
|
||||
responses = self.speech_client.streaming_recognize(
|
||||
self.streaming_config, requests)
|
||||
|
||||
|
||||
self.logger.debug("Starting voice loop")
|
||||
for response in responses:
|
||||
if not response.results:
|
||||
self.logger.debug('...')
|
||||
continue
|
||||
"""Iterates through server responses and prints them.
|
||||
|
||||
|
||||
The responses passed is a generator that will block until a response
|
||||
is provided by the server.
|
||||
|
||||
|
||||
Each response may contain multiple results, and each result may contain
|
||||
multiple alternatives; for details, see https://goo.gl/tjCPAU. Here we
|
||||
print only the transcription for the top alternative of the top result.
|
||||
|
||||
|
||||
In this case, responses are provided for interim results as well. If the
|
||||
response is an interim one, print a line feed at the end of it, to allow
|
||||
the next result to overwrite it, until the response is a final one. For the
|
||||
final one, print a newline to preserve the finalized transcription.
|
||||
"""
|
||||
|
||||
|
||||
# The `results` list is consecutive. For streaming, we only care about
|
||||
# the first result being considered, since once it's `is_final`, it
|
||||
# moves on to considering the next utterance.
|
||||
result = response.results[0]
|
||||
if not result.alternatives:
|
||||
continue
|
||||
|
||||
|
||||
# Display the transcription of the top alternative.
|
||||
transcript = result.alternatives[0].transcript
|
||||
|
||||
|
||||
# self.logger.debug("Text: ".format(transcript))
|
||||
|
||||
|
||||
if not result.is_final:
|
||||
self.logger.debug(f"Text: {transcript}")
|
||||
self.lastNonFinalTranscript = transcript
|
||||
else:
|
||||
self.logger.info(f"Text: {transcript}")
|
||||
self.lastNonFinalTranscript = None
|
||||
|
||||
|
||||
if result.is_final:
|
||||
self.logger.info("native final")
|
||||
msg = {
|
||||
|
@ -156,13 +156,13 @@ class GoogleVoiceClient(object):
|
|||
"is_final": result.is_final,
|
||||
"transcript": transcript.strip(),
|
||||
}
|
||||
|
||||
|
||||
self.hugvey.queueEvent(msg)
|
||||
|
||||
|
||||
if self.restart:
|
||||
self.restart = False
|
||||
raise RequireRestart("Restart required")
|
||||
|
||||
|
||||
if self.toBeShutdown:
|
||||
self.logger.warn("Stopping voice loop")
|
||||
break
|
||||
|
@ -170,30 +170,33 @@ class GoogleVoiceClient(object):
|
|||
self.restart = False
|
||||
self.logger.warn("Restart Google Voice. Language: {}".format(self.language_code))
|
||||
except Exception as e:
|
||||
self.logger.critical(f"Crashed Google Voice: {e}")
|
||||
|
||||
if "305" in str(e):
|
||||
self.logger.warning(f"Long Google Voice: {e}")
|
||||
else:
|
||||
self.logger.critical(f"Crashed Google Voice: {e}")
|
||||
|
||||
# sending an extra message is deprecated since we ignore finals anyway
|
||||
# make sure we always send a 'final' transcript.
|
||||
# if self.lastNonFinalTranscript is not None:
|
||||
# msg = {
|
||||
# "event": "speech",
|
||||
# "is_final": True,
|
||||
# "is_final": True,
|
||||
# "transcript": self.lastNonFinalTranscript.strip(),
|
||||
# }
|
||||
# self.hugvey.queueEvent(msg)
|
||||
|
||||
self.logger.warn("Stop google run()") # finish means wrapping of hugvey#3v thread
|
||||
|
||||
|
||||
# time.sleep(1)
|
||||
# for i in gc.get_referrers(self):
|
||||
# print(i)
|
||||
|
||||
|
||||
|
||||
|
||||
def receive(self, chunk):
|
||||
if not self.task.isAlive():
|
||||
raise Exception("Voice thread died")
|
||||
|
||||
|
||||
|
||||
|
||||
if audioop.max(chunk, 2) == 0:
|
||||
# mic is muted on client side.
|
||||
self.subsequentMutedFrames += 1
|
||||
|
@ -202,31 +205,30 @@ class GoogleVoiceClient(object):
|
|||
self.logger.info("Pause muted stream!")
|
||||
self.pause()
|
||||
return
|
||||
|
||||
|
||||
self.subsequentMutedFrames = 0
|
||||
# self.logger.debug("We have mic!")
|
||||
if not self.isRunning.is_set():
|
||||
self.logger.info("Resume voice")
|
||||
self.resume()
|
||||
|
||||
|
||||
|
||||
|
||||
if not self.isRunning.is_set():
|
||||
# logger.log(LOG_BS, "Don't put to queue if google is paused")
|
||||
return
|
||||
|
||||
|
||||
if self.src_rate == self.target_rate:
|
||||
data = chunk
|
||||
else:
|
||||
data, self.cv_laststate = audioop.ratecv(chunk, 2, 1, self.src_rate, self.target_rate, self.cv_laststate)
|
||||
data, self.cv_laststate = audioop.ratecv(chunk, 2, 1, self.src_rate, self.target_rate, self.cv_laststate)
|
||||
self.buffer.put_nowait(data)
|
||||
|
||||
|
||||
def shutdown(self):
|
||||
self.toBeShutdown = True
|
||||
self.hugvey = None
|
||||
|
||||
|
||||
def triggerStart(self):
|
||||
pass
|
||||
|
||||
|
||||
def __del__(self):
|
||||
self.logger.warn("Destroyed google object")
|
||||
|
||||
|
|
Loading…
Reference in a new issue