""" Live integration test for Gemini API video segment extraction. Requires a valid GEMINI_API_KEY in .env (run from the lib/ directory). Run with: cd /Users/durukov/Work/TheOrchard/collab/durukov/fansifter-video-clipper/lib PYTHONPATH=src uv run pytest tests/test_gemini_live.py -v -s """ import time from pathlib import Path import pytest # Mark the whole module as a live integration test (skip if no key or no video) pytestmark = pytest.mark.integration VIDEO_PATH = Path(__file__).parent.parent / "harry.mp4" NUM_SEGMENTS = 3 MIN_DURATION = 10.0 MAX_DURATION = 15.0 def _load_engine(): """Import and instantiate IntelligenceEngine, failing gracefully if key missing.""" try: from fansifter_clipper.intelligence import IntelligenceEngine # noqa: PLC0415 return IntelligenceEngine() except Exception as exc: # noqa: BLE001 pytest.skip(f"Cannot initialise IntelligenceEngine: {exc}") @pytest.fixture(scope="module") def video_path(): if not VIDEO_PATH.exists(): pytest.skip(f"Test video not found: {VIDEO_PATH}") return VIDEO_PATH def test_gemini_live_extract_segments(video_path): """ End-to-end test: downsample → upload → Gemini inference → validate. Prints timing and segment details so quality can be inspected by eye. """ engine = _load_engine() print(f"\n[live] analysing {video_path.name} ...") t0 = time.perf_counter() segments = engine.extract_segments( video_path, num_segments=NUM_SEGMENTS, min_duration=MIN_DURATION, max_duration=MAX_DURATION, ) elapsed = time.perf_counter() - t0 print(f"[live] total time: {elapsed:.1f}s") # --- structural assertions --- assert len(segments) >= 1, "Expected at least one segment back from Gemini" from fansifter_clipper.ffmpeg_utils import probe_video # noqa: PLC0415 meta = probe_video(video_path) for seg in segments: duration = seg.end - seg.start print( f" [{seg.start:.1f}s – {seg.end:.1f}s] " f"type={seg.segment_type:<12} score={seg.score:.2f} " f'desc="{seg.description[:60]}"' ) assert seg.start >= 0, f"Segment starts before video: {seg.start}" assert seg.end <= meta.duration + 0.5, ( f"Segment ends past video ({seg.end:.1f} > {meta.duration:.1f})" ) assert MIN_DURATION <= duration <= MAX_DURATION + 0.5, ( f"Segment duration {duration:.1f}s out of range [{MIN_DURATION}, {MAX_DURATION}]" ) assert 0.0 <= seg.score <= 1.0, f"Score out of range: {seg.score}" assert seg.description, "Empty description" # No overlapping segments for i in range(len(segments) - 1): assert segments[i].end <= segments[i + 1].start + 0.1, ( f"Segments {i} and {i+1} overlap" ) print(f"[live] {len(segments)} valid segment(s) returned in {elapsed:.1f}s ✓")