Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| Test script to verify the opening kickoff detection fix. | |
| Tests: | |
| 1. Tennessee: Opening kickoff should be detected around 117s | |
| 2. Oregon: Opening kickoff should be detected around 332s | |
| 3. Texas: Should REJECT the fake kickoff at 20.5s and detect real game start around 444s | |
| The fix requires: | |
| - k=3 consecutive clock readings to confirm kickoff start | |
| - Maximum kickoff duration of 90s (rejects if too long) | |
| """ | |
| import sys | |
| import logging | |
| from pathlib import Path | |
| # Add src to path | |
| sys.path.insert(0, str(Path(__file__).parent.parent / "src")) | |
| from config import SessionConfig, load_session_config, get_video_basename, OUTPUT_DIR | |
| from pipeline import run_extraction | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") | |
| logger = logging.getLogger(__name__) | |
| def test_video(video_name: str, video_path: str, start_time: float, end_time: float, expected_kickoff_start: float, expected_kickoff_tolerance: float = 30.0): | |
| """ | |
| Test opening kickoff detection on a video segment. | |
| Args: | |
| video_name: Name for display | |
| video_path: Path to video file | |
| start_time: Start time in seconds | |
| end_time: End time in seconds | |
| expected_kickoff_start: Expected kickoff start time (within video segment) | |
| expected_kickoff_tolerance: Tolerance for kickoff timing match | |
| """ | |
| print(f"\n{'=' * 60}") | |
| print(f"Testing: {video_name}") | |
| print(f"Video: {video_path}") | |
| print(f"Time range: {start_time}s - {end_time}s") | |
| print(f"Expected kickoff around: {expected_kickoff_start}s (Β±{expected_kickoff_tolerance}s)") | |
| print("=" * 60) | |
| try: | |
| # Load existing session config for this video | |
| video_basename = get_video_basename(video_path, testing_mode=False) | |
| config_path = OUTPUT_DIR / f"{video_basename}_config.json" | |
| if not config_path.exists(): | |
| logger.error(f"Config not found: {config_path}") | |
| logger.error("Run main.py with --use-saved-regions first") | |
| return False | |
| # Load config and update time bounds | |
| session_config = load_session_config(str(config_path)) | |
| session_config.video_path = video_path | |
| session_config.start_time = start_time | |
| session_config.end_time = end_time | |
| session_config.video_basename = video_basename | |
| # Run extraction | |
| results = run_extraction(session_config, OUTPUT_DIR, num_workers=1) | |
| # Analyze results - plays are dicts, not objects | |
| plays = results.get("plays", []) | |
| kickoff_plays = [p for p in plays if p.get("play_type") == "kickoff"] | |
| print(f"\nResults:") | |
| print(f" Total plays detected: {len(plays)}") | |
| print(f" Kickoff plays: {len(kickoff_plays)}") | |
| success = True | |
| if kickoff_plays: | |
| for kp in kickoff_plays: | |
| start = kp.get("start_time", 0) | |
| end = kp.get("end_time", 0) | |
| print(f"\n Kickoff found:") | |
| print(f" Start: {start:.1f}s") | |
| print(f" End: {end:.1f}s") | |
| print(f" Duration: {end - start:.1f}s") | |
| # Check if within expected range | |
| diff = abs(start - expected_kickoff_start) | |
| if diff <= expected_kickoff_tolerance: | |
| print(f" β PASS: Within expected range ({diff:.1f}s from expected)") | |
| else: | |
| print(f" β FAIL: Outside expected range ({diff:.1f}s from expected)") | |
| success = False | |
| else: | |
| print(f"\n β No kickoff detected!") | |
| success = False | |
| # Show first few plays for context | |
| print(f"\nFirst 5 plays:") | |
| for p in plays[:5]: | |
| pnum = p.get("play_number", "?") | |
| pstart = p.get("start_time", 0) | |
| pend = p.get("end_time", 0) | |
| ptype = p.get("play_type", "?") | |
| pmethod = p.get("start_method", "?") | |
| print(f" Play #{pnum}: {pstart:.1f}s - {pend:.1f}s ({ptype}, {pmethod})") | |
| return success | |
| except Exception as e: | |
| logger.error(f"Error testing {video_name}: {e}") | |
| import traceback | |
| traceback.print_exc() | |
| return False | |
| def main(): | |
| """Run all tests.""" | |
| base_path = Path("/Users/andytaylor/Documents/Personal/cfb40/full_videos") | |
| # Test configurations | |
| tests = [ | |
| { | |
| "video_name": "Tennessee (baseline - should pass)", | |
| "video_path": str(base_path / "OSU vs Tenn 12.21.24.mkv"), | |
| "start_time": 0, | |
| "end_time": 300, # First 5 minutes | |
| "expected_kickoff_start": 117, # ~1:57 video time | |
| "expected_kickoff_tolerance": 30, | |
| }, | |
| { | |
| "video_name": "Oregon (baseline - should pass)", | |
| "video_path": str(base_path / "OSU vs Oregon 01.01.25.mkv"), | |
| "start_time": 200, | |
| "end_time": 500, # Around kickoff time | |
| "expected_kickoff_start": 332, # ~5:32 video time | |
| "expected_kickoff_tolerance": 30, | |
| }, | |
| { | |
| "video_name": "Texas (fix test - should reject fake kickoff at 20s)", | |
| "video_path": str(base_path / "OSU vs Texas 01.10.25.mkv"), | |
| "start_time": 0, | |
| "end_time": 600, # First 10 minutes | |
| "expected_kickoff_start": 444, # Real game starts ~7:24 | |
| "expected_kickoff_tolerance": 30, | |
| }, | |
| ] | |
| print("\n" + "=" * 60) | |
| print("OPENING KICKOFF DETECTION FIX TEST") | |
| print("=" * 60) | |
| results = [] | |
| for test_config in tests: | |
| success = test_video(**test_config) | |
| results.append((test_config["video_name"], success)) | |
| # Summary | |
| print("\n" + "=" * 60) | |
| print("TEST SUMMARY") | |
| print("=" * 60) | |
| for name, success in results: | |
| status = "β PASS" if success else "β FAIL" | |
| print(f" {status}: {name}") | |
| if __name__ == "__main__": | |
| main() | |