gnosticdev commited on
Commit
1829fd6
verified
1 Parent(s): aa61beb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +88 -72
app.py CHANGED
@@ -2,85 +2,101 @@ import os
2
  import gradio as gr
3
  import requests
4
  import tempfile
5
- import logging
6
- from datetime import datetime
7
-
8
- import edge_tts
9
- import nest_asyncio
10
  import asyncio
11
-
 
 
 
 
 
12
  from transformers import pipeline
13
- from moviepy.editor import AudioFileClip, VideoFileClip, concatenate_videoclips
14
 
15
  nest_asyncio.apply()
16
 
17
- PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")
18
- logger = logging.getLogger(__name__)
19
-
20
- # Carga modelo
21
- generator = pipeline("text-generation", model="DeepESP/gpt2-spanish")
22
-
23
- # Cargar voces
24
- loop = asyncio.get_event_loop()
25
- VOCES = loop.run_until_complete(edge_tts.list_voices())
26
- VOICE_NAMES = [f"{v['Name']} ({v['Gender']})" for v in VOCES]
27
-
28
- def generar_guion(prompt):
29
- prompt_text = f"Escribe un guion profesional de YouTube sobre '{prompt}':\n"
30
- res = generator(prompt_text, max_new_tokens=300)[0]['generated_text']
31
- return res.strip()
32
-
33
- def buscar_videos(prompt, max_videos=3):
34
- headers = {"Authorization": PEXELS_API_KEY}
35
- r = requests.get(f"https://api.pexels.com/videos/search?query={prompt}&per_page={max_videos}", headers=headers)
36
- return r.json().get("videos", [])
37
-
38
- def crear_video(prompt, voz_nombre):
 
 
 
 
 
39
  try:
40
- idx = VOICE_NAMES.index(voz_nombre)
41
- except:
42
- idx = 0
43
-
44
- voz_short = VOCES[idx]['ShortName']
45
- guion = generar_guion(prompt)
46
-
47
- # Guardar voz
48
- tts = edge_tts.Communicate(guion, voz_short)
49
- voz_path = "voz.mp3"
50
- loop.run_until_complete(tts.save(voz_path))
51
-
52
- audio_clip = AudioFileClip(voz_path)
53
- duracion = audio_clip.duration
54
-
55
- # Descargar videos
56
- videos = buscar_videos(prompt)
57
- clips = []
58
- for v in videos:
59
- url = v['video_files'][0]['link']
60
- tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
61
- r = requests.get(url, stream=True)
62
- for c in r.iter_content(1024*1024):
63
- tmp.write(c)
64
- tmp.close()
65
- clip = VideoFileClip(tmp.name).subclip(0, min(v['duration'], duracion / len(videos)))
66
- clips.append(clip)
67
-
68
- final = concatenate_videoclips(clips).set_audio(audio_clip)
69
- salida = f"video_{datetime.now().strftime('%H%M%S')}.mp4"
70
- final.write_videofile(salida, fps=24)
71
-
72
- return salida
73
-
74
- def run(prompt, voz):
75
- return crear_video(prompt, voz)
76
-
77
- with gr.Blocks() as app:
78
- entrada = gr.Textbox(label="Tema del video")
79
- voz = gr.Dropdown(VOICE_NAMES, label="Voz", value=VOICE_NAMES[0])
80
- boton = gr.Button("Generar Video")
 
 
 
 
 
 
 
 
 
81
  salida = gr.Video(label="Resultado")
82
 
83
- boton.click(fn=run, inputs=[entrada, voz], outputs=salida)
 
 
84
 
85
  if __name__ == "__main__":
86
- app.launch(server_name="0.0.0.0", server_port=7860)
 
2
  import gradio as gr
3
  import requests
4
  import tempfile
 
 
 
 
 
5
  import asyncio
6
+ import edge_tts
7
+ from datetime import datetime
8
+ from moviepy.editor import (
9
+ VideoFileClip, AudioFileClip,
10
+ concatenate_videoclips, CompositeAudioClip, afx
11
+ )
12
  from transformers import pipeline
