File size: 4,212 Bytes
a5e880f
 
 
3b0ee09
 
 
a5e880f
 
 
 
 
3b0ee09
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ee6d55e
3b0ee09
 
 
 
 
 
 
ee6d55e
 
 
 
 
 
 
 
 
3b0ee09
 
 
 
a5e880f
3b0ee09
 
 
a5e880f
 
 
 
 
 
3b0ee09
a5e880f
 
3b0ee09
 
a5e880f
3b0ee09
a5e880f
 
 
3b0ee09
a5e880f
3b0ee09
 
 
 
 
 
a5e880f
 
 
3b0ee09
a5e880f
 
3b0ee09
a5e880f
 
3b0ee09
 
 
 
 
a5e880f
3b0ee09
 
 
 
 
 
 
 
 
a5e880f
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import os
import subprocess
import uuid
import shutil
import glob
from pathlib import Path

# Get the directory of the current script (backend/)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
MEDIA_DIR = os.path.join(BASE_DIR, "media")

def cleanup_old_files():
    """Clean up old scene files and media to free memory"""
    try:
        # Remove old scene files (keep only last 2)
        scene_files = sorted(glob.glob(os.path.join(BASE_DIR, "scene_*.py")), key=os.path.getmtime)
        for old_file in scene_files[:-2]:
            try:
                os.remove(old_file)
                print(f"🗑️ Cleaned up old scene file: {old_file}")
            except Exception as e:
                print(f"⚠️ Could not remove {old_file}: {e}")
        
        # Remove old video folders (keep only last 3)
        videos_dir = os.path.join(MEDIA_DIR, "videos")
        if os.path.exists(videos_dir):
            video_folders = sorted(
                [f for f in Path(videos_dir).iterdir() if f.is_dir()],
                key=os.path.getmtime
            )
            for old_folder in video_folders[:-3]:
                try:
                    shutil.rmtree(old_folder)
                    print(f"🗑️ Cleaned up old video folder: {old_folder}")
                except Exception as e:
                    print(f"⚠️ Could not remove {old_folder}: {e}")
        
        # Remove old step audio files (keep only last 5)
        audio_files = sorted(glob.glob(os.path.join(BASE_DIR, "step_*_narration.mp3")), key=os.path.getmtime)
        for old_audio in audio_files[:-5]:
            try:
                os.remove(old_audio)
                print(f"🗑️ Cleaned up old audio file: {old_audio}")
            except Exception as e:
                print(f"⚠️ Could not remove {old_audio}: {e}")
        
        # Remove old combined audio files (keep only last 2)
        combined_files = sorted(glob.glob(os.path.join(BASE_DIR, "combined_narration*.mp3")), key=os.path.getmtime)
        for old_combined in combined_files[:-2]:
            try:
                os.remove(old_combined)
                print(f"🗑️ Cleaned up old combined audio: {old_combined}")
            except Exception as e:
                print(f"⚠️ Could not remove {old_combined}: {e}")
                
    except Exception as e:
        print(f"⚠️ Cleanup error: {e}")

async def render_scene(code: str):
    # Clean up old files before rendering
    cleanup_old_files()
    
    # Create a unique ID for this run
    run_id = str(uuid.uuid4())
    filename = f"scene_{run_id}.py"
    
    # Save code to file in the backend directory
    filepath = os.path.join(BASE_DIR, filename)
    with open(filepath, "w", encoding='utf-8') as f:
        f.write(code)
        
    # Run Manim with LOW quality (-ql) for better memory usage
    # -ql = 480p15, much lighter than -qm (720p30)
    
    cmd = ["manim", "-ql", "--media_dir", MEDIA_DIR, filepath, "GenScene"]
    
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        print("✓ Manim render completed")
    except subprocess.CalledProcessError as e:
        print("❌ Manim Error:", e.stderr)
        # Clean up failed scene file
        try:
            os.remove(filepath)
        except:
            pass
        raise Exception(f"Manim failed: {e.stderr}")
        
    # Construct expected output path
    # Low quality: {MEDIA_DIR}/videos/{filename_without_extension}/480p15/GenScene.mp4
    
    video_folder = filename.replace(".py", "")
    video_path = os.path.join(MEDIA_DIR, "videos", video_folder, "480p15", "GenScene.mp4")
    
    if not os.path.exists(video_path):
        # Clean up scene file
        try:
            os.remove(filepath)
        except:
            pass
        raise Exception(f"Video file not found at {video_path}")
    
    print(f"✓ Video created: {video_path}")
    
    # Clean up the scene file immediately after successful render
    try:
        os.remove(filepath)
        print(f"🗑️ Cleaned up scene file: {filepath}")
    except Exception as e:
        print(f"⚠️ Could not remove scene file: {e}")
        
    return video_path