89 lines
3.1 KiB
Python
89 lines
3.1 KiB
Python
"""
|
||
vision.py — Video analysis via Google Gemini 2.5 Flash.
|
||
|
||
Uploads a short video clip and asks Gemini to describe what happened
|
||
in 1-2 sentences in Russian.
|
||
"""
|
||
|
||
import logging
|
||
import time
|
||
from pathlib import Path
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
ANALYSIS_PROMPT = """\
|
||
Опиши кратко (1–2 предложения на русском языке), что происходит на видео с камеры видеонаблюдения.
|
||
Укажи: есть ли человек, животное, транспортное средство, курьер (Озон, Яндекс, СДЭК и т.д.).
|
||
Если ничего значимого не происходит — напиши "Движение без объекта".
|
||
Будь конкретен и лаконичен.
|
||
"""
|
||
|
||
|
||
def analyze_video(video_path: str, api_key: str) -> str:
|
||
"""
|
||
Upload video to Gemini and return a Russian description.
|
||
|
||
Args:
|
||
video_path: Path to the trimmed video file.
|
||
api_key: Gemini API key.
|
||
|
||
Returns:
|
||
Russian text description, or fallback string on error.
|
||
"""
|
||
try:
|
||
from google import genai
|
||
from google.genai import types
|
||
|
||
client = genai.Client(api_key=api_key)
|
||
|
||
logger.info("Uploading video to Gemini: %s", video_path)
|
||
with open(video_path, "rb") as f:
|
||
video_bytes = f.read()
|
||
|
||
# Upload file via Files API (required for video)
|
||
video_file = client.files.upload(
|
||
file=video_path,
|
||
config=types.UploadFileConfig(mime_type="video/mp4"),
|
||
)
|
||
|
||
# Wait for file to be processed
|
||
max_wait = 60
|
||
waited = 0
|
||
while video_file.state.name == "PROCESSING" and waited < max_wait:
|
||
time.sleep(2)
|
||
waited += 2
|
||
video_file = client.files.get(name=video_file.name)
|
||
|
||
if video_file.state.name != "ACTIVE":
|
||
logger.error("Gemini file upload failed, state: %s", video_file.state.name)
|
||
return "Ошибка анализа видео (файл не обработан)."
|
||
|
||
response = client.models.generate_content(
|
||
model="gemini-2.5-flash-preview-04-17",
|
||
contents=[
|
||
types.Content(
|
||
parts=[
|
||
types.Part(file_data=types.FileData(file_uri=video_file.uri)),
|
||
types.Part(text=ANALYSIS_PROMPT),
|
||
]
|
||
)
|
||
],
|
||
)
|
||
|
||
# Clean up uploaded file
|
||
try:
|
||
client.files.delete(name=video_file.name)
|
||
except Exception:
|
||
pass
|
||
|
||
text = response.text.strip() if response.text else ""
|
||
logger.info("Gemini description: %s", text)
|
||
return text or "Описание недоступно."
|
||
|
||
except ImportError:
|
||
logger.error("google-genai not installed. Run: pip install google-genai")
|
||
return "Анализ видео недоступен (библиотека не установлена)."
|
||
except Exception as exc:
|
||
logger.error("Gemini analysis error: %s", exc)
|
||
return f"Ошибка анализа: {exc}"
|