alisaadhq commited on
Commit
cd3139e
·
verified ·
1 Parent(s): 0de0dd3

Update core/analyze.py

Browse files
Files changed (1) hide show
  1. core/analyze.py +94 -56
core/analyze.py CHANGED
@@ -13,91 +13,121 @@ logger = logging.getLogger(__name__)
13
 
14
  # Configure Groq Client
15
  api_key = os.getenv("GROQ_API_KEY")
16
- MODEL_NAME = os.getenv("GROQ_MODEL", "llama-3.1-8b-instant")
17
 
18
  client = Groq(api_key=api_key)
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  def analyze_transcript(transcript):
22
- """Analyze transcript using Groq API."""
23
 
24
  prompt = f"""
25
- You are an expert video editor and viral content strategist.
26
- Your task is to identify the most engaging segments from the provided transcript
27
- that are suitable for short-form video platforms like TikTok, Reels, and YouTube Shorts.
28
-
29
- **STRICT REQUIREMENTS:**
30
- 1. **Duration**: duration MUST be between 60 seconds and 180 seconds (3 minutes)
31
- 2. **Context Preservation**: Each segment must be a complete thought - no abrupt cuts
32
- 3. **Sentence Boundaries**: Start at the beginning of a sentence, end at a natural conclusion
33
- 4. **Meaning Coherence**: The clip must make sense on its own without requiring prior context
34
-
35
- **SELECTION CRITERIA:**
36
- - Strong hooks that grab attention
37
- - Emotional moments, humor, or surprising revelations
38
- - Clear beginning, middle, and satisfying conclusion
39
- - High shareability potential
40
-
41
- **JSON OUTPUT FORMAT (REQUIRED):**
42
  {{
43
- "segments": [
44
- {{
45
- "start_time": <float, start time in seconds>,
46
- "end_time": <float, end time in seconds>,
47
- "duration": <float, duration in seconds (30-180)>,
48
- "description": "<string, brief summary of the clip content 10 words max>",
49
- "viral_score": <float, score from 0-10 indicating viral potential>,
50
- "reason": "<string, explanation of why this segment is engaging>"
51
- }}
52
- ]
53
  }}
54
-
55
- **IMPORTANT NOTES:**
56
- - If no suitable segments are found, return {{ "segments": [] }}
57
- - Ensure all strings are properly escaped
58
- - Each segment must be a complete, coherent thought
59
- - Avoid cutting mid-sentence or mid-thought
60
-
61
- Transcript to Analyze:
62
- {transcript}
63
- """
 
64
 
65
  max_retries = 3
66
  base_delay = 5
67
- content = None
68
 
69
  for attempt in range(max_retries):
70
  try:
71
  response = client.chat.completions.create(
72
  model=MODEL_NAME,
73
  messages=[
74
- {"role": "system", "content": "You are a helpful assistant that outputs only valid JSON."},
 
 
 
75
  {"role": "user", "content": prompt}
76
  ],
77
- temperature=0.7,
78
  )
79
 
80
- content = response.choices[0].message.content
81
- print(f"🤖 AI Raw Response (First 500 chars): {content[:500]}...")
82
 
83
- # Clean Markdown code blocks if present
84
  if "```json" in content:
85
  content = content.split("```json")[1].split("```")[0].strip()
86
  elif "```" in content:
87
  content = content.split("```")[1].split("```")[0].strip()
88
 
89
- # Validate JSON and log segment count
90
  data = json.loads(content)
91
- segments_count = len(data.get("segments", []))
92
- print(f"🤖 AI Response parsed successfully: Found {segments_count} segments.")
 
93
 
 
 
94
  return {"content": content}
95
 
96
  except Exception as e:
97
- print(f"❌ Error in Groq analysis: {e}")
98
  if attempt < max_retries - 1:
99
  wait_time = base_delay * (2 ** attempt)
100
- print(f"⚠️ Retrying task in {wait_time}s...")
101
  time.sleep(wait_time)
102
  else:
103
  break
@@ -108,8 +138,7 @@ def analyze_transcript(transcript):
108
 
109
  def smart_chunk_transcript(transcript, max_tokens=4000):
110
  """
111
- Split transcript into coherent chunks at sentence boundaries
112
- while preserving context and meaning.
113
  """
114
  sentences = transcript.replace('\n', ' ').split('. ')
115
  chunks = []
@@ -158,7 +187,7 @@ def analyze_transcript_with_chunking(transcript):
158
  continue
159
 
160
  if all_segments:
161
- all_segments.sort(key=lambda x: x.get('viral_score', 0), reverse=True)
162
  unique_segments = []
163
  seen_times = set()
164
 
@@ -183,6 +212,10 @@ if __name__ == "__main__":
183
  [45.0 - 60.0] This has saved me hours every week. I batch my emails, phone calls, and even errands.
184
  [60.0 - 90.0] The third hack is the Pomodoro Technique. Work for 25 minutes, then take a 5-minute break.
185
  [90.0 - 120.0] This technique helps me stay focused and avoid burnout. I get more done in less time.
 
 
 
 
186
  """
187
 
188
  logger.info("🧪 Testing AI Analysis...")
@@ -191,11 +224,16 @@ if __name__ == "__main__":
191
  try:
192
  data = json.loads(result['content'])
193
  segments = data.get('segments', [])
194
- logger.info(f"✅ Found {len(segments)} viral segments:")
195
 
196
  for i, seg in enumerate(segments):
197
- logger.info(f" #{i+1} [{seg['start_time']:.0f}s-{seg['end_time']:.0f}s] "
198
- f"Score: {seg['viral_score']}/10 - {seg['description']}")
 
 
 
 
 
199
  except Exception as e:
200
  logger.error(f"❌ Error parsing result: {e}")
201
  logger.info(f"Raw result: {result}")
 
13
 
14
  # Configure Groq Client
15
  api_key = os.getenv("GROQ_API_KEY")
16
+ MODEL_NAME = os.getenv("GROQ_MODEL", "openai/gpt-oss-120b")
17
 
18
  client = Groq(api_key=api_key)
19
 
20
+ MIN_DURATION = 60 # seconds
21
+ MAX_DURATION = 180 # seconds
22
+
23
+
24
+ def validate_segments(segments):
25
+ """
26
+ Remove segments that don't meet duration requirements (60-180 seconds).
27
+ Recalculates duration from start/end times — never trusts AI's duration field.
28
+ """
29
+ valid = []
30
+ for seg in segments:
31
+ start = seg.get("start_time", 0)
32
+ end = seg.get("end_time", 0)
33
+ duration = end - start
34
+
35
+ if duration < MIN_DURATION:
36
+ print(f"⚠️ Skipped short segment: {duration:.1f}s → [{start}s–{end}s] ({seg.get('description', '')})")
37
+ continue
38
+
39
+ if duration > MAX_DURATION:
40
+ print(f"⚠️ Skipped long segment: {duration:.1f}s → [{start}s–{end}s] ({seg.get('description', '')})")
41
+ continue
42
+
43
+ seg["duration"] = round(duration, 2)
44
+ valid.append(seg)
45
+
46
+ print(f"✅ Valid segments after duration filter: {len(valid)}/{len(segments)}")
47
+ return valid
48
+
49
 
50
  def analyze_transcript(transcript):
51
+ """Analyze transcript using Groq API — minimal output, maximum quality."""
52
 
53
  prompt = f"""
54
+ You are an expert viral video editor. Analyze this transcript and find the best self-contained segments for TikTok/Reels/YouTube Shorts.
55
+
56
+ SEGMENT RULES (STRICT):
57
+ - Duration MUST be 60–180 seconds (end_time - start_time >= 60)
58
+ - Must be a COMPLETE thought: natural start, full story/point, satisfying end
59
+ - Must make sense WITHOUT watching anything before or after it
60
+ - NO mid-sentence cuts, NO abrupt endings
61
+
62
+ QUALITY CRITERIA (pick segments that have ALL of these):
63
+ - Strong hook in the first few seconds that grabs attention
64
+ - One clear emotional core: funny / surprising / inspiring / controversial
65
+ - Builds naturally to a satisfying conclusion
66
+ - Highly shareable standalone moment
67
+
68
+ OUTPUT return ONLY this JSON, nothing else:
69
+ {{
70
+ "segments": [
71
  {{
72
+ "start_time": <float>,
73
+ "end_time": <float>,
74
+ "title": "<YouTube-ready title, punchy, max 60 chars>",
75
+ "description": "<YouTube description, 1-2 sentences, include relevant keywords>",
76
+ "reason": "<why this specific segment is complete and viral-worthy, max 20 words>"
 
 
 
 
 
77
  }}
78
+ ]
79
+ }}
80
+
81
+ RULES:
82
+ - end_time - start_time MUST be >= 60, skip any segment shorter than that
83
+ - Return empty segments array if nothing qualifies: {{"segments": []}}
84
+ - Raw JSON only, no markdown, no explanation
85
+
86
+ TRANSCRIPT:
87
+ {transcript}
88
+ """
89
 
90
  max_retries = 3
91
  base_delay = 5
 
92
 
93
  for attempt in range(max_retries):
94
  try:
95
  response = client.chat.completions.create(
96
  model=MODEL_NAME,
97
  messages=[
98
+ {
99
+ "role": "system",
100
+ "content": "You are a JSON-only assistant. Output raw JSON with no markdown, no explanation, no code blocks."
101
+ },
102
  {"role": "user", "content": prompt}
103
  ],
104
+ temperature=0.3,
105
  )
106
 
107
+ content = response.choices[0].message.content.strip()
108
+ print(f"🤖 AI Raw Response (First 300 chars): {content[:300]}...")
109
 
110
+ # Strip markdown if model ignores system prompt
111
  if "```json" in content:
112
  content = content.split("```json")[1].split("```")[0].strip()
113
  elif "```" in content:
114
  content = content.split("```")[1].split("```")[0].strip()
115
 
116
+ # Parse and validate
117
  data = json.loads(content)
118
+ raw_segments = data.get("segments", [])
119
+ valid_segments = validate_segments(raw_segments)
120
+ data["segments"] = valid_segments
121
 
122
+ content = json.dumps(data)
123
+ print(f"🤖 Parsed: {len(raw_segments)} raw → {len(valid_segments)} valid segments.")
124
  return {"content": content}
125
 
126
  except Exception as e:
127
+ print(f"❌ Error in Groq analysis (attempt {attempt + 1}): {e}")
128
  if attempt < max_retries - 1:
129
  wait_time = base_delay * (2 ** attempt)
130
+ print(f"⚠️ Retrying in {wait_time}s...")
131
  time.sleep(wait_time)
132
  else:
133
  break
 
138
 
139
  def smart_chunk_transcript(transcript, max_tokens=4000):
140
  """
141
+ Split transcript into coherent chunks at sentence boundaries.
 
142
  """
143
  sentences = transcript.replace('\n', ' ').split('. ')
144
  chunks = []
 
187
  continue
188
 
189
  if all_segments:
190
+ # Sort by viral quality (reason length as proxy, or add viral_score back if needed)
191
  unique_segments = []
192
  seen_times = set()
193
 
 
212
  [45.0 - 60.0] This has saved me hours every week. I batch my emails, phone calls, and even errands.
213
  [60.0 - 90.0] The third hack is the Pomodoro Technique. Work for 25 minutes, then take a 5-minute break.
214
  [90.0 - 120.0] This technique helps me stay focused and avoid burnout. I get more done in less time.
215
+ [120.0 - 150.0] The fourth hack is to eliminate distractions completely. Turn off notifications, close tabs, and focus.
216
+ [150.0 - 180.0] When you eliminate distractions, your productivity skyrockets. I finish in 2 hours what used to take 6.
217
+ [180.0 - 210.0] The fifth and final hack is to review your day every evening. Spend 5 minutes planning tomorrow.
218
+ [210.0 - 240.0] This evening review changed everything for me. I wake up knowing exactly what to do and I never waste morning time figuring out priorities.
219
  """
220
 
221
  logger.info("🧪 Testing AI Analysis...")
 
224
  try:
225
  data = json.loads(result['content'])
226
  segments = data.get('segments', [])
227
+ logger.info(f"✅ Found {len(segments)} valid segments:\n")
228
 
229
  for i, seg in enumerate(segments):
230
+ duration = seg['end_time'] - seg['start_time']
231
+ logger.info(
232
+ f"#{i+1} [{seg['start_time']:.0f}s – {seg['end_time']:.0f}s] ({duration:.0f}s)\n"
233
+ f" 📌 Title: {seg.get('title', 'N/A')}\n"
234
+ f" 📝 Description: {seg.get('description', 'N/A')}\n"
235
+ f" 💡 Reason: {seg.get('reason', 'N/A')}\n"
236
+ )
237
  except Exception as e:
238
  logger.error(f"❌ Error parsing result: {e}")
239
  logger.info(f"Raw result: {result}")