Просмотр исходного кода

Attendre deux secondes de silence global avant la reponse vocale

Andy Esnard 18 часов назад
Родитель
Сommit
2d26cdac93
3 измененных файлов с 27 добавлено и 2 удалено
  1. 1 1
      chatbot.py
  2. 13 1
      test_voice_stt.py
  3. 13 0
      voice_stt.py

+ 1 - 1
chatbot.py

@@ -51,7 +51,7 @@ if WEB_SEARCH_RESULT_COUNT < 1:
 # Initialiser le client OpenAI asynchrone ici
 # Initialiser le client OpenAI asynchrone ici
 openai_client = AsyncOpenAI(api_key=OPENAI_API_KEY, base_url=URL_OPENAI_API)
 openai_client = AsyncOpenAI(api_key=OPENAI_API_KEY, base_url=URL_OPENAI_API)
 
 
-BOT_VERSION = "3.3.0"
+BOT_VERSION = "3.3.1"
 
 
 # Vérifier la version de Discord
 # Vérifier la version de Discord
 if not sys.version_info[:2] >= (3, 15):
 if not sys.version_info[:2] >= (3, 15):

+ 13 - 1
test_voice_stt.py

@@ -114,10 +114,22 @@ class VoiceTests(unittest.IsolatedAsyncioTestCase):
                 self.sink.add_pcm(other, self.pcm, time.monotonic())
                 self.sink.add_pcm(other, self.pcm, time.monotonic())
                 self.assertIn(2, self.sink.buffers)
                 self.assertIn(2, self.sink.buffers)
             release.set()
             release.set()
-            await asyncio.wait_for(second.wait(), 2)
+            await asyncio.wait_for(second.wait(), 4)
             self.assertEqual(batches[1], [(other, 'Minecraft ?'), (self.user, 'Avec des mods')])
             self.assertEqual(batches[1], [(other, 'Minecraft ?'), (self.user, 'Avec des mods')])
             self.assertFalse(self.sink.pending)
             self.assertFalse(self.sink.pending)
 
 
+    async def test_reply_waits_for_global_silence(self):
+        with self.sink.lock:
+            self.sink.last_voice = time.monotonic()
+        self.sink.pending.append((self.user, 'Bonjour'))
+        self.sink.pending_event.set()
+        await asyncio.sleep(0.2)
+        self.reply.assert_not_awaited()
+        with self.sink.lock:
+            self.sink.last_voice = time.monotonic() - 2.1
+        await asyncio.sleep(0.2)
+        self.reply.assert_awaited_once_with([(self.user, 'Bonjour')])
+
     async def test_close_discards_pending_audio(self):
     async def test_close_discards_pending_audio(self):
         self.sink.queue.put_nowait((self.user, self.pcm))
         self.sink.queue.put_nowait((self.user, self.pcm))
         await self.sink.close()
         await self.sink.close()

+ 13 - 0
voice_stt.py

@@ -32,6 +32,7 @@ class STTSink(voice_recv.AudioSink):
         self.responding = False
         self.responding = False
         self.last_stt_seconds = None
         self.last_stt_seconds = None
         self.last_reply_seconds = None
         self.last_reply_seconds = None
+        self.last_voice = 0.0
         self.last_error = 0
         self.last_error = 0
         self.stats_lock = threading.Lock()
         self.stats_lock = threading.Lock()
         self.stats = Counter(audio=0, rtcp=0, pcm=0, audible=0, phrases=0, stt=0)
         self.stats = Counter(audio=0, rtcp=0, pcm=0, audible=0, phrases=0, stt=0)
@@ -135,6 +136,7 @@ class STTSink(voice_recv.AudioSink):
         buffer[1].extend(pcm[:available])
         buffer[1].extend(pcm[:available])
         if audible:
         if audible:
             buffer[2] = now
             buffer[2] = now
+            self.last_voice = now
 
 
     async def flush_phrases(self):
     async def flush_phrases(self):
         while True:
         while True:
@@ -211,6 +213,17 @@ class STTSink(voice_recv.AudioSink):
     async def respond_batches(self):
     async def respond_batches(self):
         while not self.closed:
         while not self.closed:
             await self.pending_event.wait()
             await self.pending_event.wait()
+            # L'affichage STT continue ; seule la réponse attend le silence global.
+            while not self.closed:
+                await self.queue.join()
+                with self.lock:
+                    quiet = time.monotonic() - self.last_voice > 2.0
+                    buffered = bool(self.buffers)
+                if quiet and not buffered and self.queue.empty():
+                    break
+                await asyncio.sleep(0.1)
+            if self.closed:
+                return
             self.pending_event.clear()
             self.pending_event.clear()
             batch, self.pending = self.pending, []
             batch, self.pending = self.pending, []
             if not batch:
             if not batch: