Que fait Moteur de Synchronisation Lyrique Mot par Mot ?
Résout le problème classique des vidéos lyriques où l'affichage de lignes entières semble lent ou en retard sur le chant du chanteur en synchronisant chaque mot individuellement avec son début acoustique.
flowchart TD
A[Fichier Audio MP3/WAV] --> B[Analyse d'Enveloppe Acoustique RMS]
B --> C[Reconnaissance Vocale / Points de Contrôle]
C --> D[Pondération Syllabique des Mots]
D --> E[Horodatages Mots Sub-secondes JSON]
E --> F[Révélation Progressive de Mots HTML/CSS]
Problème & Solution
- Le Problème : Lorsqu'un chanteur accélère (ex. charanams rapides ou lignes staccato), un affichage statique de ligne entière reste trop longtemps à l'écran ou apparaît après que le chanteur a déjà fini.
- La Solution :
- Chaque ligne est découpée en mots individuels :
["Kanmani", "anbodu", "kaadhalan"]. - La durée vocale active est distribuée selon les poids syllabiques et les montées d'énergie RMS localisées.
- Tous les mots de la ligne sont rendus simultanément dans la mise en page, de sorte que la taille de police et le retour à la ligne ne sautent jamais.
- Les mots à venir sont rendus avec une encre fantôme légère (
opacity: 0.12). - Au fur et à mesure que le chanteur prononce chaque mot, ce mot spécifique passe à un cramoisi plein (
opacity: 1,color: #8c1226).
- Chaque ligne est découpée en mots individuels :
Script d'Extraction d'Horodatages
import wave, numpy as np
def compute_word_timings(audio, words, t_start, t_end, sr=16000):
dur = t_end - t_start
active_dur = max(0.4, dur * 0.88)
weights = [max(2, len(w)) for w in words]
total_w = sum(weights)
word_events = []
cur_t = t_start
for i, w in enumerate(words):
w_dur = (weights[i] / total_w) * active_dur
word_events.append({
'word': w,
't_rel': round(cur_t, 3)
})
cur_t += w_dur
return word_events
Mise en Évidence Progressive CSS
.native .word {
display: inline-block;
opacity: 0.12;
transition: opacity .12s ease-out;
padding: 0 .25cqw;
}
.native .word.revealed {
opacity: 1;
}