Aller au contenu
ColliePWA

08/Documentation

Saisie vocale et Web Push

Le microphone dans le compositeur, et notifications lorsqu'un agent vous attend

Ces deux fonctionnalités sont désactivées par défaut. Vous pouvez activer un bouton de microphone dans le champ de saisie, ainsi que des notifications de navigateur qui se déclenchent lorsqu'un agent attend une saisie.

Saisie vocale (facultatif)

Un bouton de microphone dans le champ de saisie, et un interrupteur mains libres dans Réglages. Touchez le bouton, parlez, et la transcription arrive dans la zone de message, prête à être relue et envoyée. Avec le mode mains libres activé, elle est envoyée pour vous ; en suivant le même chemin de réponse sécurisé qu'un message saisi, sans jamais le contourner. Le microphone est le bouton rond au bout de la ligne, tant que le champ reste vide ; le premier caractère saisi le transforme à nouveau en Envoyer. Vous dictez un message ou vous le saisissez : il n'y a donc qu'une seule action principale au lieu de deux qui se disputent la largeur du champ.

Il n'existe pas tant que vous n'exécutez pas collie stt setup. Aucun bouton n'est affiché, aucun signal audio ne quitte le téléphone, aucun identifiant n'est conservé, aucun processus enfant ne tourne. Absent, pas simplement désactivé. Deux fournisseurs :

fournisseurce que c'est
openai-compatibleTout endpoint compatible POST /audio/transcriptions : l'API publique d'OpenAI, un clone cloud de Whisper ou un moteur local sur la même machine, qui constitue le choix zéro trafic sortant (ci-dessous).
codexEmprunte le binaire codex auquel vous faites déjà confiance pour obtenir un jeton temporaire. Pas de nouveau compte, pas de nouvelle clé, et un endpoint privé, non pris en charge qui comporte une étape de consentement où vous devez saisir yes (ci-dessous).

La configuration s'effectue en CLI pour la même raison que association : cette interface reçoit un identifiant, elle doit donc se trouver sur le clavier de la machine hôte. Il n'y a pas de formulaire de configuration web.

$ bin/collie stt setup
Which speech-to-text provider?
  openai-compatible  any endpoint that speaks POST /audio/transcriptions —
                     the public OpenAI API, or a local whisper.cpp / parakeet.cpp
                     server, which is the zero-egress choice and the one to prefer.
  codex              borrow your own `codex` sign-in. No new key, no new account —
                     and a private endpoint that may break without notice.
provider [openai-compatible]:
The API base, INCLUDING its version prefix — the provider appends /audio/transcriptions.
  local  http://127.0.0.1:8080/v1     (whisper.cpp / parakeet.cpp — nothing leaves the host)
  cloud  https://api.openai.com/v1    (room audio leaves this machine)
base URL: http://127.0.0.1:8080/v1
The model the endpoint understands. Empty takes Collie's default, gpt-transcribe.
model [gpt-transcribe]: whisper-1
API key [none]:
The language you speak, as a two-letter ISO-639-1 code — en, de, tr, ja.
LEAVE IT EMPTY to let the model detect it, which is what you want if you mix languages in one
sentence. Name one only if short clips keep coming back in a language you did not speak: a few
seconds of accented audio is too little for the model to detect from, and it guesses.
spoken language [auto-detect]: en
✓ speech-to-text configured — /home/you/.local/state/collie/stt.json (owner-only)
  Live immediately — no restart needed. The bridge re-reads this file per request.
  Check it end to end with `collie stt test`.

Chaque question ci-dessus possède un flag (--provider · --url · --model · --key · --lang), si bien qu'une exécution de provisionnement ne requiert aucun terminal. Laisser la clé vide est un mode pris en charge : un endpoint sans clé est contacté sans aucun en-tête Authorization, plutôt qu'avec un en-tête vide.

La langue parlée ne mérite d'être définie que pour un seul cas d'échec. Laissé vide (valeur par défaut), le modèle détecte la langue de lui-même, ce qui convient à une personne mélangeant deux langues dans une même phrase. Définissez-la si des enregistrements court reviennent régulièrement dans une langue que vous n'avez pas parlée : quelques secondes de signal audio avec accent ne suffisent pas pour une bonne détection, et le modèle devine. Un code à deux lettres, ou une étiquette régionale que Collie restreint pour vous (en-GBen). Cela ne concerne que le fournisseur openai-compatible ; l'endpoint codex ne prend pas de paramètre de langue, et collie stt status vous l'indique plutôt que de vous laisser croire l'inverse.

Un enregistrement long bénéficie d'un délai long. Le délai alloué par le navigateur pour un extrait audio dépend de sa taille et non d'une valeur fixe : il suppose un débit montant soutenu de 256 kb/s et y ajoute le délai d'expiration propre au fournisseur via la passerelle, ce qui laisse un peu moins de six minutes pour la taille maximale de 8 MiB. Un enregistrement que Collie a accepté d'effectuer est un enregistrement qu'il accepte d'attendre. Pendant l'envoi, Collie arrête le polling et n'affiche pas d'alerte de connexion : saturer la bande passante montante d'un téléphone avec votre propre audio n'est pas une panne de service et ne doit pas être signalé comme telle.

Est-ce que cela a fonctionné ? stt test envoie un cinquième de seconde de silence généré au fournisseur réel, une fois pour chaque format de conteneur qu'un téléphone peut enregistrer :

$ bin/collie stt test
provider: openai-compatible (http://127.0.0.1:8080/v1, model whisper-1, language en)
sending:  0.2 s of generated silence as audio/wav (the setup probe) … ✓ 214 ms
  transcript: (empty) — expected from silence, and the empty answer still proves the pipeline.
sending:  0.2 s of generated silence as audio/webm;codecs=opus (Chrome, Android, Firefox) … ✓ 198 ms
sending:  0.2 s of generated silence as audio/mp4 (Safari, iOS) … ✓ 190 ms

Une transcription vide vaut succès : le silence n'est transcrit en rien, et c'est l'aller-retour qui était validé. En cas d'échec, l'erreur précise sa nature (authentification, endpoint, format de réponse). Rechargez ensuite Collie sur le téléphone : un microphone apparaît à côté du champ de saisie. collie stt status affiche ce qui est configuré et la provenance de chaque paramètre (le fichier, ou une variable d'environnement prioritaire) ; collie stt off supprime stt.json et le bouton disparaît à nouveau, sans redémarrage dans un cas comme dans l'autre.

La prise en charge des conteneurs dépend du fournisseur

Le téléphone n'enregistre jamais en WAV. Il enregistre en Opus dans un conteneur WebM sur Chrome, Android et Firefox, ou en AAC dans un conteneur MP4 sur Safari et iOS, et envoie ces octets tels quels. Un fournisseur capable de transcrire le WAV peut quand même renvoyer une erreur 400 pour ces deux formats, et chaque dictée échoue alors avec la mention « refused » alors que stt test semble opérationnel. C'est pourquoi stt test envoie les trois extraits : le refus est détecté lors de la configuration, pas sur le téléphone.

Un cas concret, vérifié le 01/09/2026 avec POST /v1/audio/transcriptions d'OpenRouter :

formatmistralai/voxtral-small-24b-2507-sttopenai/whisper-large-v3-turbo
wavouioui
ogg/opusouioui
webm/opusnon, 400oui
mp4/m4a AACnon, 400oui

La solution de contournement réside dans le modèle, pas dans la clé : faites pointer la même clé OpenRouter vers openai/whisper-large-v3-turbo, qui accepte les quatre formats.

bin/collie stt setup --provider openai-compatible \
  --url https://openrouter.ai/api/v1 --model openai/whisper-large-v3-turbo --key <key>

Une transcription refusée indique désormais le statut amont ainsi que le conteneur sous lequel elle a été envoyée, afin que l'erreur sur le téléphone précise le format rejeté par le fournisseur. (#148, merci @drewbitt)

Zéro sortie réseau : pointez vers votre propre moteur

La raison pour laquelle openai-compatible est le fournisseur à privilégier : indiquez-lui une URL de base locale et aucun enregistrement audio de la pièce ne quitte l'hôte. Deux moteurs fournissent un endpoint de transcription compatible OpenAI : le server intégré de whisper.cpp, et mudler/parakeet.cpp (MIT). Compilez ou installez l'un ou l'autre selon ses propres instructions, lancez-le sur la boucle locale (loopback) et faites pointer --url dessus :

bin/collie stt setup --provider openai-compatible --url http://127.0.0.1:8080/v1

C'est là toute l'intégration : Collie n'impose aucun choix de moteur.

Voxtral de Mistral ne nécessite aucun support dédié, et rien d'autre qui respecte ce contrat n'en a non plus : c'est le principe même de ce point de jonction. vLLM sert les modèles Voxtral aux poids ouverts sur /v1/audio/transcriptions, donc une instance locale se configure avec le même --url que n'importe quel autre moteur. Les modèles hébergés utilisent la même requête sur la base de Mistral :

bin/collie stt setup --provider openai-compatible \
  --url https://api.mistral.ai/v1 --model voxtral-mini-latest --key <key> --lang en

