Was macht beat-sync?
Skripte in scripts/:
beats.py MUSIK --out beats.json [--start S --end E]– Tempo, Beats, Downbeat-Schätzung, starke Onsets (Hits), RMS-Energie pro Sekunde.timemap.py– Erstellt eine variable Geschwindigkeits-Zeitkarte (Speed Ramps) und rendert sie frame-genau mit ffmpeg.
1. Musik analysieren
python beats.py song.mp3 --out edit/beats.json
Gibt tempo, beats (s), downbeats (jeder 4. Beat ab der stärksten Phase), hits (starke Onsets: Snare/Kick/Drops), energy pro 0,5 s aus.
Ergebnis interpretieren:
- Beat-Periode
P = 60 / BPM. Bei 30 fps entspricht ein Beat bei 120 BPM = 15 Frames. - Hits sind nicht immer Beats. Vokale Akzente, Risers-Endungen, Drops. Bei „Edit-Audio“-Trends sind die Schnittpunkte die Hits, nicht das Metronom.
- librosa kann auf halbes oder doppeltes Tempo einrasten. Plausibilitätscheck: typischer Pop 90–130 BPM, Trap 130–160 (oft als half-time empfunden), EDM 120–128, Phonk 130–150. Fühlt sich das erkannte Raster in einem Frame-Grab-Test falsch an, halbieren/verdoppeln.
- Die Energiekurve findet den Drop/Chorus: größter RMS-Sprung nach einer ruhigen Passage.
2. Songfenster wählen
- Kurzform: 7–20 s. Fenster auf einem Downbeat beginnen und auf einem Downbeat oder am Ende einer Phrase (4 oder 8 Takte) enden.
- Das stärkste Bild auf den Drop legen. Liegt der Drop bei 12 s im Song und soll er 3 s im Reel erscheinen, beginnt das Fenster bei 9 s.
- Trend-Sounds auf Instagram/TikTok: Der In-App-Sound beginnt an einem festen Punkt. Verwendet der finale Post den In-App-Sound, den Schnitt auf diesen Startpunkt ausrichten und eine Version mit dem Referenzaudio als Orientierung exportieren.
- Musik einblenden in 10–50 ms (Klicken vermeiden), es sei denn, das Fenster beginnt auf einem Transienten, und ausblenden über 0,3–1,5 s oder auf einem harten Hit enden.
3. Raster erstellen und Ereignisse platzieren
fps = 30
fr = lambda t: round(t * fps) # jedes Ereignis auf den nächsten Frame runden
U = beat_period / 2 # Unter-Beat-Einheit (Achtel) wenn der Song dicht ist
- Schnitte: auf Beats für den Fluss, auf Hits für Impact. Jeden Beat zu schneiden ist ermüdend; alle 2 oder 4 Beats schneiden und nur für Bursts (2–4 s) vor dem Drop jeden Beat nutzen.
- Antizipation: ein Schnitt 1–2 Frames vor dem Beat fühlt sich auf Smartphones (Audiolatenz + Wahrnehmung) straffer an. Beides testen und einheitlich verwenden.
- Blitze / Shakes / Zoom-Punches: auf Hits, 2–6 Frames, abklingend.
- Text: Wort erscheint auf der Vokalsilbe oder auf dem Beat; mindestens 0,4 s pro Wort bei einzelnen Wörtern, ~0,25 s/Wort bei im Rhythmus gelesenen Zeilen.
- Geschwindigkeits-/Effektwechsel: auf Downbeats oder Drops.
- Eine Tabelle (
timing.json) führen mit jedem Ereignis und seiner musikalischen Begründung; das Build-Skript liest sie.
4. Speed Ramps (Velocity)
Ein Speed Ramp ist eine Zeitkarte src_t = f(out_t). Aus Segmenten mit weichem Geschwindigkeitsübergang aufbauen:
# Geschwindigkeitskurve: 1x ... hoch auf 4x zwischen Hits ... zurück auf 0,3x auf dem Hit
segments = [(out_start, out_end, speed_start, speed_end, ease)]
- Geschwindigkeit mit Smoothstep/Cubic ein- und ausgleiten; ein sofortiger 1x→4x-Sprung wirkt wie ein Glitch.
- Langsam (0,2–0,5x) auf dem Hit, schnell (2–5x) zwischen Hits. Der Hit-Frame selbst zeigt die Schlüsselaktion (Impact, Drehung, Blick).
- Langsame Abschnitte benötigen High-Fps-Quellen oder Frame-Interpolation (
minterpolate, Resolve Speed Warp, RIFE). - Bewegungsunschärfe in schnellen Teilen hinzufügen (
tmix=frames=3oder Frame-Blending im Zeitkarten-Renderer), um Stroboskopeffekte zu vermeiden. - Praxisbeispiel: Overhead-Schreibtischaufnahme, Kamerabewegungsteile bei 1x gehalten, statische Teile bei 5,6x, jeder Geschwindigkeitswechsel auf einem starken Hit; ein Optical-Flow-Durchlauf (OpenCV LK + RANSAC-Ähnlichkeit) ortete die Kamerabewegungen automatisch (siehe
motion-tracking).
timemap.py rendert eine Zeitkarte, indem es für jeden Ausgabeframe den richtigen Quellframe (optional mit Frame-Blending) zieht – exakt und einfacher als das Verketten von setpts-Filtern.
5. Timing eines Referenzvideos nachbilden
- Referenz herunterladen/beschaffen; dessen Audio extrahieren.
- Dessen Schnitte erkennen:
ffmpeg -i ref.mp4 -vf "select='gt(scene,0.3)',showinfo" -f null - 2>&1 | grep pts_time. - Beats auf dessen Audio erkennen; jeden Schnitt als Beat-Index oder Offset ausdrücken → das ist die Rhythmusvorlage.
- Text-Ein/Aus-Zeiten messen, indem Frames (1/30 s Genauigkeit) um Änderungen herum durchgegangen werden.
- Mit eigenem Material auf demselben Raster neu aufbauen (siehe
reference-matching).
6. Überprüfen
- Scene-Detect des Renders; jede Schnittzeit × fps sollte dem geplanten Frame entsprechen (±0).
- Einen Click-Track auf Beats in einem Debug-Render überlagern (
aevalsrc-Sinustöne) und Frames auf Hits greifen. - Sie können nicht zuhören: die Zahlen melden (geplante vs. gemessene Schnittframes) und den Benutzer bitten, nach Gehör zu prüfen.