"""ELAI avatar video generation service.""" import logging import time _logger = logging.getLogger(__name__) try: import requests as _requests except ImportError: _requests = None ELAI_BASE = "https://apis.elai.io/api/v1" class ElaiService: """Generate avatar videos for listening exercises and instructional content.""" def __init__(self, env): self.env = env self._get_param = env["ir.config_parameter"].sudo().get_param def _get_token(self): token = self._get_param("encoach_ai.elai_token", "") if not token: import os token = os.environ.get("ELAI_TOKEN", "") if not token: raise RuntimeError("ELAI token not configured — set in AI Settings") return token def _headers(self): return { "Authorization": f"Bearer {self._get_token()}", "Content-Type": "application/json", } def _log(self, action, latency, status="success", error=None): try: self.env["encoach.ai.log"].sudo().create({ "service": "elai", "action": action, "latency_ms": latency, "status": status, "error_message": error, }) except Exception: pass def list_avatars(self): """List available ELAI avatars.""" if not _requests: raise RuntimeError("requests package not installed") resp = _requests.get(f"{ELAI_BASE}/avatars", headers=self._headers(), timeout=15) resp.raise_for_status() return resp.json() def create_video(self, script, *, avatar_id=None, title="EnCoach Video", language="en"): """Create an avatar video from a script. Returns: dict with 'video_id', 'status' """ if not _requests: raise RuntimeError("requests package not installed") payload = { "name": title, "slides": [ { "speech": script, "avatar": avatar_id or "default", "language": language, } ], } t0 = time.time() try: resp = _requests.post( f"{ELAI_BASE}/videos", json=payload, headers=self._headers(), timeout=30, ) resp.raise_for_status() data = resp.json() self._log("create_video", int((time.time() - t0) * 1000)) return {"video_id": data.get("_id", data.get("id")), "status": data.get("status", "pending")} except Exception as exc: self._log("create_video", int((time.time() - t0) * 1000), "error", str(exc)) raise def get_video_status(self, video_id): """Check video generation status.""" if not _requests: raise RuntimeError("requests package not installed") resp = _requests.get( f"{ELAI_BASE}/videos/{video_id}", headers=self._headers(), timeout=15, ) resp.raise_for_status() data = resp.json() return { "video_id": video_id, "status": data.get("status", "unknown"), "url": data.get("url", ""), "duration": data.get("duration"), }