SKILL : Subtitles Studio — Bibliothèque modulaire de légendes dynamiques (subtitles_studio)
1. Vue d'ensemble pour l'IA
Dépôt officiel : https://github.com/NicolasCoder/subtitles_studio.git
Ce dossier est une boîte à outils 100% autonome et partageable pour générer des légendes dynamiques de type Lockup (un mot principal géant au centre avec des mots plus petits insérés dans les creux réels des ascendantes/descendantes de la police) pour HyperFrames (1080x1920 @ 30fps).
Architecture du dossier
subtitles_studio/
├── SKILL.md # Ce guide complet pour les agents IA
├── README.md # Guide rapide pour les humains
├── requirements.txt # fonttools, brotli, Pillow, numpy
├── cli.py # Interface en ligne de commande prête à l'emploi
├── fonts/ # Polices .woff2 locales pré-packagées (+ téléchargement automatique via Google Fonts)
├── caption_kit/ # Paquet Python importable
│ ├── __init__.py # API publique
│ ├── nesting.py # Moteur de géométrie de glyphes réelle + auto-téléchargement Google Fonts
│ ├── grouper.py # Groupeur intelligent mot par mot (maintien >= 0.38s, anti-sclignotement)
│ ├── renderer.py # Compilateur HTML/CSS/GSAP et chargeur dynamique du dossier styles/
│ └── transcribe.py # Transcription mot par mot (CrisperWhisper / faster-whisper / whisper)
├── styles/ # MODULES DE STYLE (1 fichier .py ou .json = 1 style partageable !)
│ ├── _TEMPLATE_NOVO_ESTILO.py # Modèle commenté pour créer de nouveaux styles
│ ├── bold_ciano.py # Bold Social — Cyan (#3de0c8)
│ ├── bold_vermelho.py # Bold Social — Rouge (#ff3355)
│ ├── bold_roxo.py # Bold Social — Violet (#b855ff)
│ ├── bold_dourado.py # Bold Social — Doré (#ffd24a)
│ ├── editorial.py # Editorial Mix (Inter 900 + Playfair Display Italic)
│ ├── gold_script.py # Gold Script (Pinyon Script + Oswald)
│ └── poster_impact.py # Poster Impact (League Gothic + Montserrat 900)
└── examples/ # Exemples prêts à tester (en portugais)
├── demo_words_pt.json # Mots avec horodatages (portugais)
└── demo_groups_pt.json # Groupes lockup/plain (portugais)
2. Utilisation en ligne de commande (cli.py)
# 1. Lister tous les styles installés dans styles/
python cli.py --list-styles
# 2. Générer une démo rapide pour n'importe quel style
python cli.py --demo --style bold_roxo
# 3. Générer à partir d'un JSON de mots avec horodatages (word, start, end)
python cli.py --words examples/demo_words_pt.json --style bold_vermelho --out output/mon_test
# 4. Changer la couleur d'accent à la volée sans modifier le style
python cli.py --words examples/demo_words_pt.json --style bold_ciano --accent "#00ff88"
# 5. Transcrire une vidéo/audio (.mp4/.wav/.mp3) et générer les légendes synchronisées
python cli.py --media ma_video.mp4 --lang pt --style bold_dourado --video ma_video.mp4
3. Utilisation en Python (Intégration dans un projet HyperFrames)
Lorsque vous assemblez une composition complète dans HyperFrames (avec A-roll, B-roll, motions, SFX et musique), importez caption_kit et utilisez render_embeddable() :
import sys
sys.path.insert(0, "chemin/vers/legendas_dinamicas_kit")
from caption_kit import build_groups_from_words, render_embeddable
# 1. `words` est une liste [{"word": "Criar", "start": 0.15, "end": 0.42}, ...]
groups = build_groups_from_words(words, min_hold=0.38)
# 2. Génère le CSS, le DOM (avec <span> internes pour zéro avertissement lint) et le JS GSAP :
caps_css, caps_dom, caps_js, report = render_embeddable(
groups,
prefix="v1", # Préfixe unique des IDs (#v1-g0, #v1-g1...)
style_name="bold_vermelho", # N'importe quel fichier dans styles/<nom>.py
accent_override=None, # Ou passez e.g. "#ff3355" pour changer uniquement la couleur
y_lockup=0.74, # Zone de sécurité Reels (1300-1560px en 1080x1920)
y_plain=0.75,
track_index=3,
z_index=95,
)
Il suffit ensuite d'injecter :
{caps_css}dans la balise<style>de la composition ;{caps_dom}dans la<div id="root" ...>;{caps_js}dans la balise<script>juste aprèsconst tl = gsap.timeline({ paused: true });.
4. Créer un nouveau style partageable (Système de plugins dans styles/)
Le système de styles a été conçu pour être 100% plug-and-play :
- Tout fichier
.py(ou.json) placé dans le dossierstyles/(dont le nom ne commence pas par_) est découvert automatiquement parload_styles(). - Pour créer un nouveau style à la demande de l'utilisateur :
- Copiez
styles/_TEMPLATE_NOVO_ESTILO.pyversstyles/<nom_du_style>.py. - Modifiez le dictionnaire
STYLE = { ... }. - Si vous utilisez une nouvelle police de Google Fonts (ex :
"Bebas Neue","Poppins","Syne"), pas besoin de téléchargement manuel : le moteurcaption_kit/nesting.pytélécharge automatiquement les fichiers.woff2depuis Google Fonts lors de la première exécution et les sauvegarde dansfonts/<famille>/! - Pour que l'utilisateur partage ce style avec quelqu'un d'autre, il suffit d'envoyer ce seul fichier
styles/<nom_du_style>.py!
- Copiez
Anatomie du dictionnaire STYLE
STYLE = {
"id": "neon_cyber",
"label": "Neon Cyber (Montserrat 900 + Glow Vert)",
# Mot principal (centre du lockup)
"main_font": "Montserrat",
"main_weight": 900,
"main_style": "normal",
"main_track": -0.05,
"main_case": "none", # IMPORTANT : utilisez "none" pour préserver les ascendantes/descendantes et permettre l'encastrement ! Utilisez "upper" uniquement si "nest_mode": "overlap".
"main_lh": 0.80,
"main_css": "color:#ffffff;text-shadow:0 10px 34px rgba(0,0,0,.6);",
"max_px": 280,
# Petits mots de soutien (au-dessus et en dessous)
"small_font": "Inter",
"small_weight": 800,
"small_style": "normal",
"small_track": -0.03,
"small_case": "none",
"small_css": "color:#ffffff;text-shadow:0 5px 20px rgba(0,0,0,.6);",
"small_scale": 0.44, # 0.25 à 0.50 de la taille du mot principal
# Légende simple continue
"plain_font": "Inter",
"plain_weight": 800,
"plain_style": "normal",
"plain_case": "none",
"plain_css": "color:#ffffff;text-shadow:0 5px 20px rgba(0,0,0,.6);",
# Couleur d'accent et éclat
"accent": "#00ff88",
"accent_extra_css": "text-shadow:0 0 24px rgba(0,255,136,0.55);",
"shine": ("#ffffff", "rgba(0,255,136,.9)"),
# Géométrie et animations
"tilt": (-2, 2), # Inclinaison (degrés) de la ligne du haut et de la ligne du bas
"clear": 0.03, # Jeu minimal entre les cadres
"variants": ("slam", "letters", "rise", "blur"),
}
5. Règles d'or de qualité (apprises en production)
- Temps de lecture (Maintien minimal) : Le groupeur (
caption_kit/grouper.py) garantit au moins0.38savec la phrase complète à l'écran avant de changer de bloc. Quand le débit de parole est rapide, il compresse l'échelonnement d'entrée des mots pour ne jamais couper la fin de la phrase. - Ordre chronologique : Les lignes entrent toujours dans l'ordre réel où elles sont prononcées (
above→main→below). - Zone de sécurité Instagram Reels / TikTok (
1080x1920) :- Par défaut
y_lockup=0.74(~1420px), ce qui se situe dans la zone de sécurité1300–1560px(en dessous du visage et des cartes de motion, et au-dessus des boutons inférieurs du Reels).
- Par défaut
- Synchronisation audio dans HyperFrames :
- Si la vidéo utilise un audio coupé en plusieurs segments, n'utilisez jamais plusieurs balises
<audio>pointant vers le même fichier avecdata-media-start(cela décale l'audio dans HyperFrames). Découpez toujours l'audio en un seul fichier.wavcontinu et utilisez une seule balise<audio data-start="0.000">.
- Si la vidéo utilise un audio coupé en plusieurs segments, n'utilisez jamais plusieurs balises