Переделано под свежий Python и Vosk
[voicecontrol.git] / voicecontrol
index 7216fef829eee8765ed549cea6ae96a4a3b196f3..6b4f17bc8417c419a4223883209155355711b248 100755 (executable)
@@ -17,6 +17,8 @@ from time import time, sleep
 
 import webrtcvad
 
 
 import webrtcvad
 
+from pprint import pprint
+
 @contextmanager
 def _pyaudio() -> Generator[PyAudio, None, None]:
     p = PyAudio()
 @contextmanager
 def _pyaudio() -> Generator[PyAudio, None, None]:
     p = PyAudio()
@@ -57,12 +59,6 @@ def SkipSource(source,seconds):
   except:
     pass
 
   except:
     pass
 
-def Silence(speaker, seconds):
-  buf = bytes(speaker._frames_per_buffer)
-  bufs = int((seconds)*speaker._rate/speaker._frames_per_buffer)
-  for i in range(bufs):
-    speaker.write(buf)
-
 def PlayBack(pyaud, text, mic = None):
   global config, last_time
   
 def PlayBack(pyaud, text, mic = None):
   global config, last_time
   
@@ -84,7 +80,7 @@ def PlayBack(pyaud, text, mic = None):
       decoder = MP3Decoder(req)
 
       speaker = pyaud.open(output=True, format=paInt16, channels=decoder.num_channels, rate=decoder.sample_rate)
       decoder = MP3Decoder(req)
 
       speaker = pyaud.open(output=True, format=paInt16, channels=decoder.num_channels, rate=decoder.sample_rate)
-      Silence(speaker, 0.3) 
+      pprint(speaker)
 
       for chunk in decoder:
         speaker.write(chunk)
 
       for chunk in decoder:
         speaker.write(chunk)
@@ -97,7 +93,7 @@ def PlayBack(pyaud, text, mic = None):
       last_time = time()
 
       if mic:
       last_time = time()
 
       if mic:
-        SkipSource(mic, elapsed + 0.5)
+        SkipSource(mic, elapsed + 0.2)
 
       return elapsed
 
 
       return elapsed
 
@@ -105,7 +101,7 @@ def PlayBack(pyaud, text, mic = None):
       raise
 
     except:
       raise
 
     except:
-      pass
+      raise
 
   else:
     return 0
 
   else:
     return 0
@@ -198,49 +194,38 @@ async def ListenPhrase(mic, server):
   sz = int(mic._rate*frame)
   sp = int(pause/frame)
 
   sz = int(mic._rate*frame)
   sp = int(pause/frame)
 
-  try:
-
-    phrase = ""
-    voice = False
+  phrase = ""
+  voice = False
 
 
-    while not phrase:
-      data = mic.read(sz)
-      if len(data) == 0:
-        break
-      vd = vad.is_speech(data, mic._rate)
-      if vd and not voice:
-        voice = True
-        if config["debug"]:
-          print("+", end="")
+  while not phrase:
+    data = mic.read(sz)
+    if len(data) == 0:
+      break
+    vd = vad.is_speech(data, mic._rate)
+    if vd and not voice:
+      voice = True
+      if config["debug"]:
+        print("+", end="")
+      cnt = 0
+    if voice and not vd:
+      cnt = cnt + 1
+      if cnt > sp:
         cnt = 0
         cnt = 0
-      if voice and not vd:
-        cnt = cnt + 1
-        if cnt > sp:
-          cnt = 0
-          voice = False
-          if config["debug"]:
-            print("-")
-      if voice:
-        print("*",end="")
-        await server.send(data)
-        datatxt = await server.recv()
-        data = json.loads(datatxt)
-        try:
-          phrase = data["text"]
-          confidence = min(map(lambda x: x["conf"], data["result"]))
-        except:
-          pass  
+        voice = False
+        if config["debug"]:
+          print("-")
+    if voice:
+      print("*",end="")
+      await server.send(data)
+      datatxt = await server.recv()
+      data = json.loads(datatxt)
+      try:
+        phrase = data["text"]
+      except:
+        pass  
   
   
-    last_time = time()
-
-    return phrase, confidence
-
-  except KeyboardInterrupt:
-    raise
-  except websockets.exceptions.ConnectionClosedError:
-    raise  
-  except:
-    return '',0
+  last_time = time()
+  return phrase
 
 
 async def main_loop(uri):
 
 
 async def main_loop(uri):
@@ -248,13 +233,13 @@ async def main_loop(uri):
   global config, last_time
 
   keyphrase = config["keyphrase"]
   global config, last_time
 
   keyphrase = config["keyphrase"]
