Beat sync (Syncro battement)
Scripts dans scripts/ :
beats.py MUSIC --out beats.json [--start S --end E]— tempo, battements, estimation du downbeat, onsets forts (hits), énergie RMS par seconde.timemap.py— construit une carte temporelle à vitesse variable (rampes de vitesse) et la rend image par image avec ffmpeg.
1. Analyser la musique
python beats.py song.mp3 --out edit/beats.json
Produit tempo, beats (s), downbeats (tous les 4e temps depuis la phase la plus forte), hits (onsets forts : caisse claire / grosse caisse / drops), energy par 0,5 s.
Lecture du résultat :
- Période du battement
P = 60 / BPM. À 30 ips, un battement à 120 BPM = 15 images. - Les hits ne sont pas toujours des battements. Accents vocaux, fins de montée, drops. Pour les tendances « edit audio », les points de coupe sont les hits, pas le métronome.
- librosa peut se verrouiller sur le demi ou double tempo. Vérification : pop typique 90-130 BPM, trap 130-160 (souvent ressenti en half-time), EDM 120-128, phonk 130-150. Si la grille détectée semble fausse dans un test image par image, diviser ou doubler.
- La courbe d'énergie trouve le drop/refrain : plus grand saut RMS après une section calme.
2. Choisir la fenêtre musicale
- Format court : 7-20 s. Commencer la fenêtre sur un downbeat et finir sur un downbeat ou à la fin d'une phrase (4 ou 8 mesures).
- Mettre le visuel le plus fort sur le drop. Si le drop est à 12 s dans la chanson et que vous le voulez 3 s après le début du reel, la fenêtre commence à 9 s.
- Sons tendance sur Instagram/TikTok : le son intégré à l'application commence à un point fixe. Si la publication finale utilisera le son intégré, alignez votre montage sur ce point de départ, et exportez une version avec le fichier audio de référence comme guide.
- Fondre la musique en 10-50 ms (éviter le clic) sauf si la fenêtre commence sur une attaque, et fondre en sortie sur 0,3-1,5 s, ou finir sur un hit sec.
3. Construire la grille et placer les événements
fps = 30
fr = lambda t: round(t * fps) # arrondir chaque événement à l'image la plus proche
U = beat_period / 2 # sous-unité (croches) si la chanson est chargée
- Coupes : sur les battements pour le flux, sur les hits pour l'impact. Couper à chaque battement est épuisant ; couper tous les 2 ou 4 battements et utiliser les coupes à chaque battement uniquement pour des accélérations (2-4 s) avant le drop.
- Anticipation : une coupe placée 1-2 images avant le battement semble plus serrée sur téléphone (latence audio + perception). Testez les deux et choisissez de manière cohérente.
- Flashs / secousses / zooms punch : sur les hits, 2-6 images, avec décroissance.
- Texte : le mot apparaît sur la syllabe vocale ou sur le battement ; maintenir au moins 0,4 s par mot pour les mots isolés, ~0,25 s/mot pour les lignes lues en rythme.
- Changement de vitesse / effet : sur les downbeats ou les drops.
- Gardez un tableau (
timing.json) de chaque événement avec sa raison musicale ; le script de construction le lit.
4. Rampes de vitesse (velocity)
Une rampe de vitesse est une carte temporelle src_t = f(out_t). Construisez-la à partir de segments avec vitesse adoucie :
# courbe de vitesse : 1x ... rampe jusqu'à 4x entre les hits ... revient à 0.3x sur le hit
segments = [(out_start, out_end, speed_start, speed_end, ease)]
- Adoucissez la vitesse avec lissage smoothstep/cubique ; un saut instantané 1x→4x ressemble à un défaut.
- Lent (0,2-0,5x) sur le hit, rapide (2-5x) entre les hits. L'image du hit montre l'action clé (impact, virage, regard).
- Les sections lentes nécessitent des sources haute fréquence ou une interpolation d'images (
minterpolate, Resolve Speed Warp, RIFE). - Ajoutez du flou de mouvement dans les parties rapides (
tmix=frames=3ou mélange d'images dans le rendu de la carte temporelle) pour éviter le scintillement. - Cas réel : plan de bureau vu du dessus, parties avec mouvement de caméra gardées à 1x, parties statiques à 5,6x, chaque changement de vitesse sur un hit fort ; un passage par flux optique (OpenCV LK + similarité RANSAC) a localisé automatiquement les mouvements de caméra (voir
motion-tracking).
timemap.py rend une carte temporelle en tirant l'image source correcte pour chaque image de sortie (avec option de mélange d'images) — exact et plus simple que d'enchaîner des filtres setpts.
5. Correspondre au timing d'un reel de référence
- Téléchargez/obtenez la référence ; extrayez son audio.
- Détectez ses coupes :
ffmpeg -i ref.mp4 -vf "select='gt(scene,0.3)',showinfo" -f null - 2>&1 | grep pts_time. - Détectez les battements sur son audio ; exprimez chaque coupe comme un index de battement ou un décalage → c'est le modèle rythmique.
- Mesurez les instants d'affichage du texte en parcourant les images (précision 1/30 s) autour des changements.
- Reconstruisez avec vos images sur la même grille (voir
reference-matching).
6. Vérifier
- Détectez les scènes dans le rendu ; chaque temps de coupe × ips doit correspondre à son image prévue (±0).
- Superposez une piste de clics sur les battements dans un rendu de débogage (
aevalsrcimpulsions sinusoïdales) et capturez des images aux hits. - Vous ne pouvez pas écouter : rapportez les chiffres (images de coupe prévues vs mesurées) et demandez à l'utilisateur de vérifier à l'oreille.