Files
aitrailer/HANDOVER.md
T
Melbar 7b4a98d760 Match segment window by its own action phase
For segmented beats, the repair stage now searches for the source action
window using the segment's own description first; the full beat context is
used only as a fallback or when it scores noticeably higher. The trailer-
offset shift is applied only when the beat context is actually chosen.

Also harden vision-call retries to catch read-side network errors
(TimeoutError, socket.timeout, ConnectionError, OSError) and wrap the
filter/repair loop so a transient vision failure preserves the previously
cached match instead of dropping it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 06:22:12 +02:00

5.1 KiB
Raw Blame History

Handover Notes

Stand: 2026-05-03 (Beat-20-Reparatur abgeschlossen).

Zustand

  • pytest tests/ -q → 52/52 grün.
  • python cli.py match --beat 20 --vision läuft erfolgreich durch und schreibt einen confirmed Match (Score 0.6632, scene 613, in=5284.706s, dur=0.88s).
  • Vorheriger Cache wurde nach .cache/match_results.json.bak gesichert.
  • Kein offener PR; lokale Änderungen sind committed (siehe letzter Commit).

Was zuletzt geändert wurde und warum

1. cli.pyrealign_window wählt das Action-Window pro Segment

In _filter_semantically_invalid_vision_matches.realign_window:

  • Vorher: find_action_window_in_scene(action_beat or check_beat, …) — bei segmentierten Beats wurde immer der ganze Beat als semantischer Kontext benutzt. Das hat für Beat 20 die Source-Position auf die Kuss-Phase (5270 s) gelegt, obwohl das sichtbare Segment nur "approaching and pulling apart" zeigt — diese Phase liegt im Source erst um 5284 s.
  • Jetzt: Es werden zwei Fenster gesucht (Segment-Beschreibung und Beat- Beschreibung). Der Beat-Kontext gewinnt nur bei deutlichem (>0.06) Score- Vorsprung. Der Trailer-Offset-Shift (visible_content_offset) wird nur angewendet, wenn tatsächlich der Beat-Kontext benutzt wurde — sonst zeigt das Segment-Fenster bereits auf die richtige Phase.

Effekt für Beat 20: 5270.118 → 5284.706, Score 0.6449 (provisional) → 0.6632 (confirmed).

2. cli.py — Filter-/Repair-Stufe ist crash-tolerant

_filter_semantically_invalid_vision_matches hat den Per-Result-Body in eine lokale Funktion _filter_repair_one herausgezogen und in einen try/except verpackt. Wenn die Reparatur abbricht (z. B. weil Vision-API mitten in der Antwort wegfällt), wird der bisher gecachte Treffer behalten statt komplett verworfen.

3. src/llm/vision_cache.py — Vision-Retry für Lesefehler

_call_vision_model fängt jetzt zusätzlich TimeoutError, socket.timeout, ConnectionError und OSError während des Antwort-Lesens und retryt mit demselben Backoff wie HTTP-/URL-Fehler. Die Auslöse-Bedingung war ein 24-h-DSL-Disconnect mitten im Lauf; davor wurde der Match-Lauf hart abgebrochen und der Cache stand auf "kein Match".

4. README.md

Zwei kurze Absätze ergänzt, die (1) die Segment-vs-Beat-Window-Auswahl und (2) das neue Crash-/Netzfehler-Verhalten beschreiben.

Nicht angefasst, aber relevant für die Übergabe

  • Der vollständige FFmpeg-Vollscan liefert für Beat 20 weiterhin keinen bestätigten Treffer (final score 0.419 < provisional 0.430). Den Confirmed-Match liefert die Action-Window-Reparatur. Das ist erwartet: das sichtbare Segment ist visuell sehr generisch (Two-Shot Profil mit unscharfem Hintergrund), die korrekte Phase fällt erst durch die semantische Aktionsbeschreibung auf.
  • Die candidate_points-Schleife in realign_window (lines ~700765) sucht nur ±~2 s um start_s herum. Solange start_s jetzt aus dem Segment- Fenster kommt, liegt der korrekte Source-Punkt in diesem Bereich. Wenn künftig Beats mit längeren visiblen Inseln auftauchen, kann diese Range zu eng werden — dann den Suchradius erweitern statt das Window-Picking rückgängig machen.
  • Es gibt keine Tests für _filter_semantically_invalid_vision_matches oder realign_window. Wer das anfasst, sollte Beat 20 als Live-Smoke-Test benutzen (siehe unten).

Reproduktion / Smoke-Test

.\.venv\Scripts\Activate.ps1
python cli.py match --beat 20 --vision

Erwartet: Beat 20: realigned semantically valid long scene by motion/action windows, danach is_confirmed: true für Beat 20 in .cache/match_results.json mit in_point_s ≈ 5284.7 und match_score ≥ 0.65.

Wenn das fehlschlägt:

  1. python -m pytest tests/ -q — falls rot, ist die Codebasis selbst kaputt.
  2. .cache/vision_descriptions.json prüfen — die Schlüssel beat:20:73.560:74.680:… und action_window:613:5282.390:5285.430:… müssen existieren, sonst ruft Vision live ab (kostet Credits; braucht Netz).
  3. match_results.json.bak zurückspielen, falls der Cache zerschossen ist.

Offene Risiken / Bekannte Schwächen

  • Die Schwelle 0.06 für "Beat-Kontext gewinnt" in realign_window ist kalibriert an Beat 20. Andere Beats sollten auch durchlaufen werden, bevor weitere Beats angefasst werden — am besten ein voller python cli.py match ohne --beat und Diff der match_results.json gegen .bak.
  • Die Filter-/Repair-Stufe kann durch Vision-Calls minutenlang laufen. Das ist nicht neu, aber bei Netzproblemen sehr sichtbar.
  • Die _filter_repair_one-Funktion bekommt viele Argumente durchgereicht (closure-Variablen aus dem Parent). Bei einer nächsten Iteration könnte das in eine kleine Klasse umgebaut werden.

Useful greps

  • find_action_window_in_scene — semantische Action-Window-Suche (Vision).
  • _reference_scoreable_segments — bestimmt die sichtbaren Inseln eines Beats.
  • estimate_usable_source_duration — kürzt Match-Clips, wenn die Source vor Beat-Ende in eine andere Phase wechselt.
  • _filter_semantically_invalid_vision_matches — Eintrittspunkt der Repair-Stufe in cli.py.