#!/bin/bash # KAWA Voice - Installation de l'accès vocal # Pour machines Linux (Debian/Ubuntu/NixOS) set -e echo "═══════════════════════════════════════════════════════════════" echo " KAWA Voice - Accès Vocal" echo "═══════════════════════════════════════════════════════════════" echo "" # Détection du système if [ -f /etc/NIXOS ]; then echo "Système: NixOS détecté" SYSTEM="nixos" elif [ -f /etc/debian_version ]; then echo "Système: Debian/Ubuntu détecté" SYSTEM="debian" else echo "Système: Linux générique" SYSTEM="linux" fi # Installation des dépendances echo "" echo "=== Installation des dépendances ===" if [ "$SYSTEM" = "debian" ]; then sudo apt update sudo apt install -y python3 python3-pip python3-venv \ portaudio19-dev ffmpeg espeak-ng \ libportaudio2 libportaudiocpp0 \ pulseaudio alsa-utils elif [ "$SYSTEM" = "nixos" ]; then echo "Pour NixOS, ajoutez à configuration.nix:" echo ' environment.systemPackages = with pkgs; [' echo ' python3 python3Packages.pip' echo ' portaudio ffmpeg espeak-ng' echo ' pulseaudio alsa-utils' echo ' ];' echo ' services.pulseaudio.enable = true;' fi # Création de l'environnement Python echo "" echo "=== Environnement Python ===" python3 -m venv ~/.venv/kawa-voice source ~/.venv/kawa-voice/bin/activate pip install --upgrade pip pip install vosk pyttsx3 pyaudio requests websocket-client # Téléchargement du modèle Vosk (français) echo "" echo "=== Téléchargement du modèle Vosk français ===" mkdir -p ~/.local/share/vosk cd ~/.local/share/vosk if [ ! -d "vosk-model-fr" ]; then wget -q https://alphacephei.com/vosk/models/vosk-model-fr-0.6-linto-2.2.0.zip unzip -q vosk-model-fr-0.6-linto-2.2.0.zip mv vosk-model-fr-0.6-linto-2.2.0 vosk-model-fr rm vosk-model-fr-0.6-linto-2.2.0.zip echo "✓ Modèle français téléchargé" else echo "✓ Modèle déjà présent" fi # Création du script kawa-voice echo "" echo "=== Création de kawa-voice ===" mkdir -p ~/.local/bin cat > ~/.local/bin/kawa-voice << 'KAWA_VOICE' #!/usr/bin/env python3 """ KAWA Voice - Interface vocale pour le réseau KAWA """ import json import queue import threading import requests import websocket from vosk import Model, KaldiRecognizer import pyaudio import pyttsx3 # Configuration NATS_SERVER = "ws://kawa:kawa123@100.64.0.1:4222" OLLAMA_SERVER = "http://100.64.0.7:11434" MODEL_PATH = os.path.expanduser("~/.local/share/vosk/vosk-model-fr") class KawaVoice: def __init__(self): self.model = Model(MODEL_PATH) self.recognizer = KaldiRecognizer(self.model, 16000) self.engine = pyttsx3.init() self.engine.setProperty('rate', 150) self.engine.setProperty('voice', 'french') # Audio self.p = pyaudio.PyAudio() self.stream = self.p.open( format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=8000 ) # NATS self.ws = None self.connect_nats() def connect_nats(self): """Connexion au bus NATS KAWA""" try: self.ws = websocket.WebSocket() self.ws.connect("ws://100.64.0.1:4222") # Subscribe aux commandes vocales self.ws.send(json.dumps({ "type": "subscribe", "topic": "kawa.voice.command" })) except Exception as e: print(f"Erreur NATS: {e}") def listen(self): """Écoute en continue""" print("🎤 En écoute... (dit 'KAWA' pour activer)") while True: data = self.stream.read(4096) if self.recognizer.AcceptWaveform(data): result = json.loads(self.recognizer.Result()) text = result.get('text', '').lower() if 'kawa' in text: self.engine.say("Oui?") self.engine.runAndWait() self.process_command(text.replace('kawa', '').strip()) def process_command(self, command): """Traite une commande vocale""" print(f"Commande: {command}") # Commander NATS if 'status' in command: self.ws.send(json.dumps({ "type": "publish", "topic": "kawa.voice.command", "message": {"command": "status"} })) response = "Statut envoyé" # Interroger Ollama elif any(word in command for word in ['que', 'quoi', 'comment', 'pourquoi']): response = self.query_ollama(command) else: response = f"Commande reçue: {command}" self.engine.say(response) self.engine.runAndWait() def query_ollama(self, question): """Interroge Ollama pour une réponse""" try: response = requests.post( f"{OLLAMA_SERVER}/api/generate", json={ "model": "glm-4.7-flash:q4_K_M", "prompt": question, "stream": False } ) return response.json().get('response', 'Je ne sais pas') except Exception as e: return f"Erreur: {str(e)}" if __name__ == "__main__": import os voice = KawaVoice() voice.listen() KAWA_VOICE chmod +x ~/.local/bin/kawa-voice # Création du service systemd echo "" echo "=== Service systemd ===" mkdir -p ~/.config/systemd/user cat > ~/.config/systemd/user/kawa-voice.service << 'SERVICE' [Unit] Description=KAWA Voice - Interface vocale After=network.target pulseaudio.service [Service] Type=simple ExecStart=/home/%u/.local/bin/kawa-voice Restart=on-failure RestartSec=10 [Install] WantedBy=default.target SERVICE echo "" echo "═══════════════════════════════════════════════════════════════" echo "✅ KAWA Voice installé!" echo "═══════════════════════════════════════════════════════════════" echo "" echo "Pour démarrer:" echo " systemctl --user start kawa-voice" echo "" echo "Pour activer au démarrage:" echo " systemctl --user enable kawa-voice" echo "" echo "Commandes vocales:" echo " 'KAWA status' - Statut du réseau" echo " 'KAWA ' - Interroger Ollama" echo "═══════════════════════════════════════════════════════════════"