-  confidence_treshold = config["confidence_treshold"]
   rec_attempts = config["rec_attempts"]
   commands = config["commands"]
 
   
   with ExitStack() as audio_stack:
     p = audio_stack.enter_context(_pyaudio())
   rec_attempts = config["rec_attempts"]
   commands = config["commands"]
 
   
   with ExitStack() as audio_stack:
     p = audio_stack.enter_context(_pyaudio())
+
     s = audio_stack.enter_context(_pyaudio_open_stream(p,
             format = paInt16, 
             channels = 1,
     s = audio_stack.enter_context(_pyaudio_open_stream(p,
             format = paInt16, 
             channels = 1,
@@ -274,28 +259,28 @@ async def main_loop(uri):
 
           ws = await web_stack.enter_async_context(_polite_websocket(ws))
           while True:
 
           ws = await web_stack.enter_async_context(_polite_websocket(ws))
           while True:
-            phrase, confidence = await ListenPhrase(s, ws)
+            phrase = await ListenPhrase(s, ws)
             if config["debug"]:
             if config["debug"]:
-              print(phrase,confidence)
-            if phrase == keyphrase and confidence>=confidence_treshold :
-              PlayBack(p, "Я жду команду", mic=s)
+              print(phrase)
+            if phrase == keyphrase :
+              print("COMMAND!")
+              PlayBack(p, "Слушаю!", mic=s)
               command = ""
   
               for i in range(rec_attempts):
               command = ""
   
               for i in range(rec_attempts):
-                phrase, confidence = await ListenPhrase(s, ws)
+                phrase = await ListenPhrase(s, ws)
                 if config["debug"]:
                 if config["debug"]:
-                  print(phrase,confidence)
-                if confidence > confidence_treshold:
-                  if (not commands) or (phrase in commands):
-                    if config["debug"]:
-                      print("Command: ", phrase)
-                    command = phrase
-                    RunCommand(command, p, s)
-                    break
-                  else:
-                    PlayBack(p, "Не знаю такой команды: "+phrase, mic=s)
+                  print(phrase)
+                if (not commands) or (phrase in commands):
+                  if config["debug"]:
+                    print("Command: ", phrase)
+                  command = phrase
+                  RunCommand(command, p, s)
+                  break
                 else:
                 else:
-                  PlayBack(p, "Не поняла, слишком неразборчиво", mic=s)
+                  PlayBack(p, "Не знаю такой команды: "+phrase, mic=s)
+              else:
+                PlayBack(p, "Не поняла, слишком неразборчиво", mic=s)
 
               if not command:
                 PlayBack(p, "Так команду и не поняла...", mic=s)
 
               if not command:
                 PlayBack(p, "Так команду и не поняла...", mic=s)
@@ -321,11 +306,6 @@ def get_config(path):
   except:
     rec_attempts = 4
 
   except:
     rec_attempts = 4
 
-  try:  
-    confidence_treshold = float(config['vosk']['confidence_treshold'])
-  except:
-    confidence_treshold = 0.4
-
   try:
     vosk_server = config['vosk']['server']
   except:
   try:
     vosk_server = config['vosk']['server']
   except:
@@ -389,7 +369,6 @@ def get_config(path):
       "asr_server": vosk_server,
       "keyphrase": keyphrase,
       "rec_attempts": rec_attempts,
       "asr_server": vosk_server,
       "keyphrase": keyphrase,
       "rec_attempts": rec_attempts,
-      "confidence_treshold": confidence_treshold,
       "tts_url": tts_url,
       "tts_param": tts_param,
       "api_attempts": api_attempts,
       "tts_url": tts_url,
       "tts_param": tts_param,
       "api_attempts": api_attempts,
@@ -413,6 +392,7 @@ config = get_config(conf_file)
 server = config['asr_server']
 
 vad = webrtcvad.Vad(config['vad_mode'])
 server = config['asr_server']
 
 vad = webrtcvad.Vad(config['vad_mode'])
+last_time = time()
 
 while True:
 
 
 while True:
 
@@ -423,6 +403,7 @@ while True:
         main_loop(f'ws://' + server))
 
   except (Exception, KeyboardInterrupt) as e:
         main_loop(f'ws://' + server))
 
   except (Exception, KeyboardInterrupt) as e:
+    raise
     loop.run_until_complete(
       loop.shutdown_asyncgens())
     if isinstance(e, KeyboardInterrupt):
     loop.run_until_complete(
       loop.shutdown_asyncgens())
     if isinstance(e, KeyboardInterrupt):