Spaces:
Sleeping
Sleeping
File size: 5,998 Bytes
f7a96ab | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | #!/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()
|