File size: 4,416 Bytes
43fcbe8
 
 
 
 
 
 
 
a483f49
57db4ae
43fcbe8
57db4ae
 
 
43fcbe8
57db4ae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43fcbe8
57db4ae
 
 
 
 
 
 
43fcbe8
57db4ae
 
 
 
 
43fcbe8
57db4ae
 
a483f49
 
 
57db4ae
 
43fcbe8
 
 
57db4ae
a483f49
57db4ae
 
43fcbe8
57db4ae
 
 
 
 
 
 
 
 
43fcbe8
57db4ae
43fcbe8
 
 
57db4ae
 
43fcbe8
 
57db4ae
43fcbe8
 
57db4ae
 
 
 
 
 
 
 
 
 
a483f49
57db4ae
 
 
a483f49
57db4ae
a483f49
57db4ae
 
 
 
 
 
 
 
a483f49
57db4ae
 
 
 
 
 
 
a483f49
 
43fcbe8
57db4ae
 
 
 
43fcbe8
 
57db4ae
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import os
import requests
import edge_tts
import gradio as gr
from moviepy.editor import *
from PIL import Image
import io
import asyncio
import json
from openai import OpenAI

# Configura APIs (gratis)
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))  # Para GPT-3.5-turbo
PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")

# 1. Generar guion automático con IA (si el usuario no proporciona uno)
async def generate_script(topic):
    prompt = f"""
    Genera un guion para un video de YouTube sobre '{topic}'. 
    Formato JSON ejemplo:
    [
        {{"prompt": "imagen de ejemplo", "text": "narración correspondiente"}},
        ...
    ]
    """
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.7
    )
    return response.choices[0].message.content

# 2. Descargar imágenes de Pexels/Unsplash
def get_stock_media(query):
    url = f"https://api.pexels.com/v1/photos/search?query={query}&per_page=1"
    headers = {"Authorization": PEXELS_API_KEY}
    response = requests.get(url, headers=headers).json()
    image_url = response["photos"][0]["src"]["large"]
    return Image.open(io.BytesIO(requests.get(image_url).content))

# 3. Generar voz con Edge TTS
async def generate_voice(text, voice="es-ES-AlvaroNeural"):
    communicate = edge_tts.Communicate(text=text, voice=voice)
    await communicate.save("voice.mp3")
    return AudioFileClip("voice.mp3")

# 4. Crear video final
async def create_video(script_json, voice_model, music_file=None):
    try:
        script = json.loads(script_json)
    except json.JSONDecodeError:
        raise gr.Error("¡Error en el formato del guion! Usa JSON válido.")

    clips = []
    for i, scene in enumerate(script):
        img = get_stock_media(scene["prompt"])
        img.save(f"scene_{i}.jpg")
        
        audio = await generate_voice(scene["text"], voice_model)
        clip = ImageClip(f"scene_{i}.jpg").set_duration(audio.duration)
        
        # Subtítulos dinámicos
        text_clip = TextClip(
            scene["text"],
            fontsize=30,
            color="white",
            stroke_color="black",
            size=(clip.w * 0.9, None),
            method="caption"
        ).set_position(("center", "bottom")).set_duration(audio.duration)
        
        clips.append(CompositeVideoClip([clip, text_clip]).set_audio(audio))
    
    final_video = concatenate_videoclips(clips)
    if music_file:
        music = AudioFileClip(music_file).volumex(0.2)
        final_video.audio = CompositeAudioClip([final_video.audio, music.set_start(0)])
    
    output_path = "final_video.mp4"
    final_video.write_videofile(output_path, fps=24, codec="libx264")
    return output_path

# 5. Interfaz Gradio (2 modos: automático o manual)
with gr.Blocks() as demo:
    gr.Markdown("## 🎥 Generador de Videos con IA (Modo Automático o Manual)")
    
    with gr.Tab("Modo Automático"):
        topic_input = gr.Textbox(label="Tema del video (ej: 'Top 10 misterios del mundo')")
        auto_voice = gr.Dropdown(label="Voz", choices=["es-ES-AlvaroNeural", "en-US-JennyNeural"])
        generate_auto_btn = gr.Button("Generar Guion y Video")
    
    with gr.Tab("Modo Manual"):
        script_input = gr.Textbox(
            label="Pega tu guion (JSON)",
            placeholder='[{"prompt": "ciudad futurista", "text": "Bienvenidos al futuro..."}]',
            lines=10
        )
        manual_voice = gr.Dropdown(label="Voz", choices=["es-ES-AlvaroNeural", "en-US-JennyNeural"])
        music_upload = gr.File(label="Música de fondo (opcional)", type="filepath")
        generate_manual_btn = gr.Button("Generar Video")
    
    output_video = gr.Video(label="Video Generado", format="mp4")
    
    # Modo Automático: Generar guion + video
    async def auto_mode(topic, voice):
        script = await generate_script(topic)
        return await create_video(script, voice)
    
    # Modo Manual: Usar guion existente
    async def manual_mode(script, voice, music):
        return await create_video(script, voice, music)
    
    generate_auto_btn.click(
        fn=auto_mode,
        inputs=[topic_input, auto_voice],
        outputs=output_video
    )
    
    generate_manual_btn.click(
        fn=manual_mode,
        inputs=[script_input, manual_voice, music_upload],
        outputs=output_video
    )

demo.launch()