gnosticdev commited on
Commit
43fcbe8
·
verified ·
1 Parent(s): 78ca651

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -0
app.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ import edge_tts
4
+ import gradio as gr
5
+ from moviepy.editor import *
6
+ from moviepy.editor import AudioFileClip, CompositeVideoClip, concatenate_videoclips, ImageClip, TextClip
7
+ from moviepy.video.fx.all import resize, scroll
8
+ from PIL import Image
9
+ import numpy as np
10
+ import io
11
+ import asyncio
12
+
13
+ # 1. Descargar imágenes/videos de stock (Pexels)
14
+ def get_stock_media(query, is_video=False):
15
+ API_KEY = os.getenv("PEXELS_API_KEY") # Configura esto en HF Secrets
16
+ url = f"https://api.pexels.com/v1/{'videos' if is_video else 'photos'}/search?query={query}&per_page=1"
17
+ headers = {"Authorization": API_KEY}
18
+ response = requests.get(url, headers=headers).json()
19
+ if is_video:
20
+ video_url = response["videos"][0]["video_files"][0]["link"]
21
+ return requests.get(video_url).content
22
+ else:
23
+ image_url = response["photos"][0]["src"]["large"]
24
+ return Image.open(io.BytesIO(requests.get(image_url).content))
25
+
26
+ # 2. Generar voz con Edge TTS (todos los modelos)
27
+ async def generate_voice(text, voice="es-ES-AlvaroNeural", output_path="voice.mp3"):
28
+ communicate = edge_tts.Communicate(text=text, voice=voice)
29
+ await communicate.save(output_path)
30
+
31
+ # 3. Añadir música de fondo (en loop si es necesario)
32
+ def add_background_music(audio_clip, music_path="background.mp3", volume=0.2):
33
+ music = AudioFileClip(music_path).volumex(volume)
34
+ if music.duration < audio_clip.duration:
35
+ music = music.loop(duration=audio_clip.duration)
36
+ return CompositeAudioClip([audio_clip, music.set_start(0)])
37
+
38
+ # 4. Efectos de movimiento/zoom para imágenes
39
+ def apply_effects(clip, zoom_factor=1.1, effect_duration=2):
40
+ return clip.resize(zoom_factor).set_position('center').fx(vfx.scroll, h=100, w=100)
41
+
42
+ # 5. Crear subtítulos dinámicos (karaoke-style)
43
+ def generate_subtitles(text, duration, fontsize=30, color="white", stroke_color="black"):
44
+ words = text.split()
45
+ word_duration = duration / len(words)
46
+ clips = []
47
+ for i, word in enumerate(words):
48
+ txt_clip = TextClip(
49
+ " ".join(words[:i+1]),
50
+ fontsize=fontsize,
51
+ color=color,
52
+ stroke_color=stroke_color,
53
+ font="Arial-Bold",
54
+ ).set_start(i * word_duration).set_duration(word_duration)
55
+ clips.append(txt_clip)
56
+ return concatenate_videoclips(clips).set_position(("center", "bottom"))
57
+
58
+ # 6. Función principal para generar el video
59
+ async def generate_video(script, voice_model, music_file=None):
60
+ clips = []
61
+ for i, scene in enumerate(script):
62
+ # Descargar imagen y generar voz
63
+ img = get_stock_media(scene["prompt"])
64
+ img.save(f"scene_{i}.jpg")
65
+ await generate_voice(scene["text"], voice_model, f"voice_{i}.mp3")
66
+
67
+ # Crear clip con efectos
68
+ audio = AudioFileClip(f"voice_{i}.mp3")
69
+ clip = ImageClip(f"scene_{i}.jpg").set_duration(audio.duration)
70
+ clip = apply_effects(clip) # Efecto de zoom/movimiento
71
+
72
+ # Subtítulos dinámicos
73
+ subtitles = generate_subtitles(scene["text"], audio.duration)
74
+ final_clip = CompositeVideoClip([clip, subtitles]).set_audio(audio)
75
+ clips.append(final_clip)
76
+
77
+ # Unir clips y añadir música
78
+ final_video = concatenate_videoclips(clips)
79
+ if music_file:
80
+ final_video.audio = add_background_music(final_video.audio, music_file.name)
81
+
82
+ # Exportar
83
+ output_path = "final_video.mp4"
84
+ final_video.write_videofile(output_path, fps=24, codec="libx264")
85
+ return output_path
86
+
87
+ # 7. Interfaz Gradio
88
+ def ui(script, voice_model, music_file):
89
+ loop = asyncio.new_event_loop()
90
+ asyncio.set_event_loop(loop)
91
+ output_video = loop.run_until_complete(generate_video(script, voice_model, music_file))
92
+ return output_video
93
+
94
+ # Lista de voces Edge TTS (ejemplo)
95
+ voices = ["es-ES-AlvaroNeural", "es-MX-DaliaNeural", "en-US-JennyNeural", "fr-FR-HenriNeural"]
96
+
97
+ # Diseño de la interfaz
98
+ with gr.Blocks() as demo:
99
+ gr.Markdown("## 🎬 Generador de Videos con IA (100% Gratis)")
100
+ with gr.Row():
101
+ script_input = gr.Textbox(label="Script (JSON)", placeholder='[{"prompt": "futuristic city", "text": "Texto aquí..."}]')
102
+ voice_dropdown = gr.Dropdown(choices=voices, label="Voz Edge TTS", value="es-ES-AlvaroNeural")
103
+ music_upload = gr.File(label="Música de fondo (opcional)", type="file")
104
+ generate_btn = gr.Button("Generar Video")
105
+ output_video = gr.Video(label="Video Generado")
106
+
107
+ generate_btn.click(
108
+ fn=ui,
109
+ inputs=[script_input, voice_dropdown, music_upload],
110
+ outputs=output_video,
111
+ )
112
+
113
+ demo.launch()