Spaces:
Running
Running
| import json | |
| import os | |
| import time | |
| from core.logger import logger | |
| from typing import Dict, Any | |
| from prompt.system_prompt_script import SYSTEM_PROMPT | |
| from schema.pydantic_schema_script import ScriptResponse | |
| from google import genai | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| GEMINI_API_KEY = os.getenv("GEMINI_KEY") | |
| def configure_gemini(): | |
| return genai.Client(api_key=GEMINI_API_KEY) | |
| def generate_scripts( | |
| video_path: str, | |
| offer_details: str, | |
| target_audience: str, | |
| specific_hooks: str, | |
| additional_context: str, | |
| num_scripts: int = 3, | |
| duration: int = 60 | |
| ) -> Dict[str, Any]: | |
| client = configure_gemini() | |
| try: | |
| user_prompt = f""" | |
| Generate {num_scripts} high-converting direct response script variations, | |
| each about {duration} seconds long. | |
| Each variation MUST be designed for a total runtime β€ {duration} seconds. | |
| - Do NOT include any timestamp beyond {duration}s. | |
| - Keep all beats within 0β{duration}s. | |
| - Use timestamps as "M:SS" (e.g., "0:03", "0:12"). | |
| CONTEXT TO FOLLOW: | |
| - Offer Details: {offer_details} | |
| - Target Audience: {target_audience} | |
| - Specific Hooks: {specific_hooks} | |
| ADDITIONAL CONTEXT: | |
| {additional_context} | |
| You must reflect this additional context in: | |
| - The script tone, CTA, visuals | |
| - Compliance or branding constraints | |
| - Any assumptions about audience or product | |
| Failure to include this will be considered incomplete. | |
| Please provide a comprehensive analysis including: | |
| 1. DETAILED VIDEO ANALYSIS with timestamp-based metrics: | |
| - Break down the video into 5-10 second segments | |
| - Rate each segment's effectiveness (1-10 scale) | |
| - Identify specific elements (hook, transition, proof, CTA, etc.) | |
| 2. TIMESTAMP-BASED IMPROVEMENTS: | |
| - Specific recommendations for each time segment | |
| - Priority level for each improvement | |
| - Expected impact of implementing changes | |
| 3. SCRIPT VARIATIONS: | |
| - Create complete script variations | |
| - Each with timestamp-by-timestamp breakdown | |
| - Different psychological triggers and approaches | |
| IMPORTANT: Return only valid JSON in the exact format specified in the system prompt. Analyze the video second-by-second for maximum detail.""" | |
| video_file = client.files.upload(file=video_path) | |
| while getattr(video_file.state, "name", "") == "PROCESSING": | |
| time.sleep(1.0) | |
| video_file = client.files.get(name=video_file.name) | |
| if getattr(video_file.state, "name", "") == "FAILED": | |
| logger.error("Video processing FAILED.") | |
| return {} | |
| resp = client.models.generate_content( | |
| model="gemini-2.0-flash", | |
| contents=[SYSTEM_PROMPT, user_prompt, video_file], | |
| config={ | |
| "response_mime_type": "application/json", | |
| "response_schema": ScriptResponse, | |
| }, | |
| ) | |
| parsed = getattr(resp, "parsed", None) | |
| if parsed is None: | |
| raw_text = getattr(resp, "text", "") or "" | |
| if not raw_text: | |
| parts = None | |
| if getattr(resp, "candidates", None): | |
| parts = getattr(resp.candidates[0].content, "parts", None) | |
| raise RuntimeError(f"Model returned no JSON text. parts={parts}") | |
| data = json.loads(raw_text) | |
| return data | |
| out = parsed.model_dump() | |
| logger.info("Generated %d variations.", len(out.get("script_variations", []))) | |
| return out | |
| except Exception as e: | |
| logger.exception("generate_scripts failed: %s", e) | |
| return {} | |