Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -14,10 +14,7 @@ try:
|
|
14 |
genai.configure(api_key=os.environ["GEMINI_API_KEY"])
|
15 |
tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
|
16 |
RUNWAY_API_KEY = os.environ["RUNWAY_API_KEY"]
|
17 |
-
# We don't need to initialize the elevenlabs_client for now
|
18 |
-
# elevenlabs_client = ElevenLabs(api_key=os.environ["ELEVENLABS_API_KEY"])
|
19 |
except KeyError as e:
|
20 |
-
# We remove ELEVENLABS_API_KEY from the required list for now
|
21 |
if 'ELEVENLABS_API_KEY' not in str(e):
|
22 |
raise ValueError(f"API Key Error: Please set the {e} secret in your Hugging Face Space settings.")
|
23 |
|
@@ -63,30 +60,34 @@ def generate_video_from_topic(topic_prompt, progress=gr.Progress(track_tqdm=True
|
|
63 |
except (json.JSONDecodeError, KeyError) as e:
|
64 |
raise gr.Error(f"Gemini did not return valid JSON. Error: {e}. Response was: {response.text}")
|
65 |
|
66 |
-
#
|
67 |
progress(0.3, desc="ποΈ MOCKING voiceover to save credits...")
|
68 |
audio_path = f"audio_{job_id}.mp3"
|
69 |
intermediate_files.append(audio_path)
|
70 |
-
|
71 |
-
# --- We now create a silent placeholder audio file instead of calling the API ---
|
72 |
-
# This creates a silent mp3 file with a realistic length based on the script.
|
73 |
-
narration_duration = len(narration.split()) / 2.5 # Rough estimate: 2.5 words per second
|
74 |
subprocess.run([
|
75 |
'ffmpeg', '-f', 'lavfi', '-i', f'anullsrc=r=44100:cl=mono',
|
76 |
'-t', str(narration_duration), '-q:a', '9', '-acodec', 'libmp3lame',
|
77 |
audio_path, '-y'
|
78 |
], check=True)
|
79 |
print(f"MOCK audio file saved (no credits used): {audio_path}")
|
80 |
-
# !!!!!!!!!!! END OF DISABLED SECTION !!!!!!!!!!!
|
81 |
|
82 |
# STEP 4: VISUALS (Runway)
|
83 |
video_clip_paths = []
|
84 |
for i, scene_prompt in enumerate(scene_prompts):
|
85 |
progress(0.4 + (i * 0.12), desc=f"π¬ Generating video scene {i+1}/{len(scene_prompts)}...")
|
86 |
|
87 |
-
|
88 |
-
# The
|
89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
if post_response.status_code != 200:
|
92 |
raise gr.Error(f"Runway API Error (start job): {post_response.status_code} - {post_response.text}")
|
@@ -97,7 +98,6 @@ def generate_video_from_topic(topic_prompt, progress=gr.Progress(track_tqdm=True
|
|
97 |
|
98 |
video_url = None
|
99 |
for _ in range(60):
|
100 |
-
# Polling URL is general and correct
|
101 |
get_response = requests.get(f"{RUNWAY_API_URL}/tasks/{task_id}", headers=RUNWAY_HEADERS)
|
102 |
status_details = get_response.json()
|
103 |
status = status_details.get("status")
|
|
|
14 |
genai.configure(api_key=os.environ["GEMINI_API_KEY"])
|
15 |
tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
|
16 |
RUNWAY_API_KEY = os.environ["RUNWAY_API_KEY"]
|
|
|
|
|
17 |
except KeyError as e:
|
|
|
18 |
if 'ELEVENLABS_API_KEY' not in str(e):
|
19 |
raise ValueError(f"API Key Error: Please set the {e} secret in your Hugging Face Space settings.")
|
20 |
|
|
|
60 |
except (json.JSONDecodeError, KeyError) as e:
|
61 |
raise gr.Error(f"Gemini did not return valid JSON. Error: {e}. Response was: {response.text}")
|
62 |
|
63 |
+
# STEP 3: MOCK VOICE OVER
|
64 |
progress(0.3, desc="ποΈ MOCKING voiceover to save credits...")
|
65 |
audio_path = f"audio_{job_id}.mp3"
|
66 |
intermediate_files.append(audio_path)
|
67 |
+
narration_duration = len(narration.split()) / 2.5
|
|
|
|
|
|
|
68 |
subprocess.run([
|
69 |
'ffmpeg', '-f', 'lavfi', '-i', f'anullsrc=r=44100:cl=mono',
|
70 |
'-t', str(narration_duration), '-q:a', '9', '-acodec', 'libmp3lame',
|
71 |
audio_path, '-y'
|
72 |
], check=True)
|
73 |
print(f"MOCK audio file saved (no credits used): {audio_path}")
|
|
|
74 |
|
75 |
# STEP 4: VISUALS (Runway)
|
76 |
video_clip_paths = []
|
77 |
for i, scene_prompt in enumerate(scene_prompts):
|
78 |
progress(0.4 + (i * 0.12), desc=f"π¬ Generating video scene {i+1}/{len(scene_prompts)}...")
|
79 |
|
80 |
+
# !!!!!!!!!!! THE FINAL, FINAL, VERIFIED RUNWAY FIX !!!!!!!!!!!
|
81 |
+
# 1. The payload structure is now correct for V2
|
82 |
+
runway_payload = {
|
83 |
+
"task_type": "gen2",
|
84 |
+
"options": {
|
85 |
+
"text_prompt": scene_prompt
|
86 |
+
}
|
87 |
+
}
|
88 |
+
# 2. The POST request goes to the base /tasks endpoint
|
89 |
+
post_response = requests.post(f"{RUNWAY_API_URL}/tasks", headers=RUNWAY_HEADERS, json=runway_payload)
|
90 |
+
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
91 |
|
92 |
if post_response.status_code != 200:
|
93 |
raise gr.Error(f"Runway API Error (start job): {post_response.status_code} - {post_response.text}")
|
|
|
98 |
|
99 |
video_url = None
|
100 |
for _ in range(60):
|
|
|
101 |
get_response = requests.get(f"{RUNWAY_API_URL}/tasks/{task_id}", headers=RUNWAY_HEADERS)
|
102 |
status_details = get_response.json()
|
103 |
status = status_details.get("status")
|