Spaces:
Sleeping
Sleeping
Update video_processor.py
Browse files- video_processor.py +40 -40
video_processor.py
CHANGED
|
@@ -36,14 +36,14 @@ def generate_audio_with_elevenlabs(text, output_path):
|
|
| 36 |
return False
|
| 37 |
|
| 38 |
def create_video(video_script, audio_script, summary):
|
| 39 |
-
"""Create educational video
|
| 40 |
try:
|
| 41 |
-
# Generate audio
|
| 42 |
audio_path = os.path.join(tempfile.gettempdir(), "narration.mp3")
|
| 43 |
if not generate_audio_with_elevenlabs(audio_script, audio_path):
|
| 44 |
raise Exception("Audio generation failed")
|
| 45 |
-
|
| 46 |
-
# Parse scenes
|
| 47 |
scenes = []
|
| 48 |
for scene_text in video_script.split("\n\n"):
|
| 49 |
if "[Visual]:" in scene_text:
|
|
@@ -52,59 +52,59 @@ def create_video(video_script, audio_script, summary):
|
|
| 52 |
"voiceover": scene_text.split("[Voiceover]:")[1].strip()
|
| 53 |
}
|
| 54 |
scenes.append(scene)
|
| 55 |
-
|
| 56 |
-
#
|
| 57 |
video_clips = []
|
| 58 |
for scene in scenes:
|
| 59 |
try:
|
| 60 |
-
|
| 61 |
f"https://api.pexels.com/videos/search?query={scene['visual']}&per_page=1",
|
| 62 |
headers={"Authorization": PEXELS_API_KEY},
|
| 63 |
timeout=10
|
| 64 |
)
|
| 65 |
-
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
-
clip = VideoFileClip(
|
| 69 |
-
clip = clip.resize(height=1080)
|
| 70 |
video_clips.append(clip)
|
| 71 |
except Exception as e:
|
| 72 |
-
print(f"Failed to
|
| 73 |
-
|
| 74 |
-
|
| 75 |
if not video_clips:
|
| 76 |
-
raise Exception("No
|
| 77 |
-
|
| 78 |
-
# Combine
|
| 79 |
-
final_video = concatenate_videoclips(video_clips)
|
| 80 |
-
audio_clip = AudioFileClip(audio_path)
|
| 81 |
final_video = final_video.set_audio(audio_clip)
|
| 82 |
-
|
| 83 |
-
# Create subtitles
|
| 84 |
def create_subtitle(text):
|
| 85 |
return TextClip(
|
| 86 |
-
text,
|
| 87 |
-
fontsize=40,
|
| 88 |
-
color='white',
|
| 89 |
-
font='Arial-Bold',
|
| 90 |
-
stroke_color='black',
|
| 91 |
stroke_width=1
|
| 92 |
).set_position(('center', 'bottom')).set_duration(8)
|
| 93 |
-
|
| 94 |
-
subtitles = [create_subtitle(scene['voiceover']) for scene in scenes]
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
# Add watermark
|
| 98 |
watermark = TextClip(
|
| 99 |
-
"MentorMindz",
|
| 100 |
-
fontsize=30,
|
| 101 |
color='white'
|
| 102 |
).set_position(('right', 'top')).set_duration(final_video.duration)
|
| 103 |
-
|
| 104 |
-
# Combine all
|
| 105 |
-
final_video = CompositeVideoClip([final_video, subtitles, watermark])
|
| 106 |
-
|
| 107 |
-
# Export
|
| 108 |
output_path = os.path.join(tempfile.gettempdir(), "final_output.mp4")
|
| 109 |
final_video.write_videofile(
|
| 110 |
output_path,
|
|
@@ -113,8 +113,8 @@ def create_video(video_script, audio_script, summary):
|
|
| 113 |
fps=24,
|
| 114 |
threads=4
|
| 115 |
)
|
| 116 |
-
|
| 117 |
return output_path
|
| 118 |
-
|
| 119 |
except Exception as e:
|
| 120 |
raise Exception(f"Video creation failed: {str(e)}")
|
|
|
|
| 36 |
return False
|
| 37 |
|
| 38 |
def create_video(video_script, audio_script, summary):
|
| 39 |
+
"""Create educational video using Pexels and ElevenLabs"""
|
| 40 |
try:
|
| 41 |
+
# Step 1: Generate audio
|
| 42 |
audio_path = os.path.join(tempfile.gettempdir(), "narration.mp3")
|
| 43 |
if not generate_audio_with_elevenlabs(audio_script, audio_path):
|
| 44 |
raise Exception("Audio generation failed")
|
| 45 |
+
|
| 46 |
+
# Step 2: Parse scenes
|
| 47 |
scenes = []
|
| 48 |
for scene_text in video_script.split("\n\n"):
|
| 49 |
if "[Visual]:" in scene_text:
|
|
|
|
| 52 |
"voiceover": scene_text.split("[Voiceover]:")[1].strip()
|
| 53 |
}
|
| 54 |
scenes.append(scene)
|
| 55 |
+
|
| 56 |
+
# Step 3: Fetch video clips from Pexels
|
| 57 |
video_clips = []
|
| 58 |
for scene in scenes:
|
| 59 |
try:
|
| 60 |
+
response = requests.get(
|
| 61 |
f"https://api.pexels.com/videos/search?query={scene['visual']}&per_page=1",
|
| 62 |
headers={"Authorization": PEXELS_API_KEY},
|
| 63 |
timeout=10
|
| 64 |
)
|
| 65 |
+
response.raise_for_status()
|
| 66 |
+
video_files = response.json()['videos'][0]['video_files']
|
| 67 |
+
mp4_url = next((file['link'] for file in video_files if file['file_type'] == 'video/mp4' and file['quality'] == 'sd'), None)
|
| 68 |
+
if not mp4_url:
|
| 69 |
+
raise Exception("No MP4 video found.")
|
| 70 |
|
| 71 |
+
clip = VideoFileClip(mp4_url).subclip(0, 8).resize(height=1080)
|
|
|
|
| 72 |
video_clips.append(clip)
|
| 73 |
except Exception as e:
|
| 74 |
+
print(f"Failed to fetch video for scene '{scene['visual']}': {str(e)}")
|
| 75 |
+
|
|
|
|
| 76 |
if not video_clips:
|
| 77 |
+
raise Exception("No video clips found")
|
| 78 |
+
|
| 79 |
+
# Step 4: Combine clips and set audio
|
| 80 |
+
final_video = concatenate_videoclips(video_clips, method="compose")
|
| 81 |
+
audio_clip = AudioFileClip(audio_path).set_duration(final_video.duration)
|
| 82 |
final_video = final_video.set_audio(audio_clip)
|
| 83 |
+
|
| 84 |
+
# Step 5: Create subtitles
|
| 85 |
def create_subtitle(text):
|
| 86 |
return TextClip(
|
| 87 |
+
text,
|
| 88 |
+
fontsize=40,
|
| 89 |
+
color='white',
|
| 90 |
+
font='Arial-Bold',
|
| 91 |
+
stroke_color='black',
|
| 92 |
stroke_width=1
|
| 93 |
).set_position(('center', 'bottom')).set_duration(8)
|
| 94 |
+
|
| 95 |
+
subtitles = [create_subtitle(scene['voiceover']).set_start(i * 8) for i, scene in enumerate(scenes)]
|
| 96 |
+
|
| 97 |
+
# Step 6: Add watermark
|
|
|
|
| 98 |
watermark = TextClip(
|
| 99 |
+
"MentorMindz",
|
| 100 |
+
fontsize=30,
|
| 101 |
color='white'
|
| 102 |
).set_position(('right', 'top')).set_duration(final_video.duration)
|
| 103 |
+
|
| 104 |
+
# Step 7: Combine all layers
|
| 105 |
+
final_video = CompositeVideoClip([final_video, *subtitles, watermark])
|
| 106 |
+
|
| 107 |
+
# Step 8: Export
|
| 108 |
output_path = os.path.join(tempfile.gettempdir(), "final_output.mp4")
|
| 109 |
final_video.write_videofile(
|
| 110 |
output_path,
|
|
|
|
| 113 |
fps=24,
|
| 114 |
threads=4
|
| 115 |
)
|
| 116 |
+
|
| 117 |
return output_path
|
| 118 |
+
|
| 119 |
except Exception as e:
|
| 120 |
raise Exception(f"Video creation failed: {str(e)}")
|