🚀 Je construis un moteur de dictée en PHP (Flow + Symfony + Whisper.cpp)
le 22 février 2026
Construire un moteur de dictée en 2026 est trivial.
Construire une architecture propre autour d’un moteur de dictée est plus intéressant.
Cet article présente Flowvox, un MVP de moteur de transcription audio développé en PHP, en s’appuyant sur :
- Symfony
- Symfony Messenger
- Flow : orchestrateur maison
- ffmpeg
- whisper.cpp
Le code source est disponible en open source : 👉 https://github.com/darkwood-com/flowvox
L’objectif n’était pas simplement d’utiliser Whisper. L’objectif était de structurer correctement le pipeline.
Le problème : la transcription n’est qu’une étape
Un moteur vocal minimal peut se résumer à :
Audio → Texte
Mais dans un système réel, plusieurs contraintes apparaissent :
- Déclenchement start / stop
- Finalisation propre du fichier audio
- Gestion d’état du recorder
- Orchestration des étapes
- Extension vers post-traitement (résumé, LLM, analyse)
La question devient alors :
Comment modéliser un pipeline audio propre, extensible et maîtrisé ?
Stack technique
Le MVP repose sur :
- PHP 8+
- Symfony
- Symfony Messenger
- Flow (orchestrateur)
- ffmpeg (captation audio locale)
- whisper.cpp (transcription open source locale)
Aucune API distante. Aucun service cloud. Transcription 100% locale.
Architecture générale
L’architecture est organisée en trois flows :
InputProvider → Recorder → Transcribe
Chaque étape est isolée et responsable d’un rôle précis.
InputProviderFlow
Responsabilité :
- Écouter les commandes
voice:startetvoice:stop - Émettre un
VoiceControlEvent
Les commandes CLI déclenchent des messages via Symfony Messenger.
Le worker, en arrière-plan, reçoit ces événements et les injecte dans Flow.
Ce découplage permet :
- Un contrĂ´le granulaire
- Une gestion multi-session
- Une séparation claire des responsabilités
RecorderFlow
Responsabilité :
- Piloter une instance de
VoiceRecorder - Gérer le cycle de vie d’un processus
ffmpeg
Le VoiceRecorder encapsule un processus système lancé via :
Symfony\Component\Process\Process
Problème central :
Comment gérer proprement start / stop sans corrompre le fichier audio ?
Trois états sont explicitement modélisés :
idlerecordingstopping
Lors d’un stop, un SIGINT est envoyé à ffmpeg afin de finaliser correctement le header WAV.
L’état stopping évite :
- Les double-start
- Les conflits concurrents
- Les fichiers incomplets
Le processus est maîtrisé, pas subi.
TranscribeFlow
Responsabilité :
- Recevoir un fichier WAV finalisé
- Lancer whisper.cpp
- Produire un texte transcrit
Whisper est exécuté localement via CLI.
Le MVP reste volontairement simple :
- Pas de streaming
- Pas de chunking temps réel
- Une transcription synchrone
L’objectif est de valider l’intégration et l’orchestration.
Worker et orchestration
Le moteur fonctionne via un worker Symfony :
php bin/console voice:worker
Ce worker :
- Instancie Flow
- Enregistre les flows
- Écoute Symfony Messenger
- Ordonne l’exécution des étapes
Commandes disponibles :
voice:start
voice:stop
voice:worker-list
Le flux complet devient :
voice:start
→ Recorder démarre
→ voice:stop
→ Recorder finalise
→ TranscribeFlow s’exécute
→ Texte produit
Sans état global externe.
Pourquoi Flow ?
Flow permet :
- Une architecture orientée pipeline
- Des stratégies d’Input Processing (IP Strategy)
- Une gestion explicite des événements
- Une séparation nette entre orchestration et logique métier
Le système n’est pas couplé à Whisper.
Whisper est une implémentation. Flow est la structure.
Ce que valide le MVP
- Gestion propre d’un processus système
- Modélisation explicite des états
- Orchestration événementielle
- Extensibilité du pipeline
Ce n’est pas un produit.
C’est une base architecturale.
Évolutions possibles
Les prochaines itérations naturelles :
- Streaming par chunk audio
- Transcription parallèle
- Post-traitement LLM
- Intégration desktop
- Support mobile
- Batching multi-modèles
Mais ces évolutions ne changent pas le cœur :
Une architecture claire. Une orchestration maîtrisée. Un pipeline extensible.
Code source
Le dépôt open source est disponible ici :
👉 https://github.com/darkwood-com/flowvox
Contributions, suggestions et retours sont les bienvenus.
Conclusion
Construire un moteur vocal en PHP est simple.
Construire une architecture propre autour d’un moteur vocal est plus intéressant.
Flowvox valide un principe :
La transcription n’est qu’un composant. L’orchestration est la véritable structure.