now / app.py
andevs's picture
Update app.py
a3c7010 verified
Raw
History Blame Contribute Delete
3.75 kB
import gradio as gr
import librosa
import numpy as np
import tempfile
import os
import random
from moviepy.editor import (
VideoFileClip,
ImageClip,
AudioFileClip,
concatenate_videoclips,
vfx
)
# -------------------------
# Beat + energy detection
# -------------------------
def analyze_audio(audio_path):
y, sr = librosa.load(audio_path)
tempo, beats = librosa.beat.beat_track(y=y, sr=sr)
beat_times = librosa.frames_to_time(beats, sr=sr)
onset_env = librosa.onset.onset_strength(y=y, sr=sr)
energy = onset_env / np.max(onset_env)
return beat_times, energy
# -------------------------
# Template rules
# -------------------------
TEMPLATES = {
"Auto": {
"min_clip": 0.3,
"max_clip": 0.8,
"zoom_prob": 0.4,
"shake_prob": 0.2
},
"Hype": {
"min_clip": 0.2,
"max_clip": 0.5,
"zoom_prob": 0.6,
"shake_prob": 0.4
},
"Sad": {
"min_clip": 0.6,
"max_clip": 1.2,
"zoom_prob": 0.2,
"shake_prob": 0.0
}
}
# -------------------------
# Edit generator
# -------------------------
def generate_edit(song, media_files, template):
if song is None or not media_files:
return None
rules = TEMPLATES[template]
with tempfile.TemporaryDirectory() as tmp:
song_path = os.path.join(tmp, "song.mp3")
with open(song_path, "wb") as f:
f.write(song)
beats, energy = analyze_audio(song_path)
audio = AudioFileClip(song_path)
clips = []
media_index = 0
t = 0
while t < audio.duration:
duration = random.uniform(
rules["min_clip"], rules["max_clip"]
)
media = media_files[media_index % len(media_files)]
media_index += 1
media_path = os.path.join(tmp, os.path.basename(media.name))
with open(media_path, "wb") as f:
f.write(media.read())
if media_path.lower().endswith((".mp4", ".mov", ".webm")):
base = VideoFileClip(media_path)
clip = base.subclip(0, min(duration, base.duration))
else:
clip = ImageClip(media_path).set_duration(duration)
# Effects
if random.random() < rules["zoom_prob"]:
clip = clip.fx(vfx.resize, lambda t: 1 + 0.05 * t)
if random.random() < rules["shake_prob"]:
clip = clip.fx(vfx.crop, x1=5, y1=5, x2=5, y2=5)
clip = clip.resize(height=1080).set_position("center")
clips.append(clip)
t += duration
final = concatenate_videoclips(
clips, method="compose", padding=-0.05
)
final = final.set_audio(audio)
final = final.resize((1080, 1920))
output = os.path.join(tmp, "edit.mp4")
final.write_videofile(
output,
fps=30,
codec="libx264",
audio_codec="aac",
threads=2,
logger=None
)
return output
# -------------------------
# UI
# -------------------------
with gr.Blocks(title="EditForge AI Advanced") as demo:
gr.Markdown("## 🎬 EditForge AI (Advanced)")
song = gr.File(label="Upload Song", type="binary")
media = gr.Files(label="Upload Images / Videos")
template = gr.Dropdown(
choices=["Auto", "Hype", "Sad"],
value="Auto",
label="Edit Style"
)
output = gr.Video(label="Final Edit")
btn = gr.Button("🚀 Generate Edit")
btn.click(
fn=generate_edit,
inputs=[song, media, template],
outputs=output
)
demo.launch(server_name="0.0.0.0", server_port=7860)