sourize commited on
Commit
722a506
Β·
1 Parent(s): f0e2e50

Updated Code

Browse files
app.py CHANGED
@@ -38,9 +38,7 @@ class ManimVideoGenerator:
38
  self.client = Groq(api_key=groq_api_key)
39
  self.available_models = {
40
  "llama-3.3-70b-versatile": "Llama 3.3 70B",
41
- "llama3-8b-8192": "Llama 3 8B",
42
- "llama-3.1-8b-instant": "Llama 3.1 8B Instant",
43
- "gemma2-9b-it": "Gemma 2 9B"
44
  }
45
  self.temp_dir = None
46
  self.metrics = MetricsCollector()
@@ -550,6 +548,14 @@ def process_video_generation(generator, user_prompt, selected_model, video_quali
550
  if logs and st.checkbox("Show error details"):
551
  st.text_area("Error Details", logs, height=200)
552
 
 
 
 
 
 
 
 
 
553
  except Exception as e:
554
  error_info = ErrorHandler.get_user_friendly_error(type(e).__name__, str(e))
555
  st.markdown(f'<div class="error-box">❌ {error_info["user_message"]}</div>',
@@ -562,6 +568,14 @@ def process_video_generation(generator, user_prompt, selected_model, video_quali
562
  st.markdown(f"β€’ {suggestion}")
563
 
564
  logger.error(f"Application error: {e}")
 
 
 
 
 
 
 
 
565
 
566
  def main():
567
  initialize_app()
@@ -597,18 +611,9 @@ def main():
597
  generator = ManimVideoGenerator(groq_api_key)
598
 
599
  # Render main interface
600
- interface_result = render_main_interface()
601
-
602
- # Handle example selection or user input
603
- if isinstance(interface_result[0], str) and not interface_result[1]:
604
- # Example was selected
605
- user_prompt = interface_result[0]
606
- generate_button = True
607
- else:
608
- # Regular user input
609
- user_prompt, generate_button = interface_result
610
 
611
- # Process generation if requested
612
  if generate_button and user_prompt and user_prompt.strip():
613
  process_video_generation(generator, user_prompt, selected_model, video_quality)
614
  generator.cleanup()
 
38
  self.client = Groq(api_key=groq_api_key)
39
  self.available_models = {
40
  "llama-3.3-70b-versatile": "Llama 3.3 70B",
41
+ "llama3-8b-8192": "Llama 3 8B"
 
 
42
  }
43
  self.temp_dir = None
44
  self.metrics = MetricsCollector()
 
548
  if logs and st.checkbox("Show error details"):
549
  st.text_area("Error Details", logs, height=200)
550
 
551
+ # Cleanup after everything is done
552
+ if temp_dir and os.path.exists(temp_dir):
553
+ try:
554
+ shutil.rmtree(temp_dir)
555
+ logger.info(f"Cleaned up temporary directory: {temp_dir}")
556
+ except Exception as e:
557
+ logger.error(f"Error cleaning up temporary directory: {e}")
558
+
559
  except Exception as e:
560
  error_info = ErrorHandler.get_user_friendly_error(type(e).__name__, str(e))
561
  st.markdown(f'<div class="error-box">❌ {error_info["user_message"]}</div>',
 
568
  st.markdown(f"β€’ {suggestion}")
569
 
570
  logger.error(f"Application error: {e}")
571
+
572
+ # Cleanup in case of error
573
+ if 'temp_dir' in locals() and temp_dir and os.path.exists(temp_dir):
574
+ try:
575
+ shutil.rmtree(temp_dir)
576
+ logger.info(f"Cleaned up temporary directory after error: {temp_dir}")
577
+ except Exception as cleanup_error:
578
+ logger.error(f"Error cleaning up temporary directory after error: {cleanup_error}")
579
 
580
  def main():
581
  initialize_app()
 
611
  generator = ManimVideoGenerator(groq_api_key)
612
 
613
  # Render main interface
614
+ user_prompt, generate_button = render_main_interface()
 
 
 
 
 
 
 
 
 
615
 
616
+ # Process generation only if button is clicked and there's a prompt
617
  if generate_button and user_prompt and user_prompt.strip():
618
  process_video_generation(generator, user_prompt, selected_model, video_quality)
619
  generator.cleanup()
config/constants.py CHANGED
@@ -1,24 +1,23 @@
1
- """Application constants and enums."""
2
-
3
  from enum import Enum, auto
4
  from typing import Dict, List, Tuple
5
 
 
 
 
 
 
 
 
 
6
  class VideoQuality(Enum):
7
- """Video quality levels."""
8
  LOW = "low_quality"
9
  MEDIUM = "medium_quality"
10
- HIGH = "high_quality"
11
- PRODUCTION = "production_quality"
12
 
13
  class ModelType(Enum):
14
- """Available AI models."""
15
  LLAMA_70B = "llama-3.3-70b-versatile"
16
  LLAMA_8B = "llama3-8b-8192"
17
- MIXTRAL = "mixtral-8x7b-32768"
18
- GEMMA = "gemma2-9b-it"
19
 
20
  class AnimationCategory(Enum):
21
- """Categories of mathematical animations."""
22
  ALGEBRA = "algebra"
23
  GEOMETRY = "geometry"
24
  CALCULUS = "calculus"
@@ -28,7 +27,6 @@ class AnimationCategory(Enum):
28
  OTHER = "other"
29
 
30
  class ErrorType(Enum):
31
- """Types of errors that can occur."""
32
  RENDERING_ERROR = auto()
33
  CODE_GENERATION_ERROR = auto()
34
  PROMPT_ERROR = auto()
@@ -64,26 +62,6 @@ FILE_CONSTANTS = {
64
  "LOG_FILE_NAME": "manimate.log"
65
  }
66
 
67
- # Example Prompts by Category
68
- EXAMPLE_PROMPTS: Dict[AnimationCategory, List[str]] = {
69
- AnimationCategory.ALGEBRA: [
70
- "Visualize solving xΒ² + 3x - 4 = 0 using the quadratic formula",
71
- "Show function transformations with f(x) = xΒ² shifting and scaling"
72
- ],
73
- AnimationCategory.GEOMETRY: [
74
- "Demonstrate the Pythagorean theorem with squares on triangle sides",
75
- "Animate the construction of a regular pentagon using compass and straightedge"
76
- ],
77
- AnimationCategory.CALCULUS: [
78
- "Show the concept of limits with a function approaching a value",
79
- "Visualize area under curve using Riemann sums with rectangles"
80
- ],
81
- AnimationCategory.STATISTICS: [
82
- "Animate the Central Limit Theorem with multiple distributions",
83
- "Show correlation vs causation with scatter plot examples"
84
- ]
85
- }
86
-
87
  # CSS Classes
88
  CSS_CLASSES = {
89
  "MAIN_HEADER": "main-header",
@@ -91,7 +69,19 @@ CSS_CLASSES = {
91
  "SUCCESS_BOX": "success-box",
92
  "ERROR_BOX": "error-box",
93
  "INFO_BOX": "info-box",
94
- "METRIC_BOX": "metric-box"
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
96
 
97
  # CSS Styles
@@ -125,14 +115,18 @@ STATUS_MESSAGES = {
125
  "ERROR": "❌ Error occurred during generation"
126
  }
127
 
128
- def get_example_prompts(category: AnimationCategory) -> List[str]:
129
- """Get example prompts for a specific category."""
130
- return EXAMPLE_PROMPTS.get(category, [])
 
 
 
 
 
 
131
 
132
  def get_css_class(class_name: str) -> str:
133
- """Get CSS class name by key."""
134
  return CSS_CLASSES.get(class_name, "")
135
 
136
  def get_status_message(key: str) -> str:
137
- """Get status message by key."""
138
  return STATUS_MESSAGES.get(key, "")
 
 
 
1
  from enum import Enum, auto
2
  from typing import Dict, List, Tuple
3
 
4
+ # Quality levels
5
+ LOW = "low_quality"
6
+ MEDIUM = "medium_quality"
7
+
8
+ # Model identifiers
9
+ LLAMA_70B = "llama-3.3-70b-versatile"
10
+ LLAMA_8B = "llama3-8b-8192"
11
+
12
  class VideoQuality(Enum):
 
13
  LOW = "low_quality"
14
  MEDIUM = "medium_quality"
 
 
15
 
16
  class ModelType(Enum):
 
17
  LLAMA_70B = "llama-3.3-70b-versatile"
18
  LLAMA_8B = "llama3-8b-8192"
 
 
19
 
20
  class AnimationCategory(Enum):
 
21
  ALGEBRA = "algebra"
22
  GEOMETRY = "geometry"
23
  CALCULUS = "calculus"
 
27
  OTHER = "other"
28
 
29
  class ErrorType(Enum):
 
30
  RENDERING_ERROR = auto()
31
  CODE_GENERATION_ERROR = auto()
32
  PROMPT_ERROR = auto()
 
62
  "LOG_FILE_NAME": "manimate.log"
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  # CSS Classes
66
  CSS_CLASSES = {
67
  "MAIN_HEADER": "main-header",
 
69
  "SUCCESS_BOX": "success-box",
70
  "ERROR_BOX": "error-box",
71
  "INFO_BOX": "info-box",
72
+ "METRIC_BOX": "metric-box",
73
+ "header": """
74
+ text-align: center;
75
+ padding: 1rem 0;
76
+ background: linear-gradient(90deg, #667eea 7%, #764ba2 100%);
77
+ color: white;
78
+ border-radius: 10px;
79
+ """,
80
+ "container": """
81
+ max-width: 1200px;
82
+ margin: 0 auto;
83
+ padding: 2rem;
84
+ """
85
  }
86
 
87
  # CSS Styles
 
115
  "ERROR": "❌ Error occurred during generation"
116
  }
117
 
118
+ # Application constants
119
+ APP_CONSTANTS = {
120
+ "MAX_RENDER_TIME": 300, # seconds
121
+ "MAX_PROMPT_LENGTH": 1000,
122
+ "MIN_PROMPT_LENGTH": 10,
123
+ "DEFAULT_VIDEO_QUALITY": VideoQuality.MEDIUM.value,
124
+ "TEMP_FILE_PREFIX": "manim_",
125
+ "LOG_FILE_NAME": "manimate.log"
126
+ }
127
 
128
  def get_css_class(class_name: str) -> str:
 
129
  return CSS_CLASSES.get(class_name, "")
130
 
131
  def get_status_message(key: str) -> str:
 
132
  return STATUS_MESSAGES.get(key, "")
config/settings.py CHANGED
@@ -1,5 +1,3 @@
1
- """Application settings and configuration."""
2
-
3
  from pathlib import Path
4
  from typing import Dict, Any
5
 
@@ -29,18 +27,6 @@ AVAILABLE_MODELS = {
29
  "description": "Fast and efficient for simpler animations",
30
  "max_tokens": 8192,
31
  "temperature": 0.7
32
- },
33
- "mixtral-8x7b-32768": {
34
- "name": "Mixtral 8x7B",
35
- "description": "Creative model with large context window",
36
- "max_tokens": 32768,
37
- "temperature": 0.8
38
- },
39
- "gemma2-9b-it": {
40
- "name": "Gemma 2 9B",
41
- "description": "Efficient model for basic animations",
42
- "max_tokens": 8192,
43
- "temperature": 0.7
44
  }
45
  }
46
 
@@ -57,18 +43,6 @@ QUALITY_SETTINGS = {
57
  "description": "Medium Quality (Balanced)",
58
  "estimated_time": 180, # seconds
59
  "resolution": "720p"
60
- },
61
- "high_quality": {
62
- "flag": "-qh",
63
- "description": "High Quality (Detailed)",
64
- "estimated_time": 300, # seconds
65
- "resolution": "1080p"
66
- },
67
- "production_quality": {
68
- "flag": "-qk",
69
- "description": "Production Quality (Best)",
70
- "estimated_time": 600, # seconds
71
- "resolution": "4K"
72
  }
73
  }
74
 
@@ -98,7 +72,6 @@ UI_SETTINGS = {
98
  }
99
 
100
  def get_setting(key: str, default: Any = None) -> Any:
101
- """Get a setting value by key with optional default."""
102
  if key in APP_SETTINGS:
103
  return APP_SETTINGS[key]
104
  if key in UI_SETTINGS:
@@ -106,7 +79,6 @@ def get_setting(key: str, default: Any = None) -> Any:
106
  return default
107
 
108
  def update_setting(key: str, value: Any) -> None:
109
- """Update a setting value."""
110
  if key in APP_SETTINGS:
111
  APP_SETTINGS[key] = value
112
  elif key in UI_SETTINGS:
 
 
 
1
  from pathlib import Path
2
  from typing import Dict, Any
3
 
 
27
  "description": "Fast and efficient for simpler animations",
28
  "max_tokens": 8192,
29
  "temperature": 0.7
 
 
 
 
 
 
 
 
 
 
 
 
30
  }
31
  }
32
 
 
43
  "description": "Medium Quality (Balanced)",
44
  "estimated_time": 180, # seconds
45
  "resolution": "720p"
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
  }
