File size: 2,865 Bytes
bf2ed68
 
 
 
 
f1f9cb5
0140161
 
 
9faf044
f1f9cb5
9faf044
0140161
 
 
 
 
9faf044
 
 
 
f1f9cb5
 
 
0140161
f1f9cb5
 
 
0140161
7b346cc
0140161
f1f9cb5
bf2ed68
0140161
f1f9cb5
 
7b346cc
0140161
f1f9cb5
 
7b346cc
0140161
bf2ed68
0140161
f1f9cb5
bf2ed68
f1f9cb5
bf2ed68
 
7b346cc
f1f9cb5
bf2ed68
 
f1f9cb5
bf2ed68
f1f9cb5
bf2ed68
f1f9cb5
0140161
 
f1f9cb5
 
0140161
f1f9cb5
 
bf2ed68
f1f9cb5
 
 
 
 
 
 
bf2ed68
f1f9cb5
bf2ed68
 
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
import gradio as gr
import subprocess
import os
import uuid

# Carpeta temporal para guardar los videos generados
TEMP_DIR = "temp_videos"
os.makedirs(TEMP_DIR, exist_ok=True)

def get_audio_duration(audio_path):
    """Obtiene duración del audio en segundos usando ffprobe"""
    try:
        result = subprocess.run([
            "ffprobe", "-v", "error", "-show_entries",
            "format=duration", "-of",
            "default=noprint_wrappers=1:nokey=1", audio_path
        ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        return float(result.stdout.strip())
    except:
        return None

def generate_video(audio_path, image_path):
    if not os.path.isfile(audio_path) or not os.path.isfile(image_path):
        return "❌ Missing or invalid input files."

    duration = get_audio_duration(audio_path)
    if not duration:
        return "❌ Could not get audio duration. Check your audio file."

    output_filename = os.path.join("temp_videos", f"output_{uuid.uuid4().hex[:8]}.mp4")

    try:
        cmd = [
            "ffmpeg", "-y",
            "-loop", "1", "-framerate", "1", "-i", image_path,
            "-i", audio_path,
            "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2",  # 👈 FIX AQUI
            "-c:v", "libx264", "-preset", "ultrafast", "-tune", "stillimage",
            "-c:a", "aac", "-b:a", "192k",
            "-t", str(duration),
            "-pix_fmt", "yuv420p", "-r", "1",
            output_filename
        ]

        result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

        if os.path.exists(output_filename) and os.path.getsize(output_filename) > 0:
            return output_filename
        else:
            print("FFmpeg ERROR:", result.stderr)
            return "❌ Something went wrong while generating the video."

    except Exception as e:
        return f"⚠️ Error: {str(e)}"

# Interfaz Gradio
with gr.Blocks(theme="Taithrah/Minimal") as app:
    gr.Markdown("# 🎶 Audio to Video Tool\nUpload an audio file and an image to generate a simple MP4 video (like TunesToTube)")

    with gr.Row():
        audio = gr.Audio(label="🎧 Upload your audio file", type="filepath")
        image = gr.Image(label="🖼️ Upload your image", type="filepath")

    submit = gr.Button("🚀 Generate Video")
    output = gr.Video(label="🎬 Your Video")

    def handle_generate(audio_path, image_path):
        result = generate_video(audio_path, image_path)
        # Si es una string con error, la mandamos como mensaje, si es ruta, se muestra el video
        if result.endswith(".mp4") and os.path.exists(result):
            return result
        else:
            return gr.update(value=None, visible=False), gr.update(value=result, visible=True)

    submit.click(fn=handle_generate, inputs=[audio, image], outputs=output)

app.launch()