2 Commits
Author SHA1 Message Date
ThePendulum eb7c1aa500 Add sync preview, restore Detect All Claps button, reorder markers panel
- Preview Sync button builds a short (8s) lossless clip around the
  marked events with the current offset applied, and plays it in a
  small popup PreviewDialog (its own independent PlayerWidget/mpv
  instance) -- lets you check the fix sounds/looks right before
  committing to a full export. ExportWorker gained optional
  clip_start/clip_duration so both the real export and this preview
  share the same underlying export_synced() call.
- Detect All Claps is back as a button in the Sync markers panel
  (alongside Mark Audio/Video Event), in addition to staying in the
  Tools menu -- both widgets' enabled state are kept in sync.
- Sync markers panel now shows Mark Audio Event before Mark Video
  Event.

The clip-mode branch of ffmpeg_export.py (the -ss/-t-on-both-inputs
path ffdelay's own notes flag as easy to get subtly wrong) hadn't been
covered by the existing roundtrip test, which only exercised full-file
export -- added a clip-mode case there, independently verified via the
same scene-change/silence-detection technique as the other cases:
29.4ms drift after the fix, well under one frame.

All of this was built and verified entirely on a virtual Xvfb display
(DISPLAY=:99) per the user's request to stop interrupting their real
desktop -- real mouse clicks and a real (non-monkeypatched) preview
dialog were exercised there, screenshotted, and confirmed correct,
without ever touching the real screen.
2026-07-26 03:01:06 +02:00
ThePendulum f634dda5bb Implement sync_logic.py and ffmpeg_export.py (build order steps 2-3)
sync_logic.py: pure delay_ms computation with the documented sign
convention. Caught and fixed a sign error in my own test-fixture
ground-truth doc while writing the unit tests: the audio+350ms fixture
actually requires delay_ms=-350 (delay video), not +350, since the
audio is already the late one.

ffmpeg_export.py: ports ffdelay's two-branch command structure
(offset video input vs audio input depending on delay_ms sign) plus
its documented quirks (leading-zero float formatting, -ss/-t applied
to both inputs for clip mode, non-fatal stream-copy warnings surfaced
via stderr rather than swallowed).

Added an end-to-end integration test (scripts/test_export_roundtrip.py)
that independently re-detects event timing in the exported output via
ffmpeg scene-change/silence detection (not the same code path used to
build the export) and confirms both the positive- and negative-delay
branches bring drift down from ~350ms to under 1ms.
2026-07-26 00:50:57 +02:00