48
 
 
72
  }
73
 
74
  def get_setting(key: str, default: Any = None) -> Any:
 
75
  if key in APP_SETTINGS:
76
  return APP_SETTINGS[key]
77
  if key in UI_SETTINGS:
 
79
  return default
80
 
81
  def update_setting(key: str, value: Any) -> None:
 
82
  if key in APP_SETTINGS:
83
  APP_SETTINGS[key] = value
84
  elif key in UI_SETTINGS:
config/space_config.py CHANGED
@@ -1,5 +1,3 @@
1
- """Configuration settings for Hugging Face Spaces deployment."""
2
-
3
  import os
4
 
5
  # Space-specific settings
@@ -8,9 +6,7 @@ SPACE_CONFIG = {
8
  "max_video_size_mb": 50, # Maximum video size in MB
9
  "allowed_models": [
10
  "llama-3.3-70b-versatile",
11
- "llama3-8b-8192",
12
- "mixtral-8x7b-32768",
13
- "gemma2-9b-it"
14
  ],
15
  "default_quality": "medium_quality",
16
  "cache_ttl": 3600, # Cache time-to-live in seconds
@@ -58,6 +54,22 @@ UI_CONFIG = {
58
  "enable_error_reporting": True
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  def get_space_config():
62
  """Get the current space configuration."""
63
  return {
 
 
 
1
  import os
2
 
3
  # Space-specific settings
 
6
  "max_video_size_mb": 50, # Maximum video size in MB
7
  "allowed_models": [
8
  "llama-3.3-70b-versatile",
9
+ "llama3-8b-8192"
 
 
10
  ],
11
  "default_quality": "medium_quality",
12
  "cache_ttl": 3600, # Cache time-to-live in seconds
 
54
  "enable_error_reporting": True
55
  }
56
 
57
+ AVAILABLE_MODELS = [
58
+ "llama-3.3-70b-versatile",
59
+ "llama3-8b-8192"
60
+ ]
61
+
62
+ QUALITY_SETTINGS = {
63
+ "low_quality": {
64
+ "resolution": "480p",
65
+ "fps": 30
66
+ },
67
+ "medium_quality": {
68
+ "resolution": "720p",
69
+ "fps": 30
70
+ }
71
+ }
72
+
73
  def get_space_config():
74
  """Get the current space configuration."""
75
  return {
core/generator.py CHANGED
@@ -1,5 +1,3 @@
1
- """Core video generation functionality."""
2
-
3
  import os
4
  import logging
5
  import tempfile
@@ -31,10 +29,8 @@ from utils.metrics_collector import MetricsCollector
31
  logger = logging.getLogger(__name__)
32
 
33
  class ManimVideoGenerator:
34
- """Main class for generating Manim videos from prompts."""
35
 
36
  def __init__(self, groq_api_key: str):
37
- """Initialize the Manim Video Generator with Groq API key."""
38
  self.client = Groq(api_key=groq_api_key)
39
  self.available_models = AVAILABLE_MODELS
40
  self.temp_dir = None
@@ -43,7 +39,6 @@ class ManimVideoGenerator:
43
  self.code_validator = CodeValidator()
44
 
45
  def enhance_prompt(self, user_prompt: str, model: str = DEFAULT_MODEL) -> str:
46
- """Enhance the user prompt for better Manim code generation."""
47
  try:
48
  model_config = self.available_models[model]
49
  return self.prompt_manager.enhance_prompt(
@@ -59,7 +54,6 @@ class ManimVideoGenerator:
59
  return user_prompt
60
 
61
  def generate_manim_code(self, enhanced_prompt: str, model: str = DEFAULT_MODEL) -> str:
62
- """Generate Manim code from the enhanced prompt."""
63
  try:
64
  model_config = self.available_models[model]
65
  return self.prompt_manager.generate_code(
@@ -75,12 +69,9 @@ class ManimVideoGenerator:
75
  raise
76
 
77
  def process_and_validate_code(self, raw_code: str) -> str:
78
- """Process and validate the generated code."""
79
  try:
80
- # Clean and validate code
81
  cleaned_code = self.code_validator.fix_common_issues(raw_code)
82
 
83
- # Validate syntax and structure
84
  validation_result = self.code_validator.validate_code(cleaned_code)
85
  if not validation_result["is_valid"]:
86
  raise ValueError(validation_result["error_message"])
@@ -92,7 +83,6 @@ class ManimVideoGenerator:
92
  raise
93
 
94
  def create_temp_directory(self) -> str:
95
- """Create a temporary directory for Manim operations."""
96
  if self.temp_dir and os.path.exists(self.temp_dir):
97
  shutil.rmtree(self.temp_dir)
98
 
@@ -103,7 +93,6 @@ class ManimVideoGenerator:
103
  return self.temp_dir
104
 
105
  def save_code_to_file(self, code: str, temp_dir: str) -> str:
106
- """Save the Manim code to a Python file."""
107
  code_file = os.path.join(temp_dir, FILE_CONSTANTS["SCENE_FILE_NAME"])
108
  try:
109
  with open(code_file, 'w', encoding='utf-8') as f:
@@ -120,7 +109,6 @@ class ManimVideoGenerator:
120
  temp_dir: str,
121
  quality: str = VideoQuality.MEDIUM.value
122
  ) -> Tuple[bool, str, str]:
123
- """Render the Manim video."""
124
  from utils.renderer import VideoRenderer
125
 
126
  try:
@@ -139,7 +127,6 @@ class ManimVideoGenerator:
139
  return False, str(e), ""
140
 
141
  def cleanup(self) -> None:
142
- """Clean up temporary files."""
143
  if self.temp_dir and os.path.exists(self.temp_dir):
144
  try:
145
  shutil.rmtree(self.temp_dir)
@@ -149,12 +136,10 @@ class ManimVideoGenerator:
149
  ErrorHandler.handle_error(ErrorType.SYSTEM_ERROR, str(e))
150
 
151
  def get_metrics_summary(self) -> Dict[str, Any]:
152
- """Get a summary of generation metrics."""
153
  return self.metrics.get_summary()
154
 
155
  @property
156
  def model_options(self) -> Dict[str, str]:
157
- """Get formatted model options for UI display."""
158
  return {
159
  model_id: f"{config['name']} ({config['description']})"
160
  for model_id, config in self.available_models.items()
@@ -162,7 +147,6 @@ class ManimVideoGenerator:
162
 
163
  @property
164
  def quality_options(self) -> Dict[str, str]:
165
- """Get formatted quality options for UI display."""
166
  return {
167
  quality_id: config["description"]
168
  for quality_id, config in QUALITY_SETTINGS.items()
 
 
 
1
  import os
2
  import logging
3
  import tempfile
 
29
  logger = logging.getLogger(__name__)
30
 
31
  class ManimVideoGenerator:
 
32
 
33
  def __init__(self, groq_api_key: str):
 
34
  self.client = Groq(api_key=groq_api_key)
35
  self.available_models = AVAILABLE_MODELS
36
  self.temp_dir = None
 
39
  self.code_validator = CodeValidator()
40
 
41
  def enhance_prompt(self, user_prompt: str, model: str = DEFAULT_MODEL) -> str:
 
42
  try:
43
  model_config = self.available_models[model]
44
  return self.prompt_manager.enhance_prompt(
 
54
  return user_prompt
55
 
56
  def generate_manim_code(self, enhanced_prompt: str, model: str = DEFAULT_MODEL) -> str:
 
57
  try:
58
  model_config = self.available_models[model]
59
  return self.prompt_manager.generate_code(
 
69
  raise
70
 
71
  def process_and_validate_code(self, raw_code: str) -> str:
 
72
  try:
 
73
  cleaned_code = self.code_validator.fix_common_issues(raw_code)
74
 
 
75
  validation_result = self.code_validator.validate_code(cleaned_code)
76
  if not validation_result["is_valid"]:
77
  raise ValueError(validation_result["error_message"])
 
83
  raise
84
 
85
  def create_temp_directory(self) -> str:
 
86
  if self.temp_dir and os.path.exists(self.temp_dir):
87
  shutil.rmtree(self.temp_dir)
88
 
 
93
  return self.temp_dir
94
 
95
  def save_code_to_file(self, code: str, temp_dir: str) -> str:
 
96
  code_file = os.path.join(temp_dir, FILE_CONSTANTS["SCENE_FILE_NAME"])
97
  try:
98
  with open(code_file, 'w', encoding='utf-8') as f:
 
109
  temp_dir: str,
110
  quality: str = VideoQuality.MEDIUM.value
111
  ) -> Tuple[bool, str, str]:
 
112
  from utils.renderer import VideoRenderer
113
 
114
  try:
 
127
  return False, str(e), ""
128
 
129
  def cleanup(self) -> None:
 
130
  if self.temp_dir and os.path.exists(self.temp_dir):
131
  try:
132
  shutil.rmtree(self.temp_dir)
 
136
  ErrorHandler.handle_error(ErrorType.SYSTEM_ERROR, str(e))
137
 
138
  def get_metrics_summary(self) -> Dict[str, Any]:
 
139
  return self.metrics.get_summary()
140
 
141
  @property
142
  def model_options(self) -> Dict[str, str]:
 
143
  return {
144
  model_id: f"{config['name']} ({config['description']})"
145
  for model_id, config in self.available_models.items()
 
147
 
148
  @property
149
  def quality_options(self) -> Dict[str, str]:
 
150
  return {
151
  quality_id: config["description"]
152
  for quality_id, config in QUALITY_SETTINGS.items()
utils/metrics_collector.py CHANGED
@@ -20,7 +20,10 @@ class MetricsCollector:
20
  self.failed_renders = 0
21
  self.render_times: List[float] = []
22
  self.error_counts = defaultdict(int)
23
- self.quality_usage = defaultdict(int)
 
 
 
24
  self.scene_types = defaultdict(int)
25
  self.start_time = time.time()
26
 
 
20
  self.failed_renders = 0
21
  self.render_times: List[float] = []
22
  self.error_counts = defaultdict(int)
23
+ self.quality_usage = {
24
+ VideoQuality.LOW.value: 0,
25
+ VideoQuality.MEDIUM.value: 0
26
+ }
27
  self.scene_types = defaultdict(int)
28
  self.start_time = time.time()
29
 
utils/performance_optimizer.py CHANGED
@@ -10,31 +10,29 @@ class PerformanceOptimizer:
10
 
11
  QUALITY_SETTINGS = {
12
  "low_quality": {
13
- "flag": "-ql",
14
- "resolution": "854x480",
15
- "frame_rate": 15,
16
- "description": "480p, 15fps - Fast rendering"
17
  },
18
  "medium_quality": {
19
- "flag": "-qm",
20
- "resolution": "1280x720",
21
- "frame_rate": 30,
22
- "description": "720p, 30fps - Balanced"
23
- },
24
- "high_quality": {
25
- "flag": "-qh",
26
- "resolution": "1920x1080",
27
- "frame_rate": 60,
28
- "description": "1080p, 60fps - High quality"
29
- },
30
- "production_quality": {
31
- "flag": "-qp",
32
- "resolution": "3840x2160",
33
- "frame_rate": 60,
34
- "description": "4K, 60fps - Production ready"
35
  }
36
  }
37
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  @classmethod
39
  def estimate_render_time(cls, quality: str, complexity: str = "medium") -> int:
40
  """Estimate rendering time in seconds"""
@@ -162,4 +160,11 @@ class PerformanceOptimizer:
162
  tips.append("Close other applications to free up system resources")
163
  tips.append("Ensure sufficient disk space for temporary files")
164
 
165
- return tips
 
 
 
 
 
 
 
 
10
 
11
  QUALITY_SETTINGS = {
12
  "low_quality": {
13
+ "resolution": "480p",
14
+ "fps": 30,
15
+ "description": "480p, 30fps - Fast rendering"
 
16
  },
17
  "medium_quality": {
18
+ "resolution": "720p",
19
+ "fps": 30,
20
+ "description": "720p, 30fps - Balanced quality"
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  }
22
  }
23
 
24
+ # Performance thresholds
25
+ RENDER_TIME_THRESHOLDS = {
26
+ "low_quality": 60,
27
+ "medium_quality": 180
28
+ }
29
+
30
+ # Memory usage thresholds (in GB)
31
+ MEMORY_THRESHOLDS = {
32
+ "low_quality": 4.0,
33
+ "medium_quality": 6.0
34
+ }
35
+
36
  @classmethod
37
  def estimate_render_time(cls, quality: str, complexity: str = "medium") -> int:
38
  """Estimate rendering time in seconds"""
 
160
  tips.append("Close other applications to free up system resources")
161
  tips.append("Ensure sufficient disk space for temporary files")
162
 
163
+ return tips
164
+
165
+ def optimize_quality(self, available_memory: float, estimated_render_time: float) -> str:
166
+ if available_memory < self.MEMORY_THRESHOLDS["low_quality"]:
167
+ return "low_quality"
168
+ if estimated_render_time > self.RENDER_TIME_THRESHOLDS["medium_quality"]:
169
+ return "low_quality"
170
+ return "medium_quality"
utils/ui_components.py CHANGED
@@ -18,7 +18,7 @@ def initialize_app():
18
  .main-header {
19
  text-align: center;
20
  padding: 1rem 0;
21
- background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
22
  color: white;
23
  border-radius: 10px;
24
  margin-bottom: 2rem;
@@ -60,7 +60,7 @@ def initialize_app():
60
  def render_header():
61
  st.markdown("""
62
  <div class="main-header">
63
- <h1>🎬 Manim Video Generator</h1>
64
  <p>Transform your ideas into mathematical animations</p>
65
  </div>
66
  """, unsafe_allow_html=True)
@@ -75,10 +75,8 @@ def render_sidebar():
75
  st.write(f"{status} {key.replace('_', ' ').title()}: {value}")
76
 
77
  model_options = {
78
- "llama-3.3-70b-versatile": "Llama 3.3 70B (Recommended)",
79
- "llama3-8b-8192": "Llama 3 8B (Fast)",
80
- "mixtral-8x7b-32768": "Mixtral 8x7B (Creative)",
81
- "gemma2-9b-it": "Gemma 2 9B (Efficient)"
82
  }
83
  selected_model = st.selectbox(
84
  "AI Model",
@@ -143,9 +141,11 @@ def render_main_interface():
143
  user_prompt = st.text_area(
144
  "Describe the mathematical animation you want to create:",
145
  height=150,
146
- placeholder="Example: Create an animation showing the derivative of xΒ² as the slope of tangent lines, with smooth transitions and clear labeling",
147
  help="Be as descriptive as possible for best results. Mention specific mathematical concepts, colors, and visual elements."
148
  )
 
 
149
  if user_prompt:
150
  category = PromptTemplates.detect_category(user_prompt)
151
  complexity = "complex" if len(user_prompt) > 100 else "medium"
@@ -154,10 +154,11 @@ def render_main_interface():
154
  st.info(f"πŸ“‚ Detected category: **{category.title()}**")
155
  with col_info2:
156
  st.info(f"🎯 Complexity: **{complexity.title()}**")
 
 
157
  generate_button = st.button("πŸš€ Generate Animation", type="primary", disabled=not user_prompt.strip())
158
 
159
- # example_prompt = render_examples()
160
- return user_prompt, generate_button, None
161
 
162
  def render_footer(generator=None):
163
  st.markdown("---")
 
18
  .main-header {
19
  text-align: center;
20
  padding: 1rem 0;
21
+ background: linear-gradient(70deg, #667eea 47%, #764ba2 100%);
22
  color: white;
23
  border-radius: 10px;
24
  margin-bottom: 2rem;
 
60
  def render_header():
61
  st.markdown("""
62
  <div class="main-header">
63
+ <h1>🎬 Manimate: Video Generator</h1>
64
  <p>Transform your ideas into mathematical animations</p>
65
  </div>
66
  """, unsafe_allow_html=True)
 
75
  st.write(f"{status} {key.replace('_', ' ').title()}: {value}")
76
 
77
  model_options = {
78
+ "llama-3.3-70b-versatile": "Llama 3.3 70B (Most Capable)",
79
+ "llama3-8b-8192": "Llama 3 8B (Fast)"
 
 
80
  }
81
  selected_model = st.selectbox(
82
  "AI Model",
 
141
  user_prompt = st.text_area(
142
  "Describe the mathematical animation you want to create:",
143
  height=150,
144
+ placeholder="Example: Create an animation showing the derivation of Pythagorean theorem, with smooth transitions and clear labeling",
145
  help="Be as descriptive as possible for best results. Mention specific mathematical concepts, colors, and visual elements."
146
  )
147
+
148
+ # Show category and complexity info if there's input
149
  if user_prompt:
150
  category = PromptTemplates.detect_category(user_prompt)
151
  complexity = "complex" if len(user_prompt) > 100 else "medium"
 
154
  st.info(f"πŸ“‚ Detected category: **{category.title()}**")
155
  with col_info2:
156
  st.info(f"🎯 Complexity: **{complexity.title()}**")
157
+
158
+ # Add a separate Generate button
159
  generate_button = st.button("πŸš€ Generate Animation", type="primary", disabled=not user_prompt.strip())
160
 
161
+ return user_prompt, generate_button
 
162
 
163
  def render_footer(generator=None):
164
  st.markdown("---")