Spaces:
Running
Running
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import moviepy.editor as mp
|
3 |
+
import numpy as np
|
4 |
+
from PIL import Image
|
5 |
+
|
6 |
+
# Resize image with aspect ratio
|
7 |
+
def resize_image_with_aspect_ratio(img, target_size=(1280, 720), padding_color=(0, 0, 0)):
|
8 |
+
width, height = img.size
|
9 |
+
target_width, target_height = target_size
|
10 |
+
aspect_ratio = width / height
|
11 |
+
target_aspect_ratio = target_width / target_height
|
12 |
+
|
13 |
+
if aspect_ratio > target_aspect_ratio:
|
14 |
+
new_width = target_width
|
15 |
+
new_height = int(new_width / aspect_ratio)
|
16 |
+
else:
|
17 |
+
new_height = target_height
|
18 |
+
new_width = int(new_height * aspect_ratio)
|
19 |
+
|
20 |
+
img_resized = img.resize((new_width, new_height))
|
21 |
+
final_img = Image.new('RGB', target_size, padding_color)
|
22 |
+
padding_left = (target_width - new_width) // 2
|
23 |
+
padding_top = (target_height - new_height) // 2
|
24 |
+
final_img.paste(img_resized, (padding_left, padding_top))
|
25 |
+
|
26 |
+
return final_img
|
27 |
+
|
28 |
+
# Video generation function with transition
|
29 |
+
def process_and_generate_video(audio_file, images):
|
30 |
+
audio = mp.AudioFileClip(audio_file)
|
31 |
+
audio_duration = audio.duration
|
32 |
+
image_clips = []
|
33 |
+
image_count = len(images)
|
34 |
+
image_duration = audio_duration / image_count
|
35 |
+
|
36 |
+
# Process each image and create a video clip
|
37 |
+
for img_path in images:
|
38 |
+
img = Image.open(img_path)
|
39 |
+
img = resize_image_with_aspect_ratio(img, target_size=(1280, 720))
|
40 |
+
|
41 |
+
img_clip = mp.ImageClip(np.array(img)).set_duration(image_duration).set_fps(24)
|
42 |
+
|
43 |
+
# Add transition effect (crossfade)
|
44 |
+
if len(image_clips) > 0:
|
45 |
+
img_clip = img_clip.crossfadein(1) # 1-second crossfade transition
|
46 |
+
|
47 |
+
image_clips.append(img_clip)
|
48 |
+
|
49 |
+
# Combine the image clips into a single video
|
50 |
+
video = mp.concatenate_videoclips(image_clips, method="compose")
|
51 |
+
video = video.set_audio(audio)
|
52 |
+
|
53 |
+
# Output path for the generated video
|
54 |
+
output_path = '/content/generated_video.mp4'
|
55 |
+
video.write_videofile(output_path, codec='libx264', audio_codec='aac')
|
56 |
+
|
57 |
+
return output_path
|
58 |
+
|
59 |
+
# Gradio interface setup
|
60 |
+
def gradio_interface():
|
61 |
+
with gr.Blocks() as demo:
|
62 |
+
with gr.Row():
|
63 |
+
with gr.Column():
|
64 |
+
mp3_input = gr.Audio(type="filepath", label="Upload MP3") # MP3 input
|
65 |
+
image_input = gr.File(type="filepath", file_types=[".jpg", ".png"], label="Upload Images", file_count="multiple") # Images input
|
66 |
+
generate_button = gr.Button("Generate Video") # Button to generate video
|
67 |
+
|
68 |
+
output_video = gr.Video(label="Generated Video") # Video output display
|
69 |
+
|
70 |
+
generate_button.click(fn=process_and_generate_video, inputs=[mp3_input, image_input], outputs=output_video)
|
71 |
+
|
72 |
+
demo.launch() # Launch the Gradio interface
|
73 |
+
|
74 |
+
# Run the Gradio app
|
75 |
+
gradio_interface()
|