File size: 5,961 Bytes
43fcbe8
d68572a
38ff849
8337d0b
fa691a5
d68572a
38ff849
d68572a
9143db2
 
ab6a3fb
60e6f97
fa691a5
53ae22b
d68572a
38ff849
 
60e6f97
ab6a3fb
60e6f97
ab6a3fb
fa691a5
38ff849
d68572a
 
 
9143db2
d68572a
60e6f97
d68572a
77ffd33
60e6f97
 
 
 
 
 
 
 
 
 
d68572a
60e6f97
 
 
 
9143db2
 
60e6f97
9143db2
60e6f97
d68572a
9143db2
60e6f97
9143db2
 
 
60e6f97
ae19496
60e6f97
9143db2
 
60e6f97
9143db2
 
60e6f97
9143db2
60e6f97
 
38ff849
60e6f97
 
07b3b3d
d68572a
 
60e6f97
d68572a
60e6f97
d68572a
60e6f97
d68572a
 
 
 
 
c7b9a72
60e6f97
 
 
 
 
d68572a
60e6f97
 
d68572a
 
 
 
60e6f97
d68572a
 
60e6f97
 
9143db2
60e6f97
 
d68572a
60e6f97
 
9143db2
60e6f97
 
 
 
 
 
 
 
d68572a
60e6f97
 
 
9143db2
 
38ff849
60e6f97
9143db2
60e6f97
 
 
9143db2
22e9f48
d68572a
60e6f97
22e9f48
60e6f97
3e716f3
38ff849
d68572a
60e6f97
ab6a3fb
38ff849
fa201eb
60e6f97
 
38ff849
fa201eb
60e6f97
720c3d5
07b3b3d
60e6f97
 
 
 
c9d2e08
60e6f97
 
d7f3a60
9143db2
60e6f97
 
 
 
 
9143db2
60e6f97
 
8337d0b
d68572a
60e6f97
 
9e5ee0a
d7f3a60
07b3b3d
60e6f97
 
 
 
 
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import os
import subprocess
import requests
import gradio as gr
from moviepy.editor import *
from datetime import datetime
import logging
import re
import torch
from transformers import GPT2LMHeadModel, GPT2Tokenizer
import warnings
import time

# Configuración inicial
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Suprimir warnings específicos
warnings.filterwarnings("ignore", category=UserWarning, module="transformers")
warnings.filterwarnings("ignore", category=DeprecationWarning)

PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")

# Lista de voces válidas
VOICES = [
    "es-MX-DaliaNeural", "es-ES-ElviraNeural", "es-AR-ElenaNeural",
    "es-MX-JorgeNeural", "es-ES-AlvaroNeural", "es-AR-TomasNeural",
    "en-US-JennyNeural", "fr-FR-DeniseNeural", "de-DE-KatjaNeural",
    "it-IT-ElsaNeural", "pt-BR-FranciscaNeural", "ja-JP-NanamiNeural"
]

# Cargar modelo GPT-2 con manejo de errores mejorado
def cargar_modelo():
    try:
        tokenizer = GPT2Tokenizer.from_pretrained("datificate/gpt2-small-spanish")
        model = GPT2LMHeadModel.from_pretrained("datificate/gpt2-small-spanish")
        logger.info("Modelo GPT-2 cargado correctamente")
        return tokenizer, model
    except Exception as e:
        logger.error(f"Error cargando modelo: {str(e)}")
        return None, None

tokenizer, model = cargar_modelo()

def generar_guion(tema, custom_script=None):
    """Genera texto basado en el tema sin estructuras predefinidas"""
    if custom_script:
        return custom_script
    
    if model is None or tokenizer is None:
        return f"Texto sobre {tema}. " * 100
    
    try:
        inputs = tokenizer(f"Escribe un texto largo sobre {tema}", return_tensors="pt", truncation=True)
        
        outputs = model.generate(
            inputs.input_ids,
            max_length=1000,
            do_sample=True,
            temperature=0.7,
            top_k=50,
            num_return_sequences=1,
            pad_token_id=tokenizer.eos_token_id
        )
        
        return tokenizer.decode(outputs[0], skip_special_tokens=True)
    except Exception as e:
        logger.error(f"Error generando texto: {str(e)}")
        return f"Contenido generado sobre {tema}. " * 100

def buscar_videos(tema):
    """Busca videos en Pexels con manejo de errores mejorado"""
    try:
        headers = {"Authorization": PEXELS_API_KEY}
        response = requests.get(
            f"https://api.pexels.com/videos/search?query={tema}&per_page=3",
            headers=headers,
            timeout=10
        )
        return response.json().get("videos", [])[:3]
    except Exception as e:
        logger.error(f"Error buscando videos: {str(e)}")
        return []

def crear_video(prompt, custom_script, voz_seleccionada, musica=None):
    try:
        start_time = time.time()
        
        # 1. Generar guión
        guion = generar_guion(prompt, custom_script)
        logger.info(f"Guion generado ({len(guion)} caracteres)")
        
        # 2. Generar voz
        voz_file = "narracion.mp3"
        subprocess.run([
            'edge-tts',
            '--voice', voz_seleccionada,
            '--text', guion,
            '--write-media', voz_file
        ], check=True)
        
        audio = AudioFileClip(voz_file)
        duracion = audio.duration
        
        # 3. Buscar y descargar videos
        videos = buscar_videos(prompt) or buscar_videos("nature")
        clips = []
        
        for i, video in enumerate(videos):
            try:
                video_file = max(video['video_files'], key=lambda x: x.get('width', 0))
                temp_file = f"temp_vid_{i}.mp4"
                
                with requests.get(video_file['link'], stream=True) as r:
                    r.raise_for_status()
                    with open(temp_file, 'wb') as f:
                        for chunk in r.iter_content(chunk_size=8192):
                            f.write(chunk)
                
                clip = VideoFileClip(temp_file)
                clip = clip.subclip(0, min(10, clip.duration))  # Máximo 10 segundos por clip
                clips.append(clip)
            except Exception as e:
                logger.error(f"Error procesando video {i}: {str(e)}")
        
        # 4. Crear video final
        if not clips:
            final_clip = ColorClip((1280, 720), (0, 0, 0), duration=duracion)
        else:
            final_clip = concatenate_videoclips(clips).set_duration(duracion)
        
        final_clip = final_clip.set_audio(audio)
        
        output_file = f"video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
        final_clip.write_videofile(
            output_file,
            fps=24,
            codec="libx264",
            audio_codec="aac",
            threads=2,
            preset='fast'
        )
        
        logger.info(f"Video creado en {time.time()-start_time:.2f} segundos")
        return output_file
        
    except Exception as e:
        logger.error(f"Error crítico: {str(e)}")
        return None
    finally:
        # Limpieza
        for f in [voz_file, *[f"temp_vid_{i}.mp4" for i in range(3)]]:
            if os.path.exists(f):
                os.remove(f)

# Interfaz simplificada y funcional
with gr.Blocks(title="Generador de Videos") as app:
    with gr.Row():
        with gr.Column():
            tema = gr.Textbox(label="Tema del video")
            guion = gr.TextArea(label="Guion personalizado (opcional)", lines=5)
            voz = gr.Dropdown(label="Voz", choices=VOICES, value=VOICES[0])
            btn = gr.Button("Generar Video")
        
        with gr.Column():
            salida = gr.Video(label="Resultado")

    btn.click(
        fn=crear_video,
        inputs=[tema, guion, voz],
        outputs=salida
    )

if __name__ == "__main__":
    app.launch(
        server_name="0.0.0.0",
        server_port=7860,
        share=False  # Desactivado para evitar problemas
    )