verivid / app /services /sightengine.py
bahaeddinmselmi
fix(analyzer): robust doubled-URL normalization and enhanced error reporting
c9f75f9
# C:\Users\bahae\.gemini\antigravity\scratch\verivid-ai\backend\app\services\sightengine.py
import requests
from app.core.config import settings
SIGHTENGINE_CHECK_URL = "https://api.sightengine.com/1.0/check.json"
def analyze_with_sightengine(image_url: str = None, image_bytes: bytes = None) -> dict:
"""
Use SightEngine's professional AI detection.
Returns: {"ai_score": 0-1, "details": str, "raw": dict}
"""
if not settings.SIGHTENGINE_USER or not settings.SIGHTENGINE_SECRET:
return {"ai_score": None, "details": "SightEngine not configured", "raw": None}
try:
if image_url:
# URL-based check
response = requests.post(
SIGHTENGINE_CHECK_URL,
data={
"url": image_url,
"models": "genai",
"api_user": settings.SIGHTENGINE_USER,
"api_secret": settings.SIGHTENGINE_SECRET
},
timeout=30
)
elif image_bytes:
# File-based check
response = requests.post(
SIGHTENGINE_CHECK_URL,
data={
"models": "genai",
"api_user": settings.SIGHTENGINE_USER,
"api_secret": settings.SIGHTENGINE_SECRET
},
files={"media": ("image.jpg", image_bytes, "image/jpeg")},
timeout=30
)
else:
return {"ai_score": None, "details": "No image provided", "raw": None}
if response.status_code != 200:
return {"ai_score": None, "details": f"API error: {response.status_code}", "raw": response.text[:200]}
data = response.json()
# SightEngine returns: {"type": {"ai_generated": 0.95, ...}}
if data.get("status") == "success":
genai_data = data.get("type", {})
ai_score = genai_data.get("ai_generated", 0)
return {
"ai_score": ai_score,
"details": f"SightEngine AI detection: {round(ai_score * 100)}% AI probability",
"raw": data
}
else:
return {"ai_score": None, "details": f"API error: {data.get('error', {}).get('message', 'Unknown')}", "raw": data}
except Exception as e:
return {"ai_score": None, "details": f"Exception: {str(e)}", "raw": None}
def analyze_frames_with_sightengine(frame_paths: list) -> dict:
"""Analyze multiple frames and aggregate scores"""
scores = []
details = []
for path in frame_paths[:5]: # Limit to 5 frames to save API calls
try:
with open(path, 'rb') as f:
img_bytes = f.read()
result = analyze_with_sightengine(image_bytes=img_bytes)
if result["ai_score"] is not None:
scores.append(result["ai_score"])
details.append(f"Frame: {round(result['ai_score'] * 100)}%")
except Exception as e:
details.append(f"Error: {str(e)[:50]}")
if scores:
avg_score = sum(scores) / len(scores)
max_score = max(scores)
return {
"avg_score": avg_score,
"max_score": max_score,
"frame_count": len(scores),
"frame_scores": [round(s, 3) for s in scores],
"details": f"SightEngine analyzed {len(scores)} frames. Avg: {round(avg_score*100)}%, Max: {round(max_score*100)}%"
}
else:
return {
"avg_score": None,
"max_score": None,
"frame_count": 0,
"frame_scores": [],
"details": "SightEngine analysis failed: " + "; ".join(details)
}