Spaces:
Sleeping
Sleeping
File size: 4,877 Bytes
1f72b0c |
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 |
import os
import math
import tempfile
from pydub import AudioSegment
from moviepy.editor import (
VideoFileClip, AudioFileClip, ImageClip,
concatenate_videoclips, CompositeVideoClip,
concatenate_audioclips
)
import edge_tts
import gradio as gr
import asyncio
# CONSTANTES DE ARCHIVOS
INTRO_VIDEO = "introvideo.mp4"
OUTRO_VIDEO = "outrovideo.mp4"
MUSIC_BG = "musicafondo.mp3"
FX_SOUND = "fxsound.mp3"
WATERMARK = "watermark.png"
# Validar existencia de archivos obligatorios
for file in [INTRO_VIDEO, OUTRO_VIDEO, MUSIC_BG, FX_SOUND, WATERMARK]:
if not os.path.exists(file):
raise FileNotFoundError(f"Falta archivo necesario: {file}")
def cortar_video(video_path, metodo="inteligente", duracion=10):
video = VideoFileClip(video_path)
if metodo == "manual":
return [video.subclip(i*duracion, (i+1)*duracion)
for i in range(math.ceil(video.duration/duracion))]
# Implementaci贸n b谩sica de cortes por voz (requerir铆a VAD real)
clips = []
ultimo_corte = 0
for i in range(1, math.ceil(video.duration)):
if i % 5 == 0: # Simulaci贸n de detecci贸n de pausas
clips.append(video.subclip(ultimo_corte, i))
ultimo_corte = i
return clips
def procesar_audio(texto, voz, clips_duracion):
communicate = edge_tts.Communicate(texto, voz)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
asyncio.run(communicate.save(tmp.name))
tts_audio = AudioFileClip(tmp.name)
# Ajustar TTS a duraci贸n de clips
if tts_audio.duration < clips_duracion:
tts_audio = tts_audio.loop(duration=clips_duracion)
else:
tts_audio = tts_audio.subclip(0, clips_duracion)
# Mezclar con m煤sica de fondo
bg_music = AudioSegment.from_mp3(MUSIC_BG)
if len(bg_music) < clips_duracion*1000:
bg_music = bg_music * math.ceil(clips_duracion*1000 / len(bg_music))
bg_music = bg_music[:clips_duracion*1000].fade_out(3000)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
bg_music.export(tmp.name, format="mp3")
bg_audio = AudioFileClip(tmp.name).volumex(0.10)
return CompositeAudioClip([bg_audio, tts_audio.volumex(0.9)])
def agregar_transiciones(clips):
fx_audio = AudioFileClip(FX_SOUND).set_duration(2.5)
transicion = ImageClip(WATERMARK).set_duration(2.5)
transicion = transicion.resize(height=clips[0].h).set_position(("center", 0.1))
clips_con_fx = []
for i, clip in enumerate(clips):
# Agregar watermark
clip_watermarked = CompositeVideoClip([clip, transicion])
clips_con_fx.append(clip_watermarked)
if i < len(clips)-1:
clips_con_fx.append(
CompositeVideoClip([transicion.set_position("center")])
.set_audio(fx_audio)
)
return concatenate_videoclips(clips_con_fx)
async def procesar_video(
video_input,
texto_tts,
voz_seleccionada,
metodo_corte,
duracion_corte
):
# Procesar video principal
clips = cortar_video(video_input, metodo_corte, duracion_corte)
video_editado = agregar_transiciones(clips)
# Agregar intro/outro
intro = VideoFileClip(INTRO_VIDEO)
outro = VideoFileClip(OUTRO_VIDEO)
video_final = concatenate_videoclips([intro, video_editado, outro])
# Procesar audio
audio_final = procesar_audio(
texto_tts,
voz_seleccionada,
video_editado.duration
)
# Combinar y renderizar
video_final = video_final.set_audio(audio_final)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp:
video_final.write_videofile(tmp.name, codec="libx264", fps=24)
return tmp.name
# Interfaz Gradio
with gr.Blocks() as demo:
gr.Markdown("# Video Editor IA")
with gr.Tab("Principal"):
video_input = gr.Video(label="Subir video")
texto_tts = gr.Textbox(label="Texto para TTS", lines=3)
voz_seleccionada = gr.Dropdown(
label="Seleccionar voz",
choices=["es-ES-AlvaroNeural", "es-MX-BeatrizNeural"]
)
procesar_btn = gr.Button("Generar Video")
video_output = gr.Video(label="Resultado")
with gr.Tab("Ajustes"):
metodo_corte = gr.Radio(
["inteligente", "manual"],
label="M茅todo de cortes",
value="inteligente"
)
duracion_corte = gr.Slider(
1, 60, 10,
label="Segundos por corte (solo manual)"
)
procesar_btn.click(
procesar_video,
inputs=[
video_input,
texto_tts,
voz_seleccionada,
metodo_corte,
duracion_corte
],
outputs=video_output
)
if __name__ == "__main__":
demo.queue().launch() |