File size: 4,100 Bytes
1924d43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2109292
 
 
 
 
 
 
 
1924d43
 
 
 
 
2109292
1924d43
 
 
 
 
 
2109292
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1924d43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2109292
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import json
import os
import time
import logging
from typing import Dict, Any

from prompt.system_prompt import SYSTEM_PROMPT
from schema_script import ScriptResponse  
from google import genai
from dotenv import load_dotenv

load_dotenv()
GEMINI_API_KEY = os.getenv("GEMINI_KEY")

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[logging.StreamHandler()]
)
logger = logging.getLogger(__name__)


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 {}