INVIDEO_BASIC / app.py
gnosticdev's picture
Update app.py
57db4ae verified
raw
history blame
4.42 kB
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()