Clamp cutter clips to source scene start

This commit is contained in:
Melbar
2026-05-08 14:11:02 +02:00
parent 430a81a988
commit bdc9e4ab31
6 changed files with 26 additions and 2 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+3
View File
@@ -170,6 +170,9 @@ Der zusätzliche Hi-Res-Phasenrefine bleibt lokal um den bereits validierten
Inpoint und übernimmt nur klare Verbesserungen. Er darf keine ganze lange Inpoint und übernimmt nur klare Verbesserungen. Er darf keine ganze lange
Dialogszene nach ähnlichen Layouts durchsuchen, weil sonst dieselbe Location Dialogszene nach ähnlichen Layouts durchsuchen, weil sonst dieselbe Location
mit anderer Gestik als falsche Phase gewinnen kann und die Laufzeit explodiert. mit anderer Gestik als falsche Phase gewinnen kann und die Laufzeit explodiert.
Report-Clips werden zusätzlich an den bekannten Source-Szenenstart geklemmt,
damit ein knapp vor der Schnittkante liegender Inpoint nicht mit Frames der
vorherigen Einstellung beginnt.
## Multi-Shot-Beats ## Multi-Shot-Beats
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

+22 -1
View File
@@ -401,6 +401,7 @@ def collect_rows(
source_path: Path, source_path: Path,
with_stills: bool, with_stills: bool,
with_clips: bool, with_clips: bool,
scenes_by_id: dict[int, dict] | None = None,
) -> list[BeatRow]: ) -> list[BeatRow]:
stills_dir = project_root / "output" / "cutter_stills" stills_dir = project_root / "output" / "cutter_stills"
clips_dir = project_root / "output" / "cutter_clips" clips_dir = project_root / "output" / "cutter_clips"
@@ -420,6 +421,23 @@ def collect_rows(
if rec is not None: if rec is not None:
segs = rec.get("segments") or [] segs = rec.get("segments") or []
num_segs = len(segs) num_segs = len(segs)
if scenes_by_id:
rec_scene = scenes_by_id.get(int(rec.get("scene_id", -1)))
if rec_scene and float(rec["in_point_s"]) < float(rec_scene["start_s"]):
shift = float(rec_scene["start_s"]) - float(rec["in_point_s"])
rec = dict(rec)
rec["in_point_s"] = float(rec_scene["start_s"])
rec["out_point_s"] = max(float(rec["in_point_s"]) + 0.04, float(rec["out_point_s"]) + shift)
fixed_segs = []
for seg in segs:
fixed = dict(seg)
seg_scene = scenes_by_id.get(int(fixed.get("scene_id", -1)))
if seg_scene and float(fixed["in_point_s"]) < float(seg_scene["start_s"]):
shift = float(seg_scene["start_s"]) - float(fixed["in_point_s"])
fixed["in_point_s"] = float(seg_scene["start_s"])
fixed["out_point_s"] = max(float(fixed["in_point_s"]) + 0.04, float(fixed["out_point_s"]) + shift)
fixed_segs.append(fixed)
segs = fixed_segs
trailer_still = source_still = None trailer_still = source_still = None
trailer_clip = source_clip = compare_clip = None trailer_clip = source_clip = compare_clip = None
@@ -1019,12 +1037,15 @@ def render_report(
cache = project_root / ".cache" cache = project_root / ".cache"
results = {r["beat_id"]: r for r in json.loads((cache / "match_results.json").read_text())} results = {r["beat_id"]: r for r in json.loads((cache / "match_results.json").read_text())}
beats = json.loads((cache / "trailer_beats.json").read_text()) beats = json.loads((cache / "trailer_beats.json").read_text())
scene_path = cache / "scene_index.json"
scenes = json.loads(scene_path.read_text()) if scene_path.exists() else []
scenes_by_id = {int(s["scene_id"]): s for s in scenes}
vis_path = cache / "vision_descriptions.json" vis_path = cache / "vision_descriptions.json"
vis_items = json.loads(vis_path.read_text())["items"] if vis_path.exists() else {} vis_items = json.loads(vis_path.read_text())["items"] if vis_path.exists() else {}
rows = collect_rows( rows = collect_rows(
project_root, beats, results, vis_items, project_root, beats, results, vis_items,
trailer_path, source_path, with_stills, with_clips, trailer_path, source_path, with_stills, with_clips, scenes_by_id,
) )
now = datetime.now() now = datetime.now()