Spaces:
Running
Running
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() |