13
+ import nest_asyncio
14
 
15
  nest_asyncio.apply()
16
 
17
+ # Generador de texto
18
+ generador = pipeline("text-generation", model="gpt2")
19
+
20
+ # Obtener voces disponibles
21
+ async def get_voices():
22
+ voices = await edge_tts.list_voices()
23
+ return voices
24
+
25
+ VOICES = asyncio.run(get_voices())
26
+ VOICE_OPTIONS = [
27
+ f"{v['Name']} ({v['Gender']}, {v['Locale']})" for v in VOICES
28
+ ]
29
+ VOICE_MAP = {v['Name']: v['ShortName'] for v in VOICES}
30
+
31
+ # Mock de videos
32
+ def buscar_videos_mock():
33
+ return [
34
+ "https://samplelib.com/lib/preview/mp4/sample-5s.mp4",
35
+ "https://samplelib.com/lib/preview/mp4/sample-10s.mp4"
36
+ ]
37
+
38
+ # Mock de m煤sica
39
+ def buscar_musica_mock():
40
+ return "https://samplelib.com/lib/preview/mp3/sample-3s.mp3"
41
+
42
+ # Funci贸n principal
43
+ async def generar_video(prompt, voz_str):
44
  try:
45
+ # 1. Texto largo
46
+ texto = generador(prompt, max_length=300, do_sample=True)[0]['generated_text']
47
+
48
+ # 2. Voz
49
+ voz_id = voz_str.split(" ")[0]
50
+ short_name = VOICE_MAP.get(voz_id, "es-ES-ElviraNeural")
51
+ voz_path = "voz.mp3"
52
+ await edge_tts.Communicate(text=texto, voice=short_name).save(voz_path)
53
+ voz_clip = AudioFileClip(voz_path)
54
+
55
+ # 3. Videos
56
+ video_urls = buscar_videos_mock()
57
+ clips = []
58
+ for url in video_urls:
59
+ r = requests.get(url, stream=True)
60
+ with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as f:
61
+ for chunk in r.iter_content(1024 * 1024):
62
+ f.write(chunk)
63
+ f.flush()
64
+ clips.append(VideoFileClip(f.name).subclip(0, 5))
65
+
66
+ video = concatenate_videoclips(clips).set_audio(voz_clip)
67
+
68
+ # 4. M煤sica (loop)
69
+ music_url = buscar_musica_mock()
70
+ r = requests.get(music_url, stream=True)
71
+ with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as f:
72
+ for chunk in r.iter_content(1024 * 1024):
73
+ f.write(chunk)
74
+ f.flush()
75
+ music_clip = AudioFileClip(f.name)
76
+ music_loop = afx.audio_loop(music_clip, duration=video.duration).volumex(0.3)
77
+
78
+ # 5. Composici贸n de audio
79
+ final_audio = CompositeAudioClip([video.audio, music_loop])
80
+ video = video.set_audio(final_audio)
81
+
82
+ # 6. Guardar
83
+ output_path = f"video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
84
+ video.write_videofile(output_path, fps=24)
85
+
86
+ return output_path
87
+ except Exception as e:
88
+ return f"Error: {e}"
89
+
90
+ # Interfaz Gradio
91
+ with gr.Blocks() as demo:
92
+ prompt = gr.Textbox(label="Prompt", placeholder="Escribe un tema...")
93
+ voz_dropdown = gr.Dropdown(VOICE_OPTIONS, label="Voz", value=VOICE_OPTIONS[0])
94
+ btn = gr.Button("Generar video")
95
  salida = gr.Video(label="Resultado")
96
 
97
+ btn.click(fn=lambda p, v: asyncio.run(generar_video(p, v)),
98
+ inputs=[prompt, voz_dropdown],
99
+ outputs=salida)
100
 
101
  if __name__ == "__main__":
102
+ demo.launch(server_name="0.0.0.0", server_port=7860)