- Replace kawa:kawa123@100.64.0.1:4222 with NATS placeholders - Replace initialPassword 'kawa2026' with <INITIAL_PASSWORD> - Update README with password placeholders - Add security notes for default credentials Safe for public release.
225 lines
7.0 KiB
Bash
Executable File
225 lines
7.0 KiB
Bash
Executable File
#!/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://<NATS_USER>:<NATS_PASSWORD>@<NATS_SERVER>"
|
|
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 <question>' - Interroger Ollama"
|
|
echo "═══════════════════════════════════════════════════════════════"
|