theminji commited on
Commit
6bc5ddf
·
verified ·
1 Parent(s): ab8c56a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +4 -56
app.py CHANGED
@@ -26,11 +26,6 @@ from threading import Timer
26
  from flask import Flask, render_template, request, url_for, send_from_directory
27
  from google import genai
28
 
29
- # New imports for audio generation and handling
30
- from kokoro import KPipeline
31
- import soundfile as sf
32
- import numpy as np
33
-
34
  app = Flask(__name__)
35
 
36
  # Load API key from environment variable
@@ -67,11 +62,7 @@ Keep the scene uncluttered and aesthetically pleasing.
67
  Make sure things are not overlapping unless explicitly stated otherwise.
68
  It is crucial that the script works correctly on the first try, so make sure to think about the layout and storyboard and stuff of the scene.
69
  Make sure to think through what you are going to do and think about the topic before you write the code.
70
- In addition, write a commentary script inside of ```script``` codeblock. This should be short and fit the content and align with the timing of the scene. Use "..." if needed to add a bit of a pause.
71
- Don't describe music or sound effects in your script, only what the text to speech model will say.
72
- Make sure that the script is short and don't do an intro and outro, simply start it. Additionally, keep it short enough so that it aligns with the video timing.
73
- You can always adjust the self.wait(x) or run_time=x inside the code to wait for the speech if needed.
74
- Make sure to think about the script timing before you write the code so that it doesnt cut off the speech or anything and the video and speech are synced
75
  You got this!! <3
76
  """
77
  )
@@ -82,13 +73,7 @@ You got this!! <3
82
  if not code_match:
83
  raise Exception("No python code block found in the AI response.")
84
  code = code_match.group(1)
85
-
86
- # Extract the commentary script from the AI response
87
- script_pattern = r"```script\s*(.*?)\s*```"
88
- script_match = re.search(script_pattern, ai_response.text, re.DOTALL)
89
- if not script_match:
90
- raise Exception("No script block found in the AI response.")
91
- script = script_match.group(1)
92
 
93
  # Determine the scene class name from the generated code
94
  scene_match = re.search(r"class\s+(\w+)\(.*Scene.*\):", code)
@@ -103,24 +88,6 @@ You got this!! <3
103
  with open(code_filepath, "w") as f:
104
  f.write(code)
105
 
106
- # === Generate Commentary Audio via Kokoro ===
107
- # Initialize the Kokoro pipeline (adjust lang_code if needed)
108
- audio_pipeline = KPipeline(lang_code='a')
109
- # Feed in the commentary script; here we split the text by one or more newlines.
110
- audio_generator = audio_pipeline(script, voice='af_heart', speed=1, split_pattern=r'\n+')
111
-
112
- audio_segments = []
113
- for _, _, audio in audio_generator:
114
- audio_segments.append(audio)
115
-
116
- if not audio_segments:
117
- raise Exception("No audio segments were generated from the commentary script.")
118
-
119
- # Concatenate all audio segments into one audio track
120
- full_audio = np.concatenate(audio_segments)
121
- commentary_audio_filename = f"commentary_{uuid.uuid4().hex}.wav"
122
- commentary_audio_path = os.path.join("/tmp", commentary_audio_filename)
123
- sf.write(commentary_audio_path, full_audio, 24000)
124
 
125
  # === Run Manim to generate the silent video ===
126
  # Prepare the Manim command with the --media_dir flag
@@ -147,26 +114,7 @@ You got this!! <3
147
  # Move the video file to /tmp (to serve it from there)
148
  tmp_video_path = os.path.join("/tmp", video_filename)
149
  shutil.move(video_path_in_media, tmp_video_path)
150
-
151
- # === Combine Video with Commentary Audio using FFmpeg ===
152
- final_video_filename = f"final_video_{uuid.uuid4().hex}.mp4"
153
- final_video_path = os.path.join("/tmp", final_video_filename)
154
-
155
- ffmpeg_cmd = [
156
- "ffmpeg", "-y",
157
- "-i", tmp_video_path,
158
- "-i", commentary_audio_path,
159
- "-c:v", "copy",
160
- "-c:a", "aac",
161
- "-shortest",
162
- final_video_path
163
- ]
164
- try:
165
- subprocess.run(ffmpeg_cmd, check=True, capture_output=True, text=True)
166
- except subprocess.CalledProcessError as cpe:
167
- app.logger.error("FFmpeg error output: %s", cpe.stderr)
168
- raise Exception(f"FFmpeg failed: {cpe.stderr}")
169
-
170
  # Schedule deletion of all temporary files after 10 minutes (600 seconds)
171
  def remove_files():
172
  for fpath in [tmp_video_path, code_filepath, commentary_audio_path, final_video_path]:
@@ -179,7 +127,7 @@ You got this!! <3
179
  Timer(600, remove_files).start()
180
 
181
  # Use the final combined video for display
182
- video_url = url_for('get_video', filename=final_video_filename)
183
  return render_template("result.html", video_url=video_url)
184
 
185
  except Exception as e:
 
26
  from flask import Flask, render_template, request, url_for, send_from_directory
27
  from google import genai
28
 
 
 
 
 
 
29
  app = Flask(__name__)
30
 
31
  # Load API key from environment variable
 
62
  Make sure things are not overlapping unless explicitly stated otherwise.
63
  It is crucial that the script works correctly on the first try, so make sure to think about the layout and storyboard and stuff of the scene.
64
  Make sure to think through what you are going to do and think about the topic before you write the code.
65
+ Use self.wait at the end to give the user enough time to process the frame.
 
 
 
 
66
  You got this!! <3
67
  """
68
  )
 
73
  if not code_match:
74
  raise Exception("No python code block found in the AI response.")
75
  code = code_match.group(1)
76
+
 
 
 
 
 
 
77
 
78
  # Determine the scene class name from the generated code
79
  scene_match = re.search(r"class\s+(\w+)\(.*Scene.*\):", code)
 
88
  with open(code_filepath, "w") as f:
89
  f.write(code)
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  # === Run Manim to generate the silent video ===
93
  # Prepare the Manim command with the --media_dir flag
 
114
  # Move the video file to /tmp (to serve it from there)
115
  tmp_video_path = os.path.join("/tmp", video_filename)
116
  shutil.move(video_path_in_media, tmp_video_path)
117
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  # Schedule deletion of all temporary files after 10 minutes (600 seconds)
119
  def remove_files():
120
  for fpath in [tmp_video_path, code_filepath, commentary_audio_path, final_video_path]:
 
127
  Timer(600, remove_files).start()
128
 
129
  # Use the final combined video for display
130
+ video_url = url_for('get_video', filename=tmp_video_path)
131
  return render_template("result.html", video_url=video_url)
132
 
133
  except Exception as e: