fix: correct ELAI render URL and split long scripts into multiple slides

Made-with: Cursor
This commit is contained in:
Yamen Ahmad
2026-04-12 03:31:45 +04:00
parent 15aab279ec
commit 953879d19a
2 changed files with 63 additions and 32 deletions

View File

@@ -72,9 +72,36 @@ class ElaiService:
resp.raise_for_status() resp.raise_for_status()
return resp.json() return resp.json()
@staticmethod
def _split_script(script, max_chars=500):
"""Split a long script into chunks that stay under ELAI's 60s/slide limit.
Uses ~10 chars/second heuristic, so 500 chars ~ 50s (with safety margin).
Splits on sentence boundaries ('. ', '? ', '! ', newlines).
"""
if len(script) <= max_chars:
return [script]
import re
sentences = re.split(r'(?<=[.!?])\s+|\n+', script)
chunks, current = [], ""
for sent in sentences:
if not sent.strip():
continue
if current and len(current) + len(sent) + 1 > max_chars:
chunks.append(current.strip())
current = sent
else:
current = f"{current} {sent}" if current else sent
if current.strip():
chunks.append(current.strip())
return chunks or [script]
def create_video(self, script, *, avatar_id=None, title="EnCoach Video", language="en"): def create_video(self, script, *, avatar_id=None, title="EnCoach Video", language="en"):
"""Create an avatar video from a script. """Create an avatar video from a script.
Automatically splits long scripts into multiple slides to stay under
ELAI's 60-second-per-slide limit.
Returns: Returns:
dict with 'video_id', 'status' dict with 'video_id', 'status'
""" """
@@ -85,12 +112,12 @@ class ElaiService:
avatar_code = avatar_preset["code"] avatar_code = avatar_preset["code"]
avatar_src = f"https://elai-avatars.s3.us-east-2.amazonaws.com/common/{avatar_code.replace('.', '/')}/{avatar_code.replace('.', '_')}.png" avatar_src = f"https://elai-avatars.s3.us-east-2.amazonaws.com/common/{avatar_code.replace('.', '/')}/{avatar_code.replace('.', '_')}.png"
payload = { chunks = self._split_script(script)
"name": title, slides = []
"slides": [ for idx, chunk in enumerate(chunks, 1):
{ slides.append({
"id": 1, "id": idx,
"speech": script, "speech": chunk,
"language": "English", "language": "English",
"voice": avatar_preset["voice"], "voice": avatar_preset["voice"],
"voiceType": "text", "voiceType": "text",
@@ -116,8 +143,12 @@ class ElaiService:
} }
], ],
}, },
} })
], _logger.info("ELAI: creating video with %d slide(s) from %d chars", len(slides), len(script))
payload = {
"name": title,
"slides": slides,
"tags": ["encoach"], "tags": ["encoach"],
} }
t0 = time.time() t0 = time.time()
@@ -135,7 +166,7 @@ class ElaiService:
# Step 2: trigger rendering -- ELAI requires a separate render call # Step 2: trigger rendering -- ELAI requires a separate render call
try: try:
render_resp = _requests.post( render_resp = _requests.post(
f"{ELAI_BASE}/videos/{video_id}/render", f"{ELAI_BASE}/videos/render/{video_id}",
headers=self._headers(), headers=self._headers(),
timeout=30, timeout=30,
) )