DTTSVG — MKII
Version stable adapté HA et professionelle
Historique des versions
Version V1
Changements :
DTTSVG, du script Flask au custom component
1. Point de départ
Le projet était un serveur séparé : app.py (Flask) + Dockerfile/docker-compose.yml + requirements.txt, avec ffmpeg système et un script à coller dans HA. Inconvénients : processus à maintenir à part, pas d'intégration GUI, dépendance à ffmpeg binaire.
2. Transformation en custom component
Tout l'ancien code a été supprimé (git rm : app.py, Docker, HA_SCRIPT, output/). Le composant vit dans custom_components/dttsvg/ :
Fichier Rôle
manifest.json metadata : config_flow, deps ["tts","http"], requirements ["av>=11.0.0"] (PyAV = ffmpeg embarqué), min HA 2023.5
const.py clés de configuration, constantes, événement
config_flow.py config flow GUI en 5 étapes + options flow
tts_compat.py couche d'abstraction entre les 3 architectures TTS de HA
video.py génération MP4 (onde + fond + audio) avec PyAV/numpy/Pillow
media_player.py entité « écran » virtuelle qui relaie vers l'écran réel
__init__.py orchestration : service speak, volume, événement
view.py endpoint /api/dttsvg/video/{jeton}.{fichier} sans auth
translations/fr.json + en.json, background.png, images/ UI et ressources
3. Fonctionnalités construites
Config flow GUI : moteur TTS (liste dynamique) → langue → voix → écran cible → options visuelles ; options flow identique pour modification. Détection auto du moteur par défaut, entrée unique (unique_id + abort si déjà configuré).
Entité media_player.dttsvg_screen : reflète l'état de l'écran réel (play/pause/volume/…), relaie toutes les commandes vers lui, expose last_video_url/last_video_path/target_entity.
Service dttsvg.speak (text + target optionnel) : TTS → vidéo → cast.
Pipeline vidéo PyAV : décodage audio tout format → mono float32 44,1 kHz → onde (couleur/hauteur réglables) sur fond → H.264 + AAC dans un MP4, en async_add_executor_job.
Volume intelligent : mode fixe ou jour/nuit (via sun.sun).
Mute anti-son de lancement : mute → génération → volume → cast → 0,2 s → unmute (mise en place au fil des itérations).
Endpoint sécurisé : jeton aléatoire (16 octets) dans l'URL, requires_auth=False pour le Chromecast, média dans media/dttsvg/ (repli storage/), URL basée sur external_url.
Événement dttsvg_video_generated (text/url/path) pour les automations.
4. Compatibilité HA 2026 (les 8 bugs rencontrés en environnement réel)
# Problème Cause Correction
1 Config flow vide, aucun champ la liste des moteurs lisait l'ancienne structure hass.data["tts"] tts_compat : détection des 3 mondes (entités 2026, providers legacy, audio stream)
2 TypeError: async_show_form() got an unexpected keyword argument 'schema' paramètre renommé schema → data_schema helper _async_show_form qui inspecte la signature au chargement ; options= de async_create_entry vérifié toujours valide
3 AttributeError: selector has no attribute 'ColorSelector' remplacé par ColorRGBSelector (liste [r,g,b]) sélecteur compatible + normalisation en "#rrggbb" au stockage ; _parse_color accepte hex, rgb(), liste
4 'dict_values' object has no attribute 'get' hass.data["media_player"] devenu EntityComponent priorité à get_entity(), repli dict/itération
5 Lien vidéo → 404 la vue cherchait {jeton}.{uuid}.mp4 alors que le fichier est {uuid}.mp4 retrait du préfixe jeton avant résolution du chemin
6 Warning écran ×4 + resélection sans effet entité réelle « unavailable » + _target figé à la création de l'entité gardes sautent mute/volume si introuvable/indisponible ; listener d'options met à jour la cible à chaud
7 Audio non décalé, seule l'onde l'était l'audio était encodé dès pts=0 silence de start_delay préfixé à l'audio (onde + audio synchronisés)
8 Onde trop basse / pas centrée bande collée en bas centrage vertical au milieu de l'écran
5. Validation effectuée
Tests locaux avec mocks : compat TTS 3 mondes (ALL TESTS PASSED), _parse_color, sélecteurs de couleur 2 mondes, endpoint vidéo.
Test d'encodage réel PyAV : silence 0→2 s puis audio + onde ensemble, durées cohérentes, position verticale vérifiée par analyse de frames.
py_compile sur tous les fichiers après chaque correctif.
État actuel
Le composant est fonctionnel dans ton HA (config flow OK, génération OK, sync audio/onde OK). Restent à faire dans une suite : test réel du cast (Nest Hub en ligne), et à terme HACS (icône/logo déjà prêts dans images/).
Version 0
Changements :
Nouvelle identité visuelle
Plan de fonctionnalité