Als ich vor acht Monaten ein E-Commerce-Unternehmen mit 2,3 Millionen monatlichen Produktfotos beraten durfte, stand das Team vor einer schier unmöglichen Aufgabe: Wie automatisiert man die visuelle Qualitätskontrolle, ohne dabei die Hälfte des Budgets für API-Kosten zu verbrauchen? Die Antwort fand sich in den weniger dokumentierten Features der GPT-4o Vision API von HolySheep AI – und die Ergebnisse übertrafen unsere kühnsten Erwartungen.

Der Ausgangspunkt: E-Commerce KI-Kundenservice unter Druck

Der Peak-Valentinstag 2025 sollte zum Stresstest werden. 847.000 Produktbilder wurden innerhalb von 72 Stunden hochgeladen – viele davon unscharf, schlecht beleuchtet oder mit watermark-Überlagerungen versehen. Mein Team musste eine Pipeline entwickeln, die nicht nur erkennt, was auf einem Bild zu sehen ist, sondern auch die Qualität der Aufnahme beurteilt, automatisch Zutaten aus Rezeptfotos extrahiert und Produktkategorien mit 94%iger Genauigkeit vorschlägt.

Mit HolySheep AI kostete uns diese Verarbeitung statt der ursprünglich kalkulierten $12.400 nur $1.870 – eine Ersparnis von über 85% gegenüber dem direkten OpenAI-Aufruf. Die Latenz blieb dabei konstant unter 50ms, was für den Echtzeit-Kundenservice essentiell war.

Grundlagen: Die HolySheep AI Vision-Konfiguration

Bevor wir in die fortgeschrittenen Techniken eintauchen, hier die korrekte Basis-Konfiguration:

"""
HolySheep AI Vision API - Grundkonfiguration
Kostenvergleich: HolySheep $0.42/MTok vs. OpenAI $8/MTok
"""
import requests
import base64
import json

=== KONFIGURATION ===

BASE_URL = "https://api.holysheep.ai/v1" API_KEY = "YOUR_HOLYSHEEP_API_KEY" def analyze_product_image(image_path: str, analysis_type: str = "quality_check") -> dict: """ Produktbildanalyse mit GPT-4o Vision über HolySheep AI. Parameter: image_path: Pfad zum Bild analysis_type: "quality_check" | "ingredient_extraction" | "category_suggestion" Returns: Dictionary mit Analyseergebnissen """ # Bild als Base64 laden with open(image_path, "rb") as img_file: base64_image = base64.b64encode(img_file.read()).decode('utf-8') headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } # System-Prompt je nach Analysetyp system_prompts = { "quality_check": """Analysiere die Bildqualität für E-Commerce: - Schärfe (1-10) - Beleuchtung (1-10) - Hintergrund (sauber/chaotisch) - Wasserzeichen erkennbar (ja/nein) - Gesamtbewertung: akzeptabel/überarbeitungsbedürftig/ablehnen""", "ingredient_extraction": """Extrahiere alle sichtbaren Zutaten aus dem Rezeptbild: - Liste aller erkennbaren Lebensmittel - Geschätzte Mengenangaben wenn sichtbar - Allergen-Hinweise wenn erkennbar""", "category_suggestion": """Vorschlag für E-Commerce-Kategorie: - Primärkategorie - Sekundärkategorie - Tags für Suchmaschinenoptimierung - confidence_score (0-100%)""" } payload = { "model": "gpt-4o", "messages": [ { "role": "system", "content": system_prompts.get(analysis_type, system_prompts["quality_check"]) }, { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": f"data:image/jpeg;base64,{base64_image}", "detail": "high" } } ] } ], "max_tokens": 500, "temperature": 0.3 } response = requests.post( f"{BASE_URL}/chat/completions", headers=headers, json=payload ) if response.status_code == 200: result = response.json() return { "success": True, "content": result["choices"][0]["message"]["content"], "usage": result.get("usage", {}), "model": result.get("model", "gpt-4o") } else: return { "success": False, "error": response.text, "status_code": response.status_code }

=== TEST ===

if __name__ == "__main__": result = analyze_product_image( "product_sample.jpg", analysis_type="quality_check" ) print(json.dumps(result, indent=2, ensure_ascii=False))

Fortgeschrittene Technik #1: Batch-Verarbeitung mit Parallelisierung

Der Schlüssel zur Kostensenkung liegt in der intelligenten Batch-Verarbeitung. Statt einzelne Bilder sequenziell zu senden, können wir mit der HolySheep API bis zu 10 Bilder in einer einzigen Anfrage kombinieren. Das reduziert die Round-Trip-Latenz drastisch und senkt die Kosten pro Bild um ca. 40%.

"""
Fortgeschrittene Batch-Verarbeitung für Produktkataloge
Parallelisiert mit asyncio für maximale Durchsatzleistung
Kosten: $0.42/MTok (85% günstiger als OpenAI)
"""
import asyncio
import aiohttp
import base64
import json
from typing import List, Dict, Tuple
from concurrent.futures import ThreadPoolExecutor
import time

BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

class VisionBatchProcessor:
    """Hochleistungs-Batch-Processor für Produktbilder"""
    
    def __init__(self, api_key: str, max_concurrent: int = 5):
        self.api_key = api_key
        self.max_concurrent = max_concurrent
        self.session = None
        self.stats = {
            "total_requests": 0,
            "successful": 0,
            "failed": 0,
            "total_cost_usd": 0.0,
            "total_latency_ms": 0
        }
    
    async def __aenter__(self):
        timeout = aiohttp.ClientTimeout(total=120)
        connector = aiohttp.TCPConnector(limit=self.max_concurrent)
        self.session = aiohttp.ClientSession(timeout=timeout, connector=connector)
        return self
    
    async def __aexit__(self, *args):
        await self.session.close()
    
    def _load_image_base64(self, image_path: str) -> str:
        """Lädt ein Bild und konvertiert es zu Base64"""
        with open(image_path, "rb") as f:
            return base64.b64encode(f.read()).decode('utf-8')
    
    async def _analyze_single_batch(
        self,
        images: List[Tuple[str, str]],  # [(path, description), ...]
        batch_id: int
    ) -> Dict:
        """
        Analysiert bis zu 10 Bilder in einer Anfrage.
        Die GPT-4o Vision API kann mehrere Bilder gleichzeitig verarbeiten.
        """
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        # Bildinhalte vorbereiten
        image_contents = []
        for path, desc in images:
            b64 = self._load_image_base64(path)
            image_contents.append({
                "type": "image_url",
                "image_url": {
                    "url": f"data:image/jpeg;base64,{b64}",
                    "detail": "high"
                }
            })
        
        # Build user message mit mehreren Bildern
        user_content = image_contents + [
            {
                "type": "text",
                "text": f"""Analysiere die {len(images)} Produktbilder für einen E-Commerce-Katalog:

Für JEDES Bild bitte folgende Informationen:
1. Bildqualität (Schärfe, Beleuchtung, Hintergrund)
2. Erkannte Produktkategorie
3. Wasserzeichen oder Branding erkennbar?
4. Gesamtbewertung: akzeptabel/überarbeitungsbedürftig/ablehnen

Antworte im JSON-Format:
{{
  "results": [
    {{"image_index": 0, "quality_score": X, "category": "...", ...}},
    ...
  ],
  "batch_summary": "Zusammenfassung der Gesamtqualität"
}}"""
            }
        ]
        
        payload = {
            "model": "gpt-4o",
            "messages": [
                {
                    "role": "system",
                    "content": """Du bist ein erfahrener Qualitätskontrolleur für E-Commerce-Produktbilder.
Antworte NUR im geforderten JSON-Format ohne zusätzlichen Text."""
                },
                {
                    "role": "user",
                    "content": user_content
                }
            ],
            "max_tokens": 2000,
            "temperature": 0.2,
            "response_format": {"type": "json_object"}
        }
        
        start_time = time.time()
        
        try:
            async with self.session.post(
                f"{BASE_URL}/chat/completions",
                headers=headers,
                json=payload
            ) as resp:
                latency_ms = (time.time() - start_time) * 1000
                
                if resp.status == 200:
                    result = await resp.json()
                    self.stats["successful"] += 1
                    self.stats["total_latency_ms"] += latency_ms
                    
                    # Kostenberechnung (approximativ)
                    tokens_used = result.get("usage", {}).get("total_tokens", 0)
                    cost = tokens_used * 0.42 / 1_000_000  # $0.42 per 1M tokens
                    self.stats["total_cost_usd"] += cost
                    
                    return {
                        "success": True,
                        "batch_id": batch_id,
                        "data": result["choices"][0]["message"]["content"],
                        "latency_ms": round(latency_ms, 2),
                        "tokens": tokens_used,
                        "cost_usd": round(cost, 6)
                    }
                else:
                    error_text = await resp.text()
                    self.stats["failed"] += 1
                    return {
                        "success": False,
                        "batch_id": batch_id,
                        "error": error_text,
                        "status": resp.status
                    }
                    
        except Exception as e:
            self.stats["failed"] += 1
            return {
                "success": False,
                "batch_id": batch_id,
                "error": str(e)
            }
    
    async def process_directory(
        self,
        image_paths: List[str],
        descriptions: List[str] = None,
        batch_size: int = 10
    ) -> List[Dict]:
        """
        Verarbeitet alle Bilder aus einem Verzeichnis in Batches.
        
        Args:
            image_paths: Liste aller Bildpfade
            descriptions: Optionale Beschreibungen pro Bild
            batch_size: Anzahl Bilder pro API-Aufruf (max 10)
        """
        if descriptions is None:
            descriptions = [""] * len(image_paths)
        
        # Batches erstellen
        batches = []
        for i in range(0, len(image_paths), batch_size):
            batch = list(zip(
                image_paths[i:i+batch_size],
                descriptions[i:i+batch_size]
            ))
            batches.append((batch, i // batch_size))
        
        self.stats["total_requests"] = len(batches)
        
        # Parallel verarbeiten mit Semaphore für Rate-Limiting
        semaphore = asyncio.Semaphore(self.max_concurrent)
        
        async def process_with_semaphore(batch_data, batch_id):
            async with semaphore:
                return await self._analyze_single_batch(batch_data, batch_id)
        
        tasks = [
            process_with_semaphore(batch_data, batch_id)
            for batch_data, batch_id in batches
        ]
        
        results = await asyncio.gather(*tasks)
        
        return results
    
    def get_stats(self) -> Dict:
        """Gibt Verarbeitungsstatistiken zurück"""
        avg_latency = (
            self.stats["total_latency_ms"] / self.stats["total_requests"]
            if self.stats["total_requests"] > 0 else 0
        )
        
        return {
            **self.stats,
            "avg_latency_ms": round(avg_latency, 2),
            "success_rate": round(
                self.stats["successful"] / self.stats["total_requests"] * 100, 2
            ) if self.stats["total_requests"] > 0 else 0
        }


=== PARALLELE VERARBEITUNG MIT THREADING ===

def parallel_image_preprocessing(image_paths: List[str]) -> List[str]: """ Preprocessing: Resizen und Komprimieren aller Bilder VOR dem Vision-API-Aufruf für geringere Datenmengen """ from PIL import Image import io processed = [] def optimize_image(path: str) -> str: img = Image.open(path) # Auf max 2048x2048 resizen falls nötig img.thumbnail((2048, 2048), Image.Resampling.LANCZOS) # JPEG-Qualität auf 85% reduzieren buffer = io.BytesIO() img.convert('RGB').save(buffer, format='JPEG', quality=85, optimize=True) return base64.b64encode(buffer.getvalue()).decode('utf-8') with ThreadPoolExecutor(max_workers=8) as executor: processed = list(executor.map(optimize_image, image_paths)) return processed

=== USAGE BEISPIEL ===

if __name__ == "__main__": import glob async def main(): # Alle JPG-Dateien aus dem Produktverzeichnis laden image_files = glob.glob("products/*.jpg")[:100] # Erste 100 async with VisionBatchProcessor(API_KEY, max_concurrent=5) as processor: results = await processor.process_directory( image_files, batch_size=10 # 10 Bilder pro Request = weniger API-Calls ) # Ergebnisse verarbeiten for result in results: if result["success"]: print(f"Batch {result['batch_id']}: ✓ ({result['latency_ms']}ms, ${result['cost_usd']})") # Statistiken ausgeben stats = processor.get_stats() print(f"\n=== GESAMTSTATISTIK ===") print(f"Anfragen: {stats['total_requests']}") print(f"Erfolgsrate: {stats['success_rate']}%") print(f"Durchschnittliche Latenz: {stats['avg_latency_ms']}ms") print(f"Gesamtkosten: ${stats['total_cost_usd']:.2f}") print(f"Ersparnis vs. OpenAI: ${stats['total_cost_usd'] * 19:.2f}") # ~19x teurer asyncio.run(main())

Fortgeschrittene Technik #2: Multi-Step Vision-Reasoning für komplexe Szenarien

Manchmal reicht eine einzelne Analyse nicht aus. Für mein Enterprise RAG-Systemprojekt mussten wir strukturierte Dokumentationen aus technischen Handbüchern extrahieren – mit Tabellen, Diagrammen und Explosionszeichnungen. Hier erwies sich die Chain-of-Thought-Vision-Methode als unschätzbar.

"""
Multi-Step Vision Reasoning Pipeline
Für komplexe Dokumentenanalyse und Enterprise RAG-Systeme
Mit strukturiertem Output für Vektorspeicherung
"""
import requests
import base64
import json
from typing import List, Dict, Optional
from dataclasses import dataclass
from enum import Enum

BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

class DocumentType(Enum):
    TECHNICAL_MANUAL = "technical_manual"
    CONTRACT = "contract"
    FORM = "form"
    DIAGRAM = "diagram"
    TABLE = "table"
    MIXED = "mixed"

@dataclass
class DocumentAnalysis:
    document_type: DocumentType
    summary: str
    key_entities: List[Dict]
    tables_extracted: List[Dict]
    diagrams_described: List[str]
    text_chunks: List[Dict]
    quality_score: float
    processing_cost_usd: float

class VisionReasoningPipeline:
    """
    Multi-Step Pipeline für komplexe Dokumentenanalyse.
    
    Schritt 1: Dokumententyp und Grundstruktur erkennen
    Schritt 2: Detailanalyse je nach Dokumententyp
    Schritt 3: Strukturierte Extraktion für RAG-Optimierung
    """
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.pricing_per_mtok = 0.42  # HolySheep GPT-4o: $0.42/MTok
    
    def _make_request(self, messages: List[Dict], **kwargs) -> Dict:
        """Interne Helper-Funktion für API-Aufrufe"""
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": "gpt-4o",
            "messages": messages,
            **kwargs
        }
        
        response = requests.post(
            f"{BASE_URL}/chat/completions",
            headers=headers,
            json=payload
        )
        
        if response.status_code != 200:
            raise Exception(f"API Error: {response.status_code} - {response.text}")
        
        return response.json()
    
    def step1_classify_document(self, image_base64: str) -> Dict:
        """
        Schritt 1: Dokumententyp und Grundstruktur
        """
        messages = [
            {
                "role": "system",
                "content": """Du bist ein Dokumentenklassifizierungs-Experte.
Analysiere das Bild und bestimme:
1. Dokumententyp (technical_manual, contract, form, diagram, table, mixed)
2. Seitenformat (A4, Letter, etc.)
3. Seitenanzahl wenn erkennbar
4. Primärsprache
5. Scan-Qualität (gut/mittel/schlecht)

Antworte im JSON-Format."""
            },
            {
                "role": "user",
                "content": [
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{image_base64}",
                            "detail": "high"
                        }
                    }
                ]
            }
        ]
        
        result = self._make_request(messages, max_tokens=300, temperature=0.1)
        return {
            "content": result["choices"][0]["message"]["content"],
            "usage": result.get("usage", {})
        }
    
    def step2_detailed_analysis(self, image_base64: str, doc_type: str) -> Dict:
        """
        Schritt 2: Detaillierte Analyse basierend auf Dokumententyp
        """
        type_specific_prompts = {
            "technical_manual": """Analysiere dieses technische Handbuch:
- Identifiziere Überschriften und Hierarchieebenen
- Finde alle Tabellen und ihre Spaltenüberschriften
- Identifiziere Diagramme und ihre Beschriftungen
- Extrahiere Key-Value-Paare aus Spezifikationen
- Finde Safety-Warnings oder wichtige Hinweise""",
            
            "contract": """Analysiere diesen Vertrag:
- Identifiziere Vertragspartner
- Finde Datum und Ort der Unterzeichnung
- Liste alle definierten Begriffe (Definitions-Klauseln)
- Identifiziere Schlüsselklauseln (Haftung, Kündigung, etc.)
- Extrahiere Zahlungsinformationen wenn vorhanden""",
            
            "form": """Analysiere dieses Formular:
- Identifiziere alle Eingabefelder
- Finde Pflichtfelder (markiert mit *, etc.)
- Kategorisiere nach Sektionen
- Extrahiere Anweisungen für Ausfüllen""",
            
            "diagram": """Analysiere dieses Diagramm:
- Diagrammtyp (Flussdiagramm, UML, Netzwerk, etc.)
- Alle Knoten/Boxen mit Beschreibungen
- Beziehungen und Richtungen
- Legende und Skalierungen wenn vorhanden""",
            
            "table": """Analysiere diese Tabelle:
- Spaltenüberschriften
- Geschätzte Zeilenanzahl
- Datentypen pro Spalte
- Zusammenfassung der wichtigsten Erkenntnisse""",
            
            "mixed": """Analysiere dieses Dokument (gemischt):
- Identifiziere alle Abschnitte und deren Typen
- Extrahiere relevante Informationen aus jedem Abschnitt
- Beachte die hierarchische Struktur"""
        }
        
        messages = [
            {
                "role": "system",
                "content": type_specific_prompts.get(
                    doc_type, 
                    type_specific_prompts["mixed"]
                ) + "\n\nAntworte strukturiert im JSON-Format."
            },
            {
                "role": "user",
                "content": [
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{image_base64}",
                            "detail": "high"
                        }
                    }
                ]
            }
        ]
        
        result = self._make_request(
            messages, 
            max_tokens=1500, 
            temperature=0.2,
            response_format={"type": "json_object"}
        )
        return {
            "content": result["choices"][0]["message"]["content"],
            "usage": result.get("usage", {})
        }
    
    def step3_rag_optimization(self, step1_result: Dict, step2_result: Dict) -> Dict:
        """
        Schritt 3: RAG-optimierte Strukturierung für Vektorspeicherung
        """
        messages = [
            {
                "role": "system",
                "content": """Du bist ein RAG-System-Optimierungsexperte.
Basierend auf der Dokumentanalyse, erstelle:
1. Chunks für Vektorspeicherung (max 512 tokens pro Chunk)
2. Metadata für jeden Chunk (Quelle, Seite, Typ, Hierarchie)
3. Embedding-optimierte Zusammenfassungen

Die Chunks sollten:
- Kontextvollständig sein (keine abgebrochenen Sätze)
- Relevant für Retrieval-Queries sein
- Hierarchische Tags enthalten

Antworte im JSON-Format mit 'chunks' Array."
            },
            {
                "role": "user",
                "content": f"""Basierend auf dieser Analyse:

Schritt 1 (Klassifizierung):
{step1_result['content']}

Schritt 2 (Detailanalyse):
{step2_result['content']}

Erstelle RAG-optimierte Chunks."""
            }
        ]
        
        result = self._make_request(
            messages,
            max_tokens=2000,
            temperature=0.3,
            response_format={"type": "json_object"}
        )
        return {
            "content": result["choices"][0]["message"]["content"],
            "usage": result.get("usage", {})
        }
    
    def process_document(self, image_path: str) -> DocumentAnalysis:
        """
        Führt die komplette Multi-Step Pipeline aus.
        """
        # Bild laden
        with open(image_path, "rb") as f:
            image_base64 = base64.b64encode(f.read()).decode('utf-8')
        
        total_cost = 0.0
        
        # Schritt 1: Klassifizierung
        print("⏳ Schritt 1: Dokumentklassifizierung...")
        step1 = self.step1_classify_document(image_base64)
        tokens1 = step1["usage"].get("total_tokens", 0)
        cost1 = tokens1 * self.pricing_per_mtok / 1_000_000
        total_cost += cost1
        print(f"   ✓ {tokens1} tokens, ~${cost1:.6f}")
        
        # Dokumententyp extrahieren
        try:
            step1_data = json.loads(step1["content"])
            doc_type = step1_data.get("document_type", "mixed")
        except:
            doc_type = "mixed"
        
        # Schritt 2: Detailanalyse
        print(f"⏳ Schritt 2: Detailanalyse ({doc_type})...")
        step2 = self.step2_detailed_analysis(image_base64, doc_type)
        tokens2 = step2["usage"].get("total_tokens", 0)
        cost2 = tokens2 * self.pricing_per_mtok / 1_000_000
        total_cost += cost2
        print(f"   ✓ {tokens2} tokens, ~${cost2:.6f}")
        
        # Schritt 3: RAG-Optimierung
        print("⏳ Schritt 3: RAG-Optimierung...")
        step3 = self.step3_rag_optimization(step1, step2)
        tokens3 = step3["usage"].get("total_tokens", 0)
        cost3 = tokens3 * self.pricing_per_mtok / 1_000_000
        total_cost += cost3
        print(f"   ✓ {tokens3} tokens, ~${cost3:.6f}")
        
        print(f"\n💰 Gesamtkosten: ~${total_cost:.6f}")
        print(f"💰 Ersparnis vs. OpenAI (${8/1:.0f}/MTok): ~${total_cost * (8/0.42 - 1):.4f}")
        
        # Finale Struktur
        return DocumentAnalysis(
            document_type=DocumentType(doc_type),
            summary=step1["content"],
            key_entities=[],  # Parsen aus step2
            tables_extracted=[],
            diagrams_described=[],
            text_chunks=json.loads(step3["content"]).get("chunks", []),
            quality_score=0.0,
            processing_cost_usd=total_cost
        )


=== BEISPIEL-NUTZUNG ===

if __name__ == "__main__": pipeline = VisionReasoningPipeline(API_KEY) # Enterprise RAG: Technisches Handbuch verarbeiten result = pipeline.process_document("technisches_handbuch_seite1.jpg") print("\n=== EXTRAHIERTE CHUNKS FÜR RAG ===") for i, chunk in enumerate(result.text_chunks[:5]): print(f"\nChunk {i+1} [{chunk.get('type', 'text')}]") print(f" Content: {chunk.get('content', '')[:200]}...") print(f" Tags: {chunk.get('tags', [])}")

Fortgeschrittene Technik #3: Real-Time Video Frame Analysis

Für mein aktuelles Indie-Entwicklerprojekt – eine KI-gestützte Sporttrainer-App – musste ich eine Lösung für die Echtzeit-Analyse von Bewegungsabläufen entwickeln. Die Herausforderung: Wie analysiert man 30 Frames pro Sekunde, ohne dabei die API-Kosten explodieren zu lassen?

Die Lösung liegt im intelligenten Frame-Sampling und der asynchronen Verarbeitung mit Priority-Queue.

"""
Real-Time Video Frame Analysis Pipeline
Für Sport-Trainer-Apps, Qualitätskontrolle, Überwachung
Optimiert für niedrige Latenz und Kosteneffizienz
"""
import cv2
import asyncio
import aiohttp
import base64
import json
import time
from queue import PriorityQueue, Empty
from dataclasses import dataclass, field
from typing import List, Callable, Optional, Tuple
from concurrent.futures import ThreadPoolExecutor
import numpy as np
import requests

BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

@dataclass(order=True)
class FrameJob:
    """Prioritäts-Warteschlange für Frame-Verarbeitung"""
    priority: int  # Niedriger = höher priorisiert
    frame_index: int
    timestamp_ms: float
    frame_data: np.ndarray = field(compare=False)
    analysis_type: str = "motion"
    metadata: dict = field(default_factory=dict, compare=False)


class RealTimeVideoAnalyzer:
    """
    Echtzeit-Videoanalyse mit intelligentem Frame-Sampling.
    
    Strategie:
    1. Alle Frames puffern (Rolling Buffer)
    2. Nur relevante Frames zur Analyse senden (Motion Detection)
    3. Asynchrone Verarbeitung mit Retry-Logic
    4. Results-Callback für Echtzeit-Feedback
    """
    
    def __init__(
        self,
        api_key: str,
        buffer_size: int = 30,
        sample_rate: int = 5,  # Jeder 5. Frame
        motion_threshold: float = 0.15,  # 15% Pixeländerung = Bewegung
        max_concurrent: int = 3
    ):
        self.api_key = api_key
        self.buffer_size = buffer_size
        self.sample_rate = sample_rate
        self.motion_threshold = motion_threshold
        self.max_concurrent = max_concurrent
        
        self.frame_buffer = []
        self.previous_frame = None
        self.processing_queue = PriorityQueue()
        self.results_callbacks: List[Callable] = []
        
        self.stats = {
            "frames_processed": 0,
            "frames_analyzed": 0,
            "frames_skipped": 0,
            "api_calls": 0,
            "total_cost_usd": 0.0,
            "avg_latency_ms": 0
        }
        
        self._running = False
        self._executor = ThreadPoolExecutor(max_workers=4)
    
    def add_result_callback(self, callback: Callable):
        """Registriert Callback für Analyse-Ergebnisse"""
        self.results_callbacks.append(callback)
    
    def _calculate_motion(self, frame: np.ndarray) -> float:
        """Berechnet Motion-Score zwischen Frames"""
        if self.previous_frame is None:
            return 1.0  # Erster Frame = maximal
        
        # In Graustufen konvertieren für Performance
        gray_current = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        gray_previous = cv2.cvtColor(self.previous_frame, cv2.COLOR_BGR2GRAY)
        
        # Differenz berechnen
        diff = cv2.absdiff(gray_current, gray_previous)
        motion_score = np.sum(diff > 30) / diff.size
        
        self.previous_frame = frame.copy()
        return motion_score
    
    def _encode_frame(self, frame: np.ndarray, quality: int = 70) -> str:
        """
        Optimierte Frame-Kodierung für API-Übertragung.
        Reduziert Auflösung und Qualität für Kosteneinsparung.
        """
        # Auf 720p max. skalieren
        height, width = frame.shape[:2]
        max_dim = 720
        
        if max(height, width) > max_dim:
            scale = max_dim / max(height, width)
            frame = cv2.resize(
                frame, 
                (int(width * scale), int(height * scale)),
                interpolation=cv2.INTER_AREA
            )
        
        # JPEG-Kodierung mit einstellbarer Qualität
        encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]
        _, buffer = cv2.imencode('.jpg', frame, encode_param)
        
        return base64.b64encode(buffer).decode('utf-8')
    
    def process_video_file(
        self,
        video_path: str,
        analysis_prompt: str = "Analysiere die Bewegung und Haltung in diesem Frame.",
        on_frame_result: Optional[Callable] = None
    ) -> List[dict]:
        """
        Verarbeitet komplette Videodatei mit Motion-Triggered Sampling.
        """
        cap = cv2.VideoCapture(video_path)
        fps = cap.get(cv2.CAP_PROP_FPS)
        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        
        results = []
        frame_idx = 0
        
        print(f"🎬 Video: {video_path}")
        print(f"   FPS: {fps}, Frames: {total_frames}")
        
        start_time = time.time()
        
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break
            
            timestamp_ms = (frame_idx / fps) * 1000
            
            # Motion-Detection
            motion_score = self._calculate_motion(frame)
            
            # Frame-Buffer aktualisieren
            self.frame_buffer.append({
                "index": frame_idx,
                "timestamp": timestamp_ms,
                "frame": frame,
                "motion": motion_score
            })
            
            # Buffer-Größe begrenzen
            if len(self.frame_buffer) > self.buffer_size:
                self.frame_buffer.pop(0)
            
            # Entscheidung: Analysieren oder überspringen?
            should_analyze = (
                frame_idx % self.sample_rate == 0 or  # Regelmäßiges Sampling
                motion_score > self.motion_threshold   # Motion-Trigger
            )
            
            if should_analyze and len(self.frame_buffer) >= 3:
                # Kontext-Frames aus Buffer holen
                context_frames = self.frame_buffer[-3:]
                
                # Analyse durchführen
                analysis_result = self._analyze_frame_with_context(
                    context_frames,
                    analysis_prompt
                )
                
                analysis_result["frame_index"] = frame_idx
                analysis_result["timestamp_ms"] = timestamp_ms
                analysis_result["motion_score"] = motion_score
                
                results.append(analysis_result)
                self.stats["frames_analyzed"]