Spaces:
Running
Running
Commit
·
5aec441
1
Parent(s):
fff13d1
fixed error
Browse files- orchestrator.py +44 -1
orchestrator.py
CHANGED
|
@@ -167,11 +167,21 @@ class NeuroAnimOrchestrator:
|
|
| 167 |
target_audience: str = "general",
|
| 168 |
animation_length_minutes: float = 2.0,
|
| 169 |
output_filename: str = "animation.mp4",
|
|
|
|
|
|
|
| 170 |
) -> Dict[str, Any]:
|
| 171 |
"""Complete animation generation pipeline."""
|
| 172 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
try:
|
| 174 |
logger.info(f"Starting animation generation for: {topic}")
|
|
|
|
| 175 |
|
| 176 |
# Step 1: Concept Planning
|
| 177 |
logger.info("Step 1: Planning concept...")
|
|
@@ -190,6 +200,7 @@ class NeuroAnimOrchestrator:
|
|
| 190 |
|
| 191 |
concept_plan = concept_result["text"]
|
| 192 |
logger.info("Concept planning completed")
|
|
|
|
| 193 |
|
| 194 |
# Step 2: Generate Narration
|
| 195 |
logger.info("Step 2: Generating narration...")
|
|
@@ -211,6 +222,7 @@ class NeuroAnimOrchestrator:
|
|
| 211 |
|
| 212 |
narration_text = narration_result["text"]
|
| 213 |
logger.info("Narration generation completed")
|
|
|
|
| 214 |
|
| 215 |
# Step 3: Generate Manim Code with retry logic
|
| 216 |
logger.info("Step 3: Generating Manim code...")
|
|
@@ -234,6 +246,7 @@ class NeuroAnimOrchestrator:
|
|
| 234 |
# Extract scene name from code
|
| 235 |
scene_name = self._extract_scene_name(manim_code)
|
| 236 |
logger.info(f"Scene name detected: {scene_name}")
|
|
|
|
| 237 |
|
| 238 |
# Step 5: Render Animation
|
| 239 |
logger.info("Step 5: Rendering animation...")
|
|
@@ -244,7 +257,7 @@ class NeuroAnimOrchestrator:
|
|
| 244 |
"scene_name": scene_name,
|
| 245 |
"file_path": str(manim_file),
|
| 246 |
"output_dir": str(self.work_dir),
|
| 247 |
-
"quality":
|
| 248 |
"format": "mp4",
|
| 249 |
"frame_rate": 30,
|
| 250 |
},
|
|
@@ -259,6 +272,7 @@ class NeuroAnimOrchestrator:
|
|
| 259 |
raise Exception("Could not find rendered video file")
|
| 260 |
|
| 261 |
logger.info(f"Animation rendered: {video_file}")
|
|
|
|
| 262 |
|
| 263 |
# Step 6: Generate Speech Audio
|
| 264 |
logger.info("Step 6: Generating speech audio...")
|
|
@@ -289,6 +303,8 @@ class NeuroAnimOrchestrator:
|
|
| 289 |
logger.error(f"TTS generation failed: {e}")
|
| 290 |
raise Exception(f"Speech generation failed: {str(e)}")
|
| 291 |
|
|
|
|
|
|
|
| 292 |
# Step 7: Merge Video and Audio
|
| 293 |
logger.info("Step 7: Merging video and audio...")
|
| 294 |
final_output = self.output_dir / output_filename
|
|
@@ -305,6 +321,33 @@ class NeuroAnimOrchestrator:
|
|
| 305 |
if merge_result["isError"]:
|
| 306 |
raise Exception(f"Merging failed: {merge_result['text']}")
|
| 307 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
# Step 8: Generate Quiz
|
| 309 |
logger.info("Step 8: Generating quiz...")
|
| 310 |
quiz_result = await self.call_tool(
|
|
|
|
| 167 |
target_audience: str = "general",
|
| 168 |
animation_length_minutes: float = 2.0,
|
| 169 |
output_filename: str = "animation.mp4",
|
| 170 |
+
quality: str = "medium",
|
| 171 |
+
progress_callback: Optional[Callable[[str, float], None]] = None,
|
| 172 |
) -> Dict[str, Any]:
|
| 173 |
"""Complete animation generation pipeline."""
|
| 174 |
|
| 175 |
+
def report_progress(step: str, progress: float):
|
| 176 |
+
if progress_callback:
|
| 177 |
+
try:
|
| 178 |
+
progress_callback(step, progress)
|
| 179 |
+
except Exception as e:
|
| 180 |
+
logger.warning(f"Progress callback failed: {e}")
|
| 181 |
+
|
| 182 |
try:
|
| 183 |
logger.info(f"Starting animation generation for: {topic}")
|
| 184 |
+
report_progress("Planning concept", 0.1)
|
| 185 |
|
| 186 |
# Step 1: Concept Planning
|
| 187 |
logger.info("Step 1: Planning concept...")
|
|
|
|
| 200 |
|
| 201 |
concept_plan = concept_result["text"]
|
| 202 |
logger.info("Concept planning completed")
|
| 203 |
+
report_progress("Generating narration script", 0.25)
|
| 204 |
|
| 205 |
# Step 2: Generate Narration
|
| 206 |
logger.info("Step 2: Generating narration...")
|
|
|
|
| 222 |
|
| 223 |
narration_text = narration_result["text"]
|
| 224 |
logger.info("Narration generation completed")
|
| 225 |
+
report_progress("Creating Manim animation code", 0.40)
|
| 226 |
|
| 227 |
# Step 3: Generate Manim Code with retry logic
|
| 228 |
logger.info("Step 3: Generating Manim code...")
|
|
|
|
| 246 |
# Extract scene name from code
|
| 247 |
scene_name = self._extract_scene_name(manim_code)
|
| 248 |
logger.info(f"Scene name detected: {scene_name}")
|
| 249 |
+
report_progress("Rendering animation video", 0.55)
|
| 250 |
|
| 251 |
# Step 5: Render Animation
|
| 252 |
logger.info("Step 5: Rendering animation...")
|
|
|
|
| 257 |
"scene_name": scene_name,
|
| 258 |
"file_path": str(manim_file),
|
| 259 |
"output_dir": str(self.work_dir),
|
| 260 |
+
"quality": quality,
|
| 261 |
"format": "mp4",
|
| 262 |
"frame_rate": 30,
|
| 263 |
},
|
|
|
|
| 272 |
raise Exception("Could not find rendered video file")
|
| 273 |
|
| 274 |
logger.info(f"Animation rendered: {video_file}")
|
| 275 |
+
report_progress("Generating audio narration", 0.75)
|
| 276 |
|
| 277 |
# Step 6: Generate Speech Audio
|
| 278 |
logger.info("Step 6: Generating speech audio...")
|
|
|
|
| 303 |
logger.error(f"TTS generation failed: {e}")
|
| 304 |
raise Exception(f"Speech generation failed: {str(e)}")
|
| 305 |
|
| 306 |
+
report_progress("Merging video and audio", 0.90)
|
| 307 |
+
|
| 308 |
# Step 7: Merge Video and Audio
|
| 309 |
logger.info("Step 7: Merging video and audio...")
|
| 310 |
final_output = self.output_dir / output_filename
|
|
|
|
| 321 |
if merge_result["isError"]:
|
| 322 |
raise Exception(f"Merging failed: {merge_result['text']}")
|
| 323 |
|
| 324 |
+
logger.info(f"Final video created: {final_output}")
|
| 325 |
+
report_progress("Creating quiz questions", 0.95)
|
| 326 |
+
|
| 327 |
+
# Step 8: Generate Quiz
|
| 328 |
+
logger.info("Step 8: Generating quiz...")
|
| 329 |
+
quiz_result = await self.call_tool(
|
| 330 |
+
self.creative_session,
|
| 331 |
+
"generate_quiz",
|
| 332 |
+
{"topic": topic, "target_audience": target_audience},
|
| 333 |
+
)
|
| 334 |
+
quiz_content = (
|
| 335 |
+
quiz_result["text"] if not quiz_result["isError"] else "Not available"
|
| 336 |
+
)
|
| 337 |
+
|
| 338 |
+
report_progress("Finalizing", 1.0)
|
| 339 |
+
|
| 340 |
+
return {
|
| 341 |
+
"success": True,
|
| 342 |
+
"output_file": str(final_output),
|
| 343 |
+
"topic": topic,
|
| 344 |
+
"target_audience": target_audience,
|
| 345 |
+
"concept_plan": concept_plan,
|
| 346 |
+
"narration": narration_text,
|
| 347 |
+
"manim_code": manim_code,
|
| 348 |
+
"quiz": quiz_content,
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
# Step 8: Generate Quiz
|
| 352 |
logger.info("Step 8: Generating quiz...")
|
| 353 |
quiz_result = await self.call_tool(
|