File size: 5,716 Bytes
43fcbe8
77c11ae
38ff849
8337d0b
fa691a5
77c11ae
 
38ff849
77c11ae
 
 
 
99b44b3
77c11ae
9143db2
99b44b3
fa691a5
77c11ae
 
 
38ff849
 
77c11ae
 
99b44b3
38ff849
99b44b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d68572a
77c11ae
99b44b3
d5141b3
 
 
 
 
 
 
 
99b44b3
 
d5141b3
 
 
 
99b44b3
d5141b3
 
 
99b44b3
d5141b3
99b44b3
 
 
38ff849
99b44b3
 
d5141b3
99b44b3
d5141b3
99b44b3
d5141b3
 
 
 
99b44b3
 
 
d68572a
99b44b3
c7b9a72
99b44b3
77c11ae
60e6f97
99b44b3
 
d68572a
99b44b3
77c11ae
 
7c87717
9143db2
99b44b3
77c11ae
d5141b3
99b44b3
d5141b3
99b44b3
 
 
 
 
 
 
 
 
 
 
 
 
7c87717
d68572a
99b44b3
 
fa201eb
77c11ae
 
fa201eb
99b44b3
720c3d5
07b3b3d
d5141b3
7c87717
c9d2e08
99b44b3
 
77c11ae
99b44b3
 
 
 
 
 
 
 
8337d0b
99b44b3
 
d5141b3
9e5ee0a
d7f3a60
07b3b3d
d5141b3
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import os
import re
import requests
import gradio as gr
from moviepy.editor import *
import edge_tts
import tempfile
import logging
from datetime import datetime
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
import nltk
from nltk.tokenize import sent_tokenize
from transformers import pipeline
import torch
import asyncio

# Configuraci贸n inicial
nltk.download('punkt', quiet=True)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Configuraci贸n de modelos
PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")
MODEL_NAME = "DeepESP/gpt2-spanish"

# Soluci贸n robusta para obtener voces
async def get_voices():
    try:
        voices = await edge_tts.list_voices()
        voice_names = []
        for v in voices:
            try:
                name = v.get('Name', v.get('ShortName', 'Desconocido'))
                gender = v.get('Gender', 'Desconocido')
                locale = v.get('Locale', v.get('Language', 'Desconocido'))
                voice_names.append(f"{name} ({gender}, {locale})")
            except Exception as e:
                logger.warning(f"Error procesando voz: {v} - {str(e)}")
                continue
        return voice_names, voices
    except Exception as e:
        logger.error(f"Error al obtener voces: {str(e)}")
        return [], []

# Obtener voces de forma s铆ncrona para la inicializaci贸n
VOICE_NAMES, VOICES = asyncio.run(get_voices())
if not VOICES:
    VOICE_NAMES = ["Voz Predeterminada (Femenino, es-ES)"]
    VOICES = [{'ShortName': 'es-ES-ElviraNeural'}]

def generar_guion_profesional(prompt):
    """Genera guiones con respaldo robusto"""
    try:
        generator = pipeline(
            "text-generation",
            model=MODEL_NAME,
            device=0 if torch.cuda.is_available() else -1
        )
        
        response = generator(
            f"Escribe un guion profesional para un video de YouTube sobre '{prompt}':\n\n1. Introducci贸n\n2. Desarrollo\n3. Conclusi贸n\n\n",
            max_length=800,
            temperature=0.7,
            num_return_sequences=1
        )
        
        return response[0]['generated_text']
        
    except Exception as e:
        logger.error(f"Error generando guion: {str(e)}")
        return f"""Gui贸n de respaldo sobre {prompt}:
        
1. INTRODUCCI脫N: Hoy exploraremos {prompt}
2. DESARROLLO: Aspectos clave sobre el tema
3. CONCLUSI脫N: Resumen y cierre"""

def buscar_videos_avanzado(prompt, guion, num_videos=3):
    """B煤squeda con m煤ltiples respaldos"""
    try:
        palabras = re.findall(r'\b\w{4,}\b', prompt.lower())[:5]
        response = requests.get(
            f"https://api.pexels.com/videos/search?query={'+'.join(palabras)}&per_page={num_videos}",
            headers={"Authorization": PEXELS_API_KEY},
            timeout=10
        )
        return response.json().get('videos', [])[:num_videos]
    except Exception as e:
        logger.error(f"Error buscando videos: {str(e)}")
        return []

async def crear_video_profesional(prompt, custom_script, voz_index, musica=None):
    try:
        # 1. Generar gui贸n
        guion = custom_script if custom_script else generar_guion_profesional(prompt)
        
        # 2. Configurar voz
        voz_seleccionada = VOICES[voz_index]['ShortName'] if VOICES else 'es-ES-ElviraNeural'
        
        # 3. Generar audio
        voz_archivo = "voz.mp3"
        await edge_tts.Communicate(guion, voz_seleccionada).save(voz_archivo)
        audio = AudioFileClip(voz_archivo)
        
        # 4. Obtener videos
        videos_data = buscar_videos_avanzado(prompt, guion)
        if not videos_data:
            raise Exception("No se encontraron videos")
            
        # 5. Procesar videos
        clips = []
        for video in videos_data[:3]:  # Usar m谩ximo 3 videos
            video_file = next((vf for vf in video['video_files'] if vf['quality'] == 'sd'), video['video_files'][0])
            with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as temp_video:
                response = requests.get(video_file['link'], stream=True)
                for chunk in response.iter_content(chunk_size=1024*1024):
                    temp_video.write(chunk)
                clip = VideoFileClip(temp_video.name).subclip(0, min(10, video['duration']))
                clips.append(clip)
        
        # 6. Crear video final
        video_final = concatenate_videoclips(clips)
        video_final = video_final.set_audio(audio)
        
        output_path = f"video_output_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
        video_final.write_videofile(output_path, fps=24, threads=2)
        
        return output_path
        
    except Exception as e:
        logger.error(f"Error cr铆tico: {str(e)}")
        return None
    finally:
        if os.path.exists(voz_archivo):
            os.remove(voz_archivo)

# Interfaz optimizada
with gr.Blocks(title="Generador de Videos") as app:
    with gr.Row():
        with gr.Column():
            prompt = gr.Textbox(label="Tema del video")
            custom_script = gr.TextArea(label="Gui贸n personalizado (opcional)")
            voz = gr.Dropdown(VOICE_NAMES, label="Voz", value=VOICE_NAMES[0])
            btn = gr.Button("Generar Video", variant="primary")
        with gr.Column():
            output = gr.Video(label="Resultado", format="mp4")
    
    btn.click(
        fn=lambda p, cs, v: asyncio.run(crear_video_profesional(p, cs, VOICE_NAMES.index(v))),
        inputs=[prompt, custom_script, voz],
        outputs=output
    )

if __name__ == "__main__":
    app.launch(server_name="0.0.0.0", server_port=7860)