kavehtaheri commited on
Commit
efe809b
·
verified ·
1 Parent(s): af4e991

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -19
app.py CHANGED
@@ -6,16 +6,12 @@ import time
6
  from moviepy.video.io.VideoFileClip import VideoFileClip
7
 
8
  # --- 1. CONFIGURATION & CONSTANTS ---
9
-
10
  # Securely load API key from Hugging Face Space secrets.
11
- ONE_API_KEY = os.environ.get("ONE_API_KEY", "268976:66f4f58a2a905") # Using your key for now, but secrets are better.
12
-
13
  # The custom endpoint for the one-api.ir service.
14
  ONE_API_URL = "https://api.one-api.ir/chatbot/v1/gpt4o/"
15
 
16
  # --- MASTER PROMPTS ---
17
-
18
- # Prompt for Mode 1: "Viral Spot for Shorts (< 3 mins)"
19
  PROMPT_SHORTS_MODE = """
20
  You are an expert producer of viral short-form content. Analyze the provided SRT transcript to find the single most impactful, hook-worthy segment for a video under 3 minutes (ideally 60-90 seconds).
21
 
@@ -35,7 +31,6 @@ Your output MUST be a single, valid JSON object and nothing else. Do not include
35
  }}
36
  """
37
 
38
- # Prompt for Mode 2: "Viral Narrative Clip (5-12 mins)"
39
  PROMPT_NARRATIVE_MODE = """
40
  You are an expert video editor and storyteller. Analyze the provided transcript to find the most compelling narrative segment between 5 and 12 minutes long.
41
 
@@ -55,10 +50,10 @@ Your output MUST be a single, valid JSON object and nothing else. Do not include
55
  }}
56
  """
57
 
58
- # --- 2. LLM AGENT WRAPPER ---
59
 
60
  def call_gpt4o_oneapi(transcript_content, prompt_template):
61
- """Makes a custom API call to the one-api.ir service."""
62
  if not ONE_API_KEY or not ONE_API_URL:
63
  raise ValueError("ONE_API_KEY and ONE_API_URL secrets are not set correctly.")
64
 
@@ -74,14 +69,27 @@ def call_gpt4o_oneapi(transcript_content, prompt_template):
74
  response.raise_for_status()
75
  result = response.json()
76
 
77
- if "result" in result and isinstance(result.get("result"), list) and len(result["result"]) > 0:
78
- message_content = result["result"][0].get("content")
 
 
 
 
 
 
 
 
 
79
  if message_content:
80
  return message_content
81
  else:
82
- return f"Error: 'content' key not found in API response item.\nFull response: {json.dumps(result)}"
 
 
 
83
  else:
84
- return f"Error: Unexpected JSON structure in API response. 'result' list not found or empty.\nFull response: {json.dumps(result)}"
 
85
 
86
  except requests.exceptions.HTTPError as e:
87
  return f"HTTP Error calling API: {e}\nResponse Body: {e.response.text}"
@@ -114,12 +122,15 @@ def generate_viral_clip(video_file, srt_file, analysis_mode, progress=gr.Progres
114
  return llm_response_str, None
115
 
116
  try:
117
- cleaned_response = llm_response_str.strip().replace("```json", "").replace("```", "")
 
 
 
 
 
 
118
  parsed_response = json.loads(cleaned_response)
119
 
120
- # --- ROBUSTNESS FIX APPLIED HERE ---
121
- # Check if the parsed response is a dictionary. If not, the AI returned a simple string
122
- # instead of the requested JSON object. Raise a TypeError to handle it as a parsing failure.
123
  if not isinstance(parsed_response, dict):
124
  raise TypeError(f"AI did not return a valid JSON object. It returned a {type(parsed_response).__name__}.")
125
 
@@ -134,7 +145,6 @@ def generate_viral_clip(video_file, srt_file, analysis_mode, progress=gr.Progres
134
  f"Clipping video from {time.strftime('%H:%M:%S', time.gmtime(start_time))} to {time.strftime('%H:%M:%S', time.gmtime(end_time))}.")
135
 
136
  except (json.JSONDecodeError, KeyError, TypeError) as e:
137
- # The new TypeError will be caught here, providing a clear error message.
138
  error_msg = f"Error: Failed to parse AI response. Details: {e}\n\nRaw AI Response:\n---\n{llm_response_str}"
139
  return error_msg, None
140
 
@@ -152,10 +162,10 @@ def generate_viral_clip(video_file, srt_file, analysis_mode, progress=gr.Progres
152
  return summary, output_filename
153
 
154
  except Exception as e:
155
- return f"An unexpected error occurred: {str(e)}", None
 
156
 
157
  # --- 4. GRADIO UI DEFINITION ---
158
-
159
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
160
  gr.Markdown(
161
  """
 
6
  from moviepy.video.io.VideoFileClip import VideoFileClip
7
 
8
  # --- 1. CONFIGURATION & CONSTANTS ---
 
9
  # Securely load API key from Hugging Face Space secrets.
10
+ ONE_API_KEY = os.environ.get("ONE_API_KEY", "268976:66f4f58a2a905") # Using your key for now, secrets are better.
 
11
  # The custom endpoint for the one-api.ir service.
12
  ONE_API_URL = "https://api.one-api.ir/chatbot/v1/gpt4o/"
13
 
14
  # --- MASTER PROMPTS ---
 
 
15
  PROMPT_SHORTS_MODE = """
16
  You are an expert producer of viral short-form content. Analyze the provided SRT transcript to find the single most impactful, hook-worthy segment for a video under 3 minutes (ideally 60-90 seconds).
17
 
 
31
  }}
32
  """
33
 
 
34
  PROMPT_NARRATIVE_MODE = """
35
  You are an expert video editor and storyteller. Analyze the provided transcript to find the most compelling narrative segment between 5 and 12 minutes long.
36
 
 
50
  }}
51
  """
52
 
53
+ # --- 2. LLM AGENT WRAPPER (WITH DEFINITIVE FIX) ---
54
 
55
  def call_gpt4o_oneapi(transcript_content, prompt_template):
56
+ """Makes a robust, custom API call to the one-api.ir service."""
57
  if not ONE_API_KEY or not ONE_API_URL:
58
  raise ValueError("ONE_API_KEY and ONE_API_URL secrets are not set correctly.")
59
 
 
69
  response.raise_for_status()
70
  result = response.json()
71
 
72
+ # Check for the basic expected structure
73
+ if "result" not in result or not isinstance(result.get("result"), list) or len(result["result"]) == 0:
74
+ return f"Error: Unexpected JSON structure from API. 'result' list not found or empty.\nFull response: {json.dumps(result)}"
75
+
76
+ first_item_in_result = result["result"][0]
77
+
78
+ # --- THE CRITICAL FIX IS HERE ---
79
+ # The API can return a dict OR a string inside the list. We must handle both.
80
+ if isinstance(first_item_in_result, dict):
81
+ # This is the expected case: {"content": "..."}
82
+ message_content = first_item_in_result.get("content")
83
  if message_content:
84
  return message_content
85
  else:
86
+ return f"Error: 'content' key not found in API response dictionary.\nFull response: {json.dumps(result)}"
87
+ elif isinstance(first_item_in_result, str):
88
+ # This is the alternate case: the string is the entire response.
89
+ return first_item_in_result
90
  else:
91
+ # Handle any other unexpected type
92
+ return f"Error: Unknown item type in API 'result' list.\nFull response: {json.dumps(result)}"
93
 
94
  except requests.exceptions.HTTPError as e:
95
  return f"HTTP Error calling API: {e}\nResponse Body: {e.response.text}"
 
122
  return llm_response_str, None
123
 
124
  try:
125
+ # Clean potential markdown code fences from the AI response
126
+ cleaned_response = llm_response_str.strip()
127
+ if cleaned_response.startswith("```json"):
128
+ cleaned_response = cleaned_response[7:]
129
+ if cleaned_response.endswith("```"):
130
+ cleaned_response = cleaned_response[:-3]
131
+
132
  parsed_response = json.loads(cleaned_response)
133
 
 
 
 
134
  if not isinstance(parsed_response, dict):
135
  raise TypeError(f"AI did not return a valid JSON object. It returned a {type(parsed_response).__name__}.")
136
 
 
145
  f"Clipping video from {time.strftime('%H:%M:%S', time.gmtime(start_time))} to {time.strftime('%H:%M:%S', time.gmtime(end_time))}.")
146
 
147
  except (json.JSONDecodeError, KeyError, TypeError) as e:
 
148
  error_msg = f"Error: Failed to parse AI response. Details: {e}\n\nRaw AI Response:\n---\n{llm_response_str}"
149
  return error_msg, None
150
 
 
162
  return summary, output_filename
163
 
164
  except Exception as e:
165
+ # This generic catch-all is our final safety net.
166
+ return f"An unexpected error occurred in the main process: {str(e)}", None
167
 
168
  # --- 4. GRADIO UI DEFINITION ---
 
169
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
170
  gr.Markdown(
171
  """