Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -50,7 +50,7 @@ Your output MUST be a single, valid JSON object and nothing else. Do not include
|
|
50 |
}}
|
51 |
"""
|
52 |
|
53 |
-
# --- 2. LLM AGENT WRAPPER
|
54 |
|
55 |
def call_gpt4o_oneapi(transcript_content, prompt_template):
|
56 |
"""Makes a robust, custom API call to the one-api.ir service."""
|
@@ -69,26 +69,20 @@ def call_gpt4o_oneapi(transcript_content, prompt_template):
|
|
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:
|
@@ -98,9 +92,10 @@ def call_gpt4o_oneapi(transcript_content, prompt_template):
|
|
98 |
except json.JSONDecodeError:
|
99 |
return f"Error: Failed to decode JSON from API response.\nResponse Body: {response.text}"
|
100 |
|
101 |
-
# --- 3. CORE ORCHESTRATOR FUNCTION ---
|
102 |
|
103 |
def generate_viral_clip(video_file, srt_file, analysis_mode, progress=gr.Progress()):
|
|
|
104 |
if not video_file or not srt_file:
|
105 |
return "Error: Please upload both a video file and an SRT file.", None
|
106 |
if not ONE_API_KEY or not ONE_API_URL:
|
@@ -108,7 +103,8 @@ def generate_viral_clip(video_file, srt_file, analysis_mode, progress=gr.Progres
|
|
108 |
|
109 |
try:
|
110 |
progress(0.1, desc="Reading SRT file...")
|
111 |
-
|
|
|
112 |
transcript_content = f.read()
|
113 |
|
114 |
progress(0.2, desc="Preparing analysis prompt...")
|
@@ -122,7 +118,6 @@ def generate_viral_clip(video_file, srt_file, analysis_mode, progress=gr.Progres
|
|
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:]
|
@@ -150,7 +145,8 @@ def generate_viral_clip(video_file, srt_file, analysis_mode, progress=gr.Progres
|
|
150 |
|
151 |
progress(0.8, desc="Clipping video...")
|
152 |
output_filename = "viral_clip.mp4"
|
153 |
-
|
|
|
154 |
if end_time > video.duration:
|
155 |
end_time = video.duration
|
156 |
summary += f"\n\n⚠️ Warning: End time was beyond video duration, adjusted to {end_time:.2f}s."
|
@@ -162,7 +158,6 @@ def generate_viral_clip(video_file, srt_file, analysis_mode, progress=gr.Progres
|
|
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 ---
|
@@ -197,3 +192,4 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
197 |
|
198 |
if __name__ == "__main__":
|
199 |
demo.launch(debug=True)
|
|
|
|
50 |
}}
|
51 |
"""
|
52 |
|
53 |
+
# --- 2. LLM AGENT WRAPPER ---
|
54 |
|
55 |
def call_gpt4o_oneapi(transcript_content, prompt_template):
|
56 |
"""Makes a robust, custom API call to the one-api.ir service."""
|
|
|
69 |
response.raise_for_status()
|
70 |
result = response.json()
|
71 |
|
|
|
72 |
if "result" not in result or not isinstance(result.get("result"), list) or len(result["result"]) == 0:
|
73 |
return f"Error: Unexpected JSON structure from API. 'result' list not found or empty.\nFull response: {json.dumps(result)}"
|
74 |
|
75 |
first_item_in_result = result["result"][0]
|
76 |
|
|
|
|
|
77 |
if isinstance(first_item_in_result, dict):
|
|
|
78 |
message_content = first_item_in_result.get("content")
|
79 |
if message_content:
|
80 |
return message_content
|
81 |
else:
|
82 |
return f"Error: 'content' key not found in API response dictionary.\nFull response: {json.dumps(result)}"
|
83 |
elif isinstance(first_item_in_result, str):
|
|
|
84 |
return first_item_in_result
|
85 |
else:
|
|
|
86 |
return f"Error: Unknown item type in API 'result' list.\nFull response: {json.dumps(result)}"
|
87 |
|
88 |
except requests.exceptions.HTTPError as e:
|
|
|
92 |
except json.JSONDecodeError:
|
93 |
return f"Error: Failed to decode JSON from API response.\nResponse Body: {response.text}"
|
94 |
|
95 |
+
# --- 3. CORE ORCHESTRATOR FUNCTION (WITH GRADIO 4.x FIX) ---
|
96 |
|
97 |
def generate_viral_clip(video_file, srt_file, analysis_mode, progress=gr.Progress()):
|
98 |
+
# The `video_file` and `srt_file` inputs are now file PATHS (strings), not objects.
|
99 |
if not video_file or not srt_file:
|
100 |
return "Error: Please upload both a video file and an SRT file.", None
|
101 |
if not ONE_API_KEY or not ONE_API_URL:
|
|
|
103 |
|
104 |
try:
|
105 |
progress(0.1, desc="Reading SRT file...")
|
106 |
+
# FIX: Use `srt_file` directly, as it's now a path string.
|
107 |
+
with open(srt_file, 'r', encoding='utf-8') as f:
|
108 |
transcript_content = f.read()
|
109 |
|
110 |
progress(0.2, desc="Preparing analysis prompt...")
|
|
|
118 |
return llm_response_str, None
|
119 |
|
120 |
try:
|
|
|
121 |
cleaned_response = llm_response_str.strip()
|
122 |
if cleaned_response.startswith("```json"):
|
123 |
cleaned_response = cleaned_response[7:]
|
|
|
145 |
|
146 |
progress(0.8, desc="Clipping video...")
|
147 |
output_filename = "viral_clip.mp4"
|
148 |
+
# FIX: Use `video_file` directly, as it's now a path string.
|
149 |
+
with VideoFileClip(video_file) as video:
|
150 |
if end_time > video.duration:
|
151 |
end_time = video.duration
|
152 |
summary += f"\n\n⚠️ Warning: End time was beyond video duration, adjusted to {end_time:.2f}s."
|
|
|
158 |
return summary, output_filename
|
159 |
|
160 |
except Exception as e:
|
|
|
161 |
return f"An unexpected error occurred in the main process: {str(e)}", None
|
162 |
|
163 |
# --- 4. GRADIO UI DEFINITION ---
|
|
|
192 |
|
193 |
if __name__ == "__main__":
|
194 |
demo.launch(debug=True)
|
195 |
+
|