gnosticdev commited on
Commit
4a93b3e
verified
1 Parent(s): 7e2dbc1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -60
app.py CHANGED
@@ -13,24 +13,12 @@ import requests
13
  import tempfile
14
  import re
15
  import random
16
- import numpy as np
17
  from google_drive_upload import upload_to_google_drive
18
 
19
  # Define la carpeta de salida
20
  output_folder = "outputs"
21
  os.makedirs(output_folder, exist_ok=True)
22
 
23
- # Crear un video predeterminado si no existe
24
- if not os.path.exists(os.path.join(output_folder, "blank.mp4")):
25
- # Create a black frame
26
- color_clip = ColorClip(size=(1920, 1080), color=[0, 0, 0], duration=1)
27
- color_clip.write_videofile(os.path.join(output_folder, "blank.mp4"), fps=24)
28
-
29
- def clean_text_for_search(text):
30
- """Limpia el texto para hacer b煤squedas v谩lidas en Pixabay"""
31
- text = re.sub(r'[^\w\s]', '', text).strip()
32
- return text
33
-
34
  def resize_and_blur_video(clip, target_aspect_ratio=16/9):
35
  """Redimensiona y aplica desenfoque al fondo del video para mantener el aspecto 16:9."""
36
  try:
@@ -67,9 +55,7 @@ def concatenate_pixabay_videos(keywords, num_videos_per_keyword=1):
67
  """Concatena videos de Pixabay basados en palabras clave."""
68
  keyword_list = [keyword.strip() for keyword in keywords.split(",") if keyword.strip()]
69
  if not keyword_list:
70
- # Si no hay palabras clave, crear un video negro
71
- color_clip = ColorClip(size=(1920, 1080), color=[0, 0, 0], duration=5)
72
- return color_clip
73
 
74
  video_clips = []
75
 
@@ -78,7 +64,7 @@ def concatenate_pixabay_videos(keywords, num_videos_per_keyword=1):
78
  print(f"Buscando videos para la palabra clave '{keyword}'...")
79
  links = search_pixabay(keyword, num_results=num_videos_per_keyword)
80
  if not links:
81
- print(f"No se encontraron videos para la palabra clave '{keyword}'. Usando palabra clave predeterminada 'nature'.")
82
  links = search_pixabay("nature", num_results=num_videos_per_keyword)
83
  if not links:
84
  continue
@@ -86,7 +72,7 @@ def concatenate_pixabay_videos(keywords, num_videos_per_keyword=1):
86
  link = links[0]
87
  video_response = requests.get(link)
88
  if video_response.status_code != 200:
89
- print(f"Error al descargar video desde {link}: C贸digo de estado {video_response.status_code}")
90
  continue
91
 
92
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_video:
@@ -94,15 +80,15 @@ def concatenate_pixabay_videos(keywords, num_videos_per_keyword=1):
94
  clip = VideoFileClip(tmp_video.name)
95
  processed_clip = resize_and_blur_video(clip)
96
  video_clips.append(processed_clip)
 
97
 
98
  except Exception as e:
99
  print(f"Error procesando palabra clave '{keyword}': {e}")
100
  continue
101
 
102
  if not video_clips:
103
- # Si no se encontraron videos, crear un video negro
104
- color_clip = ColorClip(size=(1920, 1080), color=[0, 0, 0], duration=5)
105
- return color_clip
106
 
107
  random.shuffle(video_clips)
108
  return concatenate_videoclips(video_clips, method="compose")
@@ -115,10 +101,8 @@ def adjust_background_music(video_duration, music_file):
115
  repetitions = int(video_duration / music.duration) + 1
116
  music_clips = [music] * repetitions
117
  music = concatenate_audioclips(music_clips)
118
- if music.duration > video_duration:
119
- music = music.subclip(0, video_duration)
120
- music = music.volumex(0.2)
121
- return music
122
  except Exception as e:
123
  print(f"Error ajustando m煤sica: {e}")
124
  return None
@@ -127,69 +111,81 @@ def combine_audio_video(audio_file, video_clip, music_clip=None):
127
  """Combina el audio y el video en un archivo final."""
128
  try:
129
  audio_clip = AudioFileClip(audio_file)
130
- total_duration = audio_clip.duration + 5
131
- if video_clip.duration < total_duration:
132
- video_clip = video_clip.loop(duration=total_duration)
133
- video_clip = video_clip.set_duration(total_duration).fadeout(5)
 
 
 
134
  final_clip = video_clip.set_audio(audio_clip)
135
 
 
136
  if music_clip:
137
- if music_clip.duration < total_duration:
138
- repetitions = int(total_duration / music_clip.duration) + 1
139
- music_clips = [music_clip] * repetitions
140
- music_clip = concatenate_audioclips(music_clips)
141
- if music_clip.duration > total_duration:
142
- music_clip = music_clip.subclip(0, total_duration)
143
- music_clip = music_clip.audio_fadeout(5)
144
  final_clip = final_clip.set_audio(CompositeAudioClip([audio_clip, music_clip]))
145
 
 
146
  output_filename = f"final_video_{int(time.time())}.mp4"
147
  output_path = os.path.join(output_folder, output_filename)
 
 
148
  final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=24)
 
 
 
 
 
 
 
 
149
  return output_path
150
 
151
  except Exception as e:
152
  print(f"Error combinando audio y video: {e}")
153
- return os.path.join(output_folder, "blank.mp4")
 
 
154
 
155
  def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch, keywords):
156
  """Procesa la entrada del usuario y genera el video final."""
157
  try:
 
158
  if text.strip():
159
  final_text = text
160
  elif txt_file is not None:
161
  final_text = txt_file.decode("utf-8")
162
  else:
163
- return os.path.join(output_folder, "blank.mp4")
164
-
165
- voices = asyncio.run(get_voices())
166
- if selected_voice not in voices:
167
- return os.path.join(output_folder, "blank.mp4")
168
 
169
- try:
170
- audio_file = asyncio.run(text_to_speech(final_text, selected_voice, rate, pitch))
171
- except Exception as e:
172
- print(f"Error generando audio: {e}")
173
- return os.path.join(output_folder, "blank.mp4")
174
 
175
- try:
176
- video_clip = concatenate_pixabay_videos(keywords, num_videos_per_keyword=1)
177
- except Exception as e:
178
- print(f"Error concatenando videos: {e}")
179
- return os.path.join(output_folder, "blank.mp4")
180
 
 
 
181
  if mp3_file is not None:
182
  music_clip = adjust_background_music(video_clip.duration, mp3_file.name)
183
- else:
184
- music_clip = None
185
 
 
186
  final_video_path = combine_audio_video(audio_file, video_clip, music_clip)
 
 
 
 
187
  upload_to_google_drive(final_video_path)
 
188
  return final_video_path
189
 
190
  except Exception as e:
191
  print(f"Error durante el procesamiento: {e}")
192
- return os.path.join(output_folder, "blank.mp4")
193
 
194
  # Interfaz Gradio
195
  with gr.Blocks() as demo:
@@ -201,14 +197,14 @@ with gr.Blocks() as demo:
201
  mp3_file_input = gr.File(label="Upload background music (.mp3)", file_types=[".mp3"])
202
  keyword_input = gr.Textbox(
203
  label="Enter keywords separated by commas (e.g., universe, galaxy, forest, cat)",
204
- value="nature" # Valor predeterminado
205
  )
206
  voices = asyncio.run(get_voices())
207
  voice_dropdown = gr.Dropdown(choices=list(voices.keys()), label="Select Voice")
208
  rate_slider = gr.Slider(minimum=-50, maximum=50, value=0, label="Speech Rate Adjustment (%)", step=1)
209
  pitch_slider = gr.Slider(minimum=-20, maximum=20, value=0, label="Pitch Adjustment (Hz)", step=1)
210
  with gr.Column():
211
- output_video = gr.File(label="Download Generated Video")
212
 
213
  btn = gr.Button("Generate Video")
214
  btn.click(
@@ -217,8 +213,5 @@ with gr.Blocks() as demo:
217
  outputs=output_video
218
  )
219
 
220
- if __name__ == "__main__":
221
- # Leer el puerto asignado por Hugging Face
222
- port = int(os.getenv("PORT", 7860))
223
- # Lanzar la aplicaci贸n
224
  demo.launch(server_name="0.0.0.0", server_port=port, share=True)
 
13
  import tempfile
14
  import re
15
  import random
 
16
  from google_drive_upload import upload_to_google_drive
17
 
18
  # Define la carpeta de salida
19
  output_folder = "outputs"
20
  os.makedirs(output_folder, exist_ok=True)
21
 
 
 
 
 
 
 
 
 
 
 
 
22
  def resize_and_blur_video(clip, target_aspect_ratio=16/9):
23
  """Redimensiona y aplica desenfoque al fondo del video para mantener el aspecto 16:9."""
24
  try:
 
55
  """Concatena videos de Pixabay basados en palabras clave."""
56
  keyword_list = [keyword.strip() for keyword in keywords.split(",") if keyword.strip()]
57
  if not keyword_list:
58
+ keyword_list = ["nature"] # Palabra clave por defecto
 
 
59
 
60
  video_clips = []
61
 
 
64
  print(f"Buscando videos para la palabra clave '{keyword}'...")
65
  links = search_pixabay(keyword, num_results=num_videos_per_keyword)
66
  if not links:
67
+ print(f"No se encontraron videos para '{keyword}', probando con 'nature'")
68
  links = search_pixabay("nature", num_results=num_videos_per_keyword)
69
  if not links:
70
  continue
 
72
  link = links[0]
73
  video_response = requests.get(link)
74
  if video_response.status_code != 200:
75
+ print(f"Error al descargar video desde {link}")
76
  continue
77
 
78
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_video:
 
80
  clip = VideoFileClip(tmp_video.name)
81
  processed_clip = resize_and_blur_video(clip)
82
  video_clips.append(processed_clip)
83
+ os.unlink(tmp_video.name) # Limpiamos el archivo temporal
84
 
85
  except Exception as e:
86
  print(f"Error procesando palabra clave '{keyword}': {e}")
87
  continue
88
 
89
  if not video_clips:
90
+ # Si no hay videos, creamos un clip negro de 5 segundos
91
+ return ColorClip(size=(1920, 1080), color=[0, 0, 0], duration=5)
 
92
 
93
  random.shuffle(video_clips)
94
  return concatenate_videoclips(video_clips, method="compose")
 
101
  repetitions = int(video_duration / music.duration) + 1
102
  music_clips = [music] * repetitions
103
  music = concatenate_audioclips(music_clips)
104
+ music = music.subclip(0, video_duration)
105
+ return music.volumex(0.2)
 
 
106
  except Exception as e:
107
  print(f"Error ajustando m煤sica: {e}")
108
  return None
 
111
  """Combina el audio y el video en un archivo final."""
112
  try:
113
  audio_clip = AudioFileClip(audio_file)
114
+ total_duration = audio_clip.duration + 2 # A帽adimos 2 segundos extra
115
+
116
+ # Aseguramos que el video tenga la duraci贸n correcta
117
+ video_clip = video_clip.loop(duration=total_duration)
118
+ video_clip = video_clip.set_duration(total_duration).fadeout(2)
119
+
120
+ # Combinamos el audio principal
121
  final_clip = video_clip.set_audio(audio_clip)
122
 
123
+ # A帽adimos la m煤sica de fondo si existe
124
  if music_clip:
125
+ music_clip = music_clip.set_duration(total_duration).audio_fadeout(2)
 
 
 
 
 
 
126
  final_clip = final_clip.set_audio(CompositeAudioClip([audio_clip, music_clip]))
127
 
128
+ # Generamos el nombre del archivo y la ruta
129
  output_filename = f"final_video_{int(time.time())}.mp4"
130
  output_path = os.path.join(output_folder, output_filename)
131
+
132
+ # Guardamos el video
133
  final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=24)
134
+
135
+ # Limpiamos los clips
136
+ final_clip.close()
137
+ video_clip.close()
138
+ audio_clip.close()
139
+ if music_clip:
140
+ music_clip.close()
141
+
142
  return output_path
143
 
144
  except Exception as e:
145
  print(f"Error combinando audio y video: {e}")
146
+ if 'final_clip' in locals():
147
+ final_clip.close()
148
+ return None
149
 
150
  def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch, keywords):
151
  """Procesa la entrada del usuario y genera el video final."""
152
  try:
153
+ # Determinamos el texto a usar
154
  if text.strip():
155
  final_text = text
156
  elif txt_file is not None:
157
  final_text = txt_file.decode("utf-8")
158
  else:
159
+ raise ValueError("No text input provided")
 
 
 
 
160
 
161
+ # Generamos el audio
162
+ audio_file = asyncio.run(text_to_speech(final_text, selected_voice, rate, pitch))
163
+ if not audio_file:
164
+ raise ValueError("Failed to generate audio")
 
165
 
166
+ # Generamos el video
167
+ video_clip = concatenate_pixabay_videos(keywords, num_videos_per_keyword=1)
168
+ if not video_clip:
169
+ raise ValueError("Failed to generate video")
 
170
 
171
+ # Procesamos la m煤sica de fondo si existe
172
+ music_clip = None
173
  if mp3_file is not None:
174
  music_clip = adjust_background_music(video_clip.duration, mp3_file.name)
 
 
175
 
176
+ # Combinamos todo
177
  final_video_path = combine_audio_video(audio_file, video_clip, music_clip)
178
+ if not final_video_path:
179
+ raise ValueError("Failed to combine audio and video")
180
+
181
+ # Subimos a Google Drive
182
  upload_to_google_drive(final_video_path)
183
+
184
  return final_video_path
185
 
186
  except Exception as e:
187
  print(f"Error durante el procesamiento: {e}")
188
+ return None
189
 
190
  # Interfaz Gradio
191
  with gr.Blocks() as demo:
 
197
  mp3_file_input = gr.File(label="Upload background music (.mp3)", file_types=[".mp3"])
198
  keyword_input = gr.Textbox(
199
  label="Enter keywords separated by commas (e.g., universe, galaxy, forest, cat)",
200
+ value="nature"
201
  )
202
  voices = asyncio.run(get_voices())
203
  voice_dropdown = gr.Dropdown(choices=list(voices.keys()), label="Select Voice")
204
  rate_slider = gr.Slider(minimum=-50, maximum=50, value=0, label="Speech Rate Adjustment (%)", step=1)
205
  pitch_slider = gr.Slider(minimum=-20, maximum=20, value=0, label="Pitch Adjustment (Hz)", step=1)
206
  with gr.Column():
207
+ output_video = gr.Video(label="Generated Video")
208
 
209
  btn = gr.Button("Generate Video")
210
  btn.click(
 
213
  outputs=output_video
214
  )
215
 
216
+ # Lanzar la aplicaci贸n
 
 
 
217
  demo.launch(server_name="0.0.0.0", server_port=port, share=True)