In [ ]:
# ============================================================
# TRON: Early Earthquake Warning via Animal Behavior Analysis
# Rutube → ffmpeg → OpenCV → Gemma 4
# ============================================================
!pip install -q google-genai opencv-python-headless
!apt-get -q -y install ffmpeg
print("✅ Зависимости установлены")
In [ ]:
# ── ПОДКЛЮЧЕНИЕ К GEMMA 4 ──────────────────────────────────────
from kaggle_secrets import UserSecretsClient
from google import genai
from google.genai import types
import requests, subprocess, cv2, json
from pathlib import Path
secret = UserSecretsClient()
api_key = secret.get_secret("GOOGLE_API_KEY")
client = genai.Client(api_key=api_key)
Path("/kaggle/working/tron/videos").mkdir(parents=True, exist_ok=True)
Path("/kaggle/working/tron/frames").mkdir(parents=True, exist_ok=True)
print("✅ Gemma 4 подключена")# ── ПОДКЛЮЧЕНИЕ К GEMMA 4 ──────────────────────────────────────
from kaggle_secrets import UserSecretsClient
from google import genai
from google.genai import types
import requests, subprocess, cv2, json
from pathlib import Path
secret = UserSecretsClient()
api_key = secret.get_secret("GOOGLE_API_KEY")
client = genai.Client(api_key=api_key)
Path("/kaggle/working/tron/videos").mkdir(parents=True, exist_ok=True)
Path("/kaggle/working/tron/frames").mkdir(parents=True, exist_ok=True)
print("✅ Gemma 4 подключена")
In [ ]:
# ── СКАЧИВАНИЕ ВИДЕО С RUTUBE ──────────────────────────────────
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Referer": "https://rutube.ru/",
}
def download_video(video_id, seconds=30):
out_path = f"/kaggle/working/tron/videos/{video_id}.mp4"
if Path(out_path).exists():
print(f" [=] Уже скачано")
return out_path
resp = requests.get(
f"https://rutube.ru/api/play/options/{video_id}/",
headers=headers, timeout=10
)
m3u8_url = resp.json()["video_balancer"]["m3u8"]
subprocess.run(
["ffmpeg", "-i", m3u8_url, "-c", "copy", "-t", str(seconds), out_path, "-y"],
capture_output=True
)
size = Path(out_path).stat().st_size // 1024
print(f" ✅ Скачано: {size} KB")
return out_path
def extract_frames(video_path, video_id, every_seconds=5, max_frames=6):
frames_dir = Path(f"/kaggle/working/tron/frames/{video_id}")
frames_dir.mkdir(parents=True, exist_ok=True)
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS) or 25
saved, count = [], 0
while len(saved) < max_frames:
ret, frame = cap.read()
if not ret: break
if count % int(fps * every_seconds) == 0:
path = str(frames_dir / f"frame_{count:06d}.jpg")
cv2.imwrite(path, frame)
saved.append(path)
count += 1
cap.release()
print(f" ✅ Кадров: {len(saved)}")
return saved
print("✅ Функции загрузки готовы")
In [ ]:
# ── ДИНАМИЧЕСКИЙ АНАЛИЗ ЧЕРЕЗ GEMMA 4 ─────────────────────────
def analyze_dynamic(frames, video_id):
contents = []
for i, fp in enumerate(frames):
contents.append(types.Part.from_bytes(
data=open(fp, "rb").read(), mime_type="image/jpeg"
))
contents.append(f"Кадр {i+1}")
contents.append("""
Ты — система TRON: раннее предупреждение землетрясений через поведение животных.
Перед тобой последовательные кадры с интервалом 5 секунд.
Проанализируй ДИНАМИКУ поведения от кадра к кадру:
- Как меняется расстояние между животными?
- Есть ли синхронные реакции?
- Есть ли защитное поведение, паника, скопление?
Временная шкала: опиши что происходит на каждом кадре.
Итог строго в формате:
СТАТУС: NORMAL / SUSPICIOUS / ANOMALY
УВЕРЕННОСТЬ: HIGH / MEDIUM / LOW
КЛЮЧЕВОЙ ПАТТЕРН: (одна фраза)
ОБОСНОВАНИЕ: (2-3 предложения)
""")
response = client.models.generate_content(
model="gemma-4-31b-it",
contents=contents
)
return response.text
print("✅ Функция анализа готова")
In [ ]:
# ── ЗАПУСК TRON ────────────────────────────────────────────────
# Слоны во время землетрясения — наш ключевой тест
VIDEOS = {
"a373489a111867d1f5ac7e0ebba5456c": "🐘 Слоны (землетрясение)",
"398399360ba36dc12230f2321b0ebfc6": "🐱 Кошка с котятами (норма)",
"d28d17606082b9bf719338e007b7f93d": "🐱 Кошка (норма)",
}
results = []
for video_id, label in VIDEOS.items():
print(f"\n{'='*55}")
print(f"📹 {label}")
print(f"{'='*55}")
video_path = download_video(video_id)
frames = extract_frames(video_path, video_id)
if not frames:
print(" ❌ Кадры не извлечены")
continue
print(" 🔍 Анализирую динамику...")
analysis = analyze_dynamic(frames, video_id)
print(analysis)
# Определяем итоговый статус
status = "🟢 NORMAL"
if "ANOMALY" in analysis.upper():
status = "🔴 ANOMALY"
elif "SUSPICIOUS" in analysis.upper():
status = "🟡 SUSPICIOUS"
results.append({"label": label, "status": status})
print(f"\n{'='*55}")
print("📊 ИТОГИ TRON:")
for r in results:
print(f" {r['status']} | {r['label']}")