Files
WeAreSyncing/scripts/validate_seek.py
T
ThePendulum 91390f751d Validate frame-accurate seeking with python-mpv (build order step 1)
Confirms single-frame stepping is reliable: monotonic frame counter
across steps, and the synthetic clip's 1-frame flash event lands on
exactly one frame with clean neighbors. Also documents/works around
three environment quirks hit along the way: locally-built libmpv not
in ldconfig's cache, QApplication resetting LC_NUMERIC and breaking
libmpv's locale requirement, and the playback-restart event not firing
reliably after frame-step (switched to polling estimated_frame_number).
2026-07-26 00:37:42 +02:00

63 lines
1.9 KiB
Python

"""Standalone validation harness for build-order step 1: confirm python-mpv
gives frame-accurate seeking before any of the rest of the UI is built.
Steps frame-by-frame across the known flash event in the synthetic test clip
(white flash at t=5.000s, frame 150 @ 30fps) and dumps a screenshot + reported
position/frame-number per step, so the results can be inspected directly
instead of trusted on faith.
"""
import sys
import time
from pathlib import Path
from PyQt6.QtWidgets import QApplication
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from player_widget import PlayerWidget
CLIP = str(Path(__file__).resolve().parent.parent / "test_media" / "sync_test_INSYNC.mp4")
OUT_DIR = Path(__file__).resolve().parent.parent / "test_media" / "seek_validation"
def main():
OUT_DIR.mkdir(exist_ok=True)
app = QApplication(sys.argv)
w = PlayerWidget()
w.resize(640, 480)
w.show()
app.processEvents()
w.load(CLIP)
app.processEvents()
print(f"fps reported by mpv: {w.fps()}")
# Land a few frames before the flash (frame 150 == t=5.000s), then
# single-step across it.
w.seek(4.900)
app.processEvents()
time.sleep(0.2)
app.processEvents()
results = []
for i in range(8):
pos = w.get_position()
frame = w.get_estimated_frame()
shot = OUT_DIR / f"step_{i:02d}_frame{frame}.png"
w.screenshot(str(shot))
results.append((i, pos, frame, shot.name))
print(f"step {i}: time_pos={pos:.4f}s estimated_frame={frame} -> {shot.name}")
w.step_frame(1)
app.processEvents()
w.shutdown()
print("\nExpected: flash frame is frame index 150 (t=5.000-5.033s).")
print("Check the dumped PNGs in test_media/seek_validation/ to confirm")
print("exactly one frame is white/bright and it lines up with the")
print("reported frame number close to 150.")
if __name__ == "__main__":
main()