# Prompt #5 — D5 ASR (Vosk FR)

**Rôle :**
Tu es _Développeur ASR_ du projet **Skull Pi**. Tu livres un service Python (`svc-asr`) qui consomme le flux audio micro + événements VAD, transcrit la parole en français avec Vosk, et publie du texte clair sur MQTT. Langue : FR. Cible : Raspberry Pi Zero 2 W.

**Contexte & contraintes :**

- Dossier : `/opt/Skull/apps/asr`.
- Exécution : `python -m asr.main`.
- Bus : MQTT local `127.0.0.1:1883`.
- Modèle ASR : **Vosk FR compact** (optimisé Pi).
- Déclenchement : VAD actif (`audio/vad.active=true`) → écouter, EOS (`end_of_speech:true`) → fermer segment.
- Paramètres dynamiques : `lang`, `eos_ms`, seuils VAD.
- Doit tolérer bruit ambiant, faible latence.

---

## Objectif fonctionnel

1. Abonner au flux `audio/rms` + `audio/vad`.
2. Quand `vad.active=true`, ouvrir session ASR.
3. Collecter audio PCM (via `audioin` partagé ou recapture micro).
4. Envoyer au modèle Vosk (streaming).
5. À `end_of_speech`, fermer session, publier texte FR.
6. Publier capabilities retained.

---

## Spécification MQTT

### Sorties

- `asr/text`

  ```json
  { "ts_ms": 0, "text": "bonjour skull" }
  ```

- `asr/capabilities` (retained)

  ```json
  { "engine": "vosk", "lang": "fr", "sample_rate": 16000 }
  ```

### Entrées (config)

- `asr/config`

  ```json
  { "lang": "fr", "eos_ms": 800, "vad": { "threshold": 0.5 } }
  ```

---

## Implémentation attendue

1. **Capture audio**

   - Option A : réutiliser frames `audioin`.
   - Option B : micro direct (I²S).
   - Normaliser sur 16 kHz mono PCM.

2. **Pipeline ASR (Vosk)**

   - Charger modèle FR compact (\~50–70 MB).
   - Streaming API : `AcceptWaveform()` / `Result()`.
   - Bufferiser jusqu’à EOS.

3. **Publication**

   - `asr/text` publié à la fin d’un segment complet.
   - Inclure `ts_ms`.

4. **Config dynamique**

   - Appliquer `eos_ms` à chaud (timeout fin segment).
   - Langue configurable (FR par défaut).

5. **Logs**

   - `/opt/Skull/logs/asr.log`.
   - Inclure temps de traitement, longueur segment.

---

## Déploiement / systemd

- Service `skull-asr.service`.
- Wrapper `/opt/Skull/bin/skull-asr.sh` :

  ```bash
  #!/usr/bin/env bash
  set -euo pipefail
  source /opt/Skull/venv/bin/activate
  exec python -m asr.main
  ```

---

## Livrables

- Code Python type-hinté, `ruff` + `mypy` clean.
- Tests unitaires avec fichiers WAV FR (voix synthétique).
- `README.md` (installation modèle, exemples MQTT).

---

## Critères d’acceptation

- Latence moyenne transcription < 1 s après EOS.
- Texte publié correct pour phrases simples (“Bonjour Skull”).
- Config `eos_ms` modifiable à chaud.
- Capabilities retained correct.
- Robustesse : silence → aucun texte, bruit → pas de faux positifs majeurs.

---

## Plan de tests unitaires

1. **Phrase simple**

   - Input WAV “Bonjour Skull” → sortie texte attendu.

2. **Silence**

   - Input silence 2 s → aucun `asr/text`.

3. **EOS**

   - VAD actif puis `end_of_speech` → publication unique.

4. **Config dynamique**

   - Changer `eos_ms` → vérifier temps déclenchement différent.

5. **Langue**

   - Config `lang=fr` → modèle FR utilisé (mock check).

6. **Capabilities retained**

   - Restart service → `asr/capabilities` dispo.

---

## Test manuel rapide

1. Démarrer service :

   ```
   mosquitto_sub -t 'asr/#' -v
   ```

2. Parler : “Bonjour Skull” → sortie `asr/text`.
3. Silence > `eos_ms` → fermeture segment.
4. Changer paramètre :

   ```
   mosquitto_pub -t asr/config -m '{"eos_ms":1500}'
   ```

   → fin de segment plus lente.

---

**À livrer** : MR “D5 ASR — Reconnaissance vocale FR” avec code, tests, service, README.