Voxtral Mini Transcribe prend en charge 13 langues et accepte le même champ ISO-639-1 language que Collie envoie déjà. Vérifiez-le avec collie stt test avant de vous y fier : la mention « compatible OpenAI » est une affirmation que chaque endpoint fait pour lui-même, et ce verbe existe pour la contrôler.

Le fournisseur codex : ce que vous acceptez

collie stt setup --provider codex affiche un bloc de consentement et s'arrête jusqu'à ce que vous saisissiez yes, car la réalité est la suivante : les enregistrements vont vers un endpoint ChatGPT non documenté et non pris en charge autorisé par la connexion votre, de sorte que votre compte ChatGPT supporte les limites de débit et le risque de bannissement, et cela peut cesser de fonctionner sans préavis.

Collie interroge cet endpoint d'abord sous son propre nom. C'est seulement si l'identité directe est refusée qu'il bascule sur les en-têtes de la CLI Codex ; ce mécanisme de secours est alors inscrit dans la configuration, sous un terme que collie stt status vous relit. Collie ne lit ni ne stocke jamais ~/.codex/auth.json ; le binaire auquel vous faites déjà confiance reste le seul à le manipuler.

Les explications détaillées de tout ce qui précède (pourquoi cela a été refusé deux fois, ce qui a changé et la raison de cette structure) se trouvent dans l'ADR 0029.

Web Push (facultatif)

Désactivé par défaut. La configuration nécessite trois étapes. La bibliothèque d'envoi (web-push) est incluse comme dépendance facultative lors de la compilation :

collie push-keys     # 1. generate + write the VAPID keys
collie restart       # 2. Collie reads them at start
#                      3. on your phone: Settings → notifications

La commande push-keys génère la paire de clés et écrit COLLIE_VAPID_PUBLIC et COLLIE_VAPID_PRIVATE avec les permissions 600 dans le .env actif, à savoir ~/.config/collie/.env sur une installation binaire ou celui situé dans le dossier de configuration des plugins de Herdr sur une installation Herdr.

Passez une URI de contact en argument pour définir la revendication subject selon la RFC 8292 :

collie push-keys mailto:you@example.com

Sur les installations gérées par Herdr, ces deux étapes sont disponibles sous forme d'actions (herdr plugin action invoke push-keys --plugin herdr.collie et restart). Les actions Herdr n'acceptent pas d'arguments positionnels, donc la définition d'un subject nécessite d'exécuter la commande directement dans le shell.

Détails sur la gestion des clés :

La commande refuse d'écraser les clés existantes sauf si vous passez --force. Remplacer les clés invalide tous les abonnements actuels, obligeant chaque appareil à se réabonner avant de pouvoir recevoir à nouveau des notifications. Fournir un argument de subject sur une configuration existante met à jour uniquement l'adresse de contact et conserve les clés actuelles.

Remarque. Sur les versions de Herdr antérieures à 0.8.0, les actions restent figées à l'ensemble mis en cache lors de l'installation initiale du plugin (ADR 0006). Les actions push-keys et push-test n'apparaîtront pas tant que vous n'exécutez pas herdr plugin install. Exécutez plutôt bash scripts/collie-ctl.sh push-keys directement. Le script wrapper transmet la commande directement au binaire.

Testez le chemin de distribution sur tous les appareils abonnés :

collie push-test                     # or: push-test "Title" "Body"

La distribution prend une à deux secondes. Si la commande indique que le push est désactivé, redémarrez le service pour qu'il charge les clés générées. Si elle indique qu'aucun appareil n'est abonné, effectuez l'étape 3 dans le navigateur du téléphone.

Web Push nécessite un contexte sécurisé (HTTPS). Celui-ci est fourni par tailscale serve (certificats MagicDNS) ou par un reverse proxy externe terminant TLS (Variante C). Les configurations en HTTP brut (COLLIE_SERVE_MODE=http) n'ont pas de contexte sécurisé, et le navigateur désactive les contrôles d'abonnement dans Settings.

Collie envoie des notifications lorsqu'un agent entre dans l'état bloqué ou terminé, en plaçant le message de l'agent dans le corps. Sélectionner la notification mène directement à cet agent dans l'interface web.

Des abonnements obsolètes peuvent s'accumuler au fil du temps car les réinstallations sur l'écran d'accueil et les réinitialisations du service worker créent de nouveaux endpoints sans toujours renvoyer de code HTTP 410. Collie met à jour l'enregistrement lorsqu'un appareil se réenregistre. Vous pouvez afficher et supprimer directement les endpoints stockés :

# one line per device: service, since, user agent, endpoint tail
bin/collie push list
bin/collie push forget <substring>   # or: push forget --all

Modifier cette page sur GitHub