konan_client.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. """
  2. Konan Voice Client — PC Windows
  3. Push-to-talk : maintiens ESPACE pour parler, relâche pour envoyer.
  4. Ctrl+C pour quitter.
  5. Installation :
  6. pip install sounddevice scipy openai-whisper requests keyboard pyttsx3
  7. """
  8. import sounddevice as sd
  9. import scipy.io.wavfile as wav
  10. import whisper
  11. import requests
  12. import pyttsx3
  13. import keyboard
  14. import numpy as np
  15. import tempfile
  16. import os
  17. import sys
  18. KONAN_API = "http://192.168.1.21:8765/api/chat"
  19. SAMPLE_RATE = 16000
  20. USER_ID = "pc_user"
  21. print("Chargement de Whisper tiny...")
  22. model = whisper.load_model("tiny")
  23. print("Whisper prêt.")
  24. engine = pyttsx3.init()
  25. engine.setProperty("rate", 165)
  26. # Voix française si disponible
  27. voices = engine.getProperty("voices")
  28. for v in voices:
  29. if "fr" in v.id.lower() or "french" in v.name.lower():
  30. engine.setProperty("voice", v.id)
  31. break
  32. def speak(text):
  33. print(f"Konan : {text}")
  34. engine.say(text)
  35. engine.runAndWait()
  36. def record_until_release():
  37. print("🎙️ Enregistrement... (relâche Espace pour envoyer)")
  38. chunks = []
  39. stream = sd.InputStream(samplerate=SAMPLE_RATE, channels=1, dtype="int16")
  40. stream.start()
  41. while keyboard.is_pressed("space"):
  42. chunk, _ = stream.read(1024)
  43. chunks.append(chunk)
  44. stream.stop()
  45. stream.close()
  46. if not chunks:
  47. return None
  48. audio = np.concatenate(chunks, axis=0).flatten()
  49. return audio
  50. def transcribe(audio):
  51. with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f:
  52. wav.write(f.name, SAMPLE_RATE, audio)
  53. result = model.transcribe(f.name, language="fr")
  54. os.unlink(f.name)
  55. return result["text"].strip()
  56. def ask_konan(text):
  57. try:
  58. r = requests.post(KONAN_API, json={"text": text, "user_id": USER_ID}, timeout=120)
  59. data = r.json()
  60. return data.get("response", "Pas de réponse.")
  61. except Exception as e:
  62. return f"Erreur connexion : {e}"
  63. speak("Konan est prêt. Maintiens Espace pour parler.")
  64. print("\n▶ Maintiens ESPACE pour parler. Ctrl+C pour quitter.\n")
  65. try:
  66. while True:
  67. keyboard.wait("space")
  68. audio = record_until_release()
  69. if audio is None or len(audio) < SAMPLE_RATE * 0.3:
  70. print("(trop court, ignoré)")
  71. continue
  72. print("Transcription...")
  73. text = transcribe(audio)
  74. if not text:
  75. print("(rien détecté)")
  76. continue
  77. print(f"Toi : {text}")
  78. print("Konan réfléchit...")
  79. response = ask_konan(text)
  80. speak(response)
  81. except KeyboardInterrupt:
  82. print("\nAu revoir.")