gnosticdev commited on
Commit
0dbf4ff
·
verified ·
1 Parent(s): 49d54e5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +95 -71
app.py CHANGED
@@ -1,4 +1,4 @@
1
- import requests_proxy
2
  import gradio as gr
3
  from tts_module import get_voices, text_to_speech
4
  from moviepy.editor import (
@@ -10,7 +10,6 @@ import asyncio
10
  import os
11
  import json
12
  import time
13
- import requests
14
  import random
15
  from googleapiclient.discovery import build
16
  from google.oauth2 import service_account
@@ -21,7 +20,7 @@ import numpy as np
21
 
22
  MIN_WIDTH = 1920
23
  MIN_HEIGHT = 1080
24
- TARGET_ASPECT_RATIO = 16/9
25
 
26
  output_folder = "outputs"
27
  temp_dir = "temp_files"
@@ -30,58 +29,67 @@ os.makedirs(temp_dir, exist_ok=True)
30
 
31
  FOLDER_ID = "12S6adpanAXjf71pKKGRRPqpzbJa5XEh3"
32
 
 
33
  def load_proxies(proxy_file="proxys.txt"):
34
  try:
35
  with open(proxy_file, 'r') as f:
36
  proxies = [line.strip() for line in f if line.strip()]
37
  print(f"Loaded {len(proxies)} proxies from file")
38
- return [requests_proxy.ProxyInfo(proxy=f"http://{proxy}") for proxy in proxies]
39
  except Exception as e:
40
  print(f"Error loading proxies: {e}")
41
  return []
42
-
 
43
  def search_google_images(query, num_images=1):
44
  try:
45
  api_key = os.getenv('GOOGLE_API_KEY')
46
  cse_id = os.getenv('GOOGLE_CSE_ID')
47
  proxies = load_proxies()
48
-
49
  print(f"Buscando imágenes para: {query}")
50
-
51
- if not proxies:
52
- print("No proxies available, trying without proxy")
53
- with requests.Session() as session:
54
- result = session.get(
55
- f"https://www.googleapis.com/customsearch/v1",
56
- params={
57
- "q": query,
58
- "cx": cse_id,
59
- "searchType": "image",
60
- "num": num_images * 3,
61
- "safe": 'off',
62
- "imgSize": 'LARGE',
63
- "imgType": 'imgTypeUndefined',
64
- "rights": 'cc_publicdomain|cc_attribute|cc_sharealike',
65
- "key": api_key
66
- }
67
- ).json()
 
 
 
 
 
 
 
68
  else:
69
- with requests_proxy.ProxyManager(proxies) as proxy_manager:
70
- result = proxy_manager.get(
71
- f"https://www.googleapis.com/customsearch/v1",
72
- params={
73
- "q": query,
74
- "cx": cse_id,
75
- "searchType": "image",
76
- "num": num_images * 3,
77
- "safe": 'off',
78
- "imgSize": 'LARGE',
79
- "imgType": 'imgTypeUndefined',
80
- "rights": 'cc_publicdomain|cc_attribute|cc_sharealike',
81
- "key": api_key
82
- }
83
- ).json()
84
-
85
  if 'items' in result:
86
  image_urls = []
87
  for item in result.get('items', []):
@@ -92,79 +100,81 @@ def search_google_images(query, num_images=1):
92
  image_urls.append(item['link'])
93
  if len(image_urls) >= num_images:
94
  break
95
-
96
  print(f"Encontradas {len(image_urls)} imágenes de tamaño adecuado")
97
  return image_urls
98
-
99
  print("No se encontraron imágenes después de probar todos los proxies")
100
  return []
101
-
102
  except Exception as e:
103
  print(f"Error general en la búsqueda de imágenes: {str(e)}")
104
  return []
105
 
 
106
  def process_image(image):
107
  try:
108
  width, height = image.size
109
  current_ratio = width / height
110
-
111
  if current_ratio > TARGET_ASPECT_RATIO:
112
  new_width = max(MIN_WIDTH, width)
113
  new_height = int(new_width / TARGET_ASPECT_RATIO)
114
  else:
115
  new_height = max(MIN_HEIGHT, height)
116
  new_width = int(new_height * TARGET_ASPECT_RATIO)
117
-
118
  image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
119
  background = Image.new('RGB', (max(new_width, MIN_WIDTH), max(new_height, MIN_HEIGHT)), 'black')
120
-
121
- offset = ((background.width - image.width) // 2,
122
- (background.height - image.height) // 2)
123
  background.paste(image, offset)
124
-
125
  return background
126
  except Exception as e:
127
  print(f"Error processing image: {e}")
128
  return None
129
 
 
130
  def download_image(url):
131
  proxies = load_proxies()
132
  if not proxies:
133
  proxies = [None]
134
-
135
  for proxy in proxies:
136
  try:
137
  response = requests.get(url, proxies=proxy, timeout=10)
138
  image = Image.open(BytesIO(response.content))
139
-
140
  if image.mode in ('RGBA', 'LA') or (image.mode == 'P' and 'transparency' in image.info):
141
  background = Image.new('RGB', image.size, (0, 0, 0))
142
  background.paste(image, mask=image.split()[-1])
143
  image = background
144
-
145
  processed_image = process_image(image)
146
  if processed_image:
147
  return processed_image
148
-
149
  except Exception as e:
150
  print(f"Error downloading image with proxy {proxy}: {e}")
151
  continue
152
  return None
153
 
 
154
  def create_animated_clip(image, duration=5, zoom_factor=1.1):
155
  img_array = np.array(image)
156
  img_clip = ImageClip(img_array).set_duration(duration)
157
-
158
  if img_clip.size[0] < MIN_WIDTH or img_clip.size[1] < MIN_HEIGHT:
159
  img_clip = img_clip.resize(width=MIN_WIDTH, height=MIN_HEIGHT)
160
-
161
  return img_clip.resize(lambda t: 1 + (zoom_factor - 1) * t / duration)
162
 
 
163
  def concatenate_google_images(keywords, clip_duration=5, num_images_per_keyword=1):
164
  keyword_list = [keyword.strip() for keyword in keywords.split(",") if keyword.strip()]
165
  if not keyword_list:
166
  keyword_list = ["nature"]
167
-
168
  video_clips = []
169
  for keyword in keyword_list:
170
  try:
@@ -179,13 +189,14 @@ def concatenate_google_images(keywords, clip_duration=5, num_images_per_keyword=
179
  except Exception as e:
180
  print(f"Error processing keyword '{keyword}': {e}")
181
  continue
182
-
183
  if not video_clips:
184
  return ColorClip(size=(MIN_WIDTH, MIN_HEIGHT), color=[0, 0, 0], duration=5)
185
-
186
  random.shuffle(video_clips)
187
  return concatenate_videoclips(video_clips, method="compose")
188
 
 
189
  def adjust_background_music(video_duration, music_file):
190
  try:
191
  music = AudioFileClip(music_file)
@@ -199,30 +210,31 @@ def adjust_background_music(video_duration, music_file):
199
  print(f"Error adjusting music: {e}")
200
  return None
201
 
 
202
  def combine_audio_video(audio_file, video_clip, music_clip=None):
203
  try:
204
  audio_clip = AudioFileClip(audio_file)
205
  total_duration = audio_clip.duration + 2
206
-
207
  video_clip = video_clip.loop(duration=total_duration)
208
  video_clip = video_clip.set_duration(total_duration).fadeout(2)
209
-
210
  final_clip = video_clip.set_audio(audio_clip)
211
  if music_clip:
212
  music_clip = music_clip.set_duration(total_duration).audio_fadeout(2)
213
  final_clip = final_clip.set_audio(CompositeAudioClip([audio_clip, music_clip]))
214
-
215
  output_filename = f"final_video_{int(time.time())}.mp4"
216
  output_path = os.path.join(output_folder, output_filename)
217
-
218
  final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=24)
219
-
220
  final_clip.close()
221
  video_clip.close()
222
  audio_clip.close()
223
  if music_clip:
224
  music_clip.close()
225
-
226
  return output_path
227
  except Exception as e:
228
  print(f"Error combining audio and video: {e}")
@@ -230,6 +242,7 @@ def combine_audio_video(audio_file, video_clip, music_clip=None):
230
  final_clip.close()
231
  return None
232
 
 
233
  def upload_to_google_drive(file_path, folder_id):
234
  try:
235
  creds = service_account.Credentials.from_service_account_info(
@@ -258,6 +271,17 @@ def upload_to_google_drive(file_path, folder_id):
258
  print(f"Error uploading to Google Drive: {e}")
259
  return None
260
 
 
 
 
 
 
 
 
 
 
 
 
261
  def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch, keywords):
262
  try:
263
  if text.strip():
@@ -266,26 +290,25 @@ def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch, keyword
266
  final_text = txt_file.decode("utf-8")
267
  else:
268
  raise ValueError("No text input provided")
269
-
270
  audio_file = asyncio.run(text_to_speech(final_text, selected_voice, rate, pitch))
271
  if not audio_file:
272
  raise ValueError("Failed to generate audio")
273
-
274
  video_clip = concatenate_google_images(keywords, clip_duration=5, num_images_per_keyword=1)
275
  if not video_clip:
276
  raise ValueError("Failed to generate video")
277
-
278
  music_clip = None
279
  if mp3_file is not None:
280
  music_clip = adjust_background_music(video_clip.duration, mp3_file.name)
281
-
282
  final_video_path = combine_audio_video(audio_file, video_clip, music_clip)
283
  if not final_video_path:
284
  raise ValueError("Failed to combine audio and video")
285
-
286
  download_link = upload_to_google_drive(final_video_path, folder_id=FOLDER_ID)
287
  if download_link:
288
- print(f"Video uploaded to Google Drive. Download link: {download_link}")
289
  return f"[Download video]({download_link})"
290
  else:
291
  raise ValueError("Error uploading video to Google Drive")
@@ -295,6 +318,7 @@ def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch, keyword
295
  finally:
296
  cleanup_temp_files()
297
 
 
298
  with gr.Blocks() as demo:
299
  gr.Markdown("# Text-to-Video Generator")
300
  with gr.Row():
@@ -304,7 +328,7 @@ with gr.Blocks() as demo:
304
  mp3_file_input = gr.File(label="Upload background music (.mp3)", file_types=[".mp3"])
305
  keyword_input = gr.Textbox(
306
  label="Enter keywords separated by commas",
307
- value="fear, religion, god, demons, aliens, possession, galaxy, mysterious, dystopian, astral, warfare, space, space, galaxy, moon, fear, astral, god, evil, mystery, cosmos, stars, paranormal, inexplicable, hidden, enigma, unknown, unusual, intriguing, curious, strange, supernatural, esoteric, arcane, occultism, supernatural, mystery, phenomenon, rare, unusual, enigmatic, sinister, gloomy, dark, shadowy, macabre, eerie, chilling, cursed, fantastic, unreal, unknown, mysterious, enigmatic, inexplicable, unusual, strange, unusual, arcane, esoteric, hidden, shadowy, dark, gloomy, sinister, macabre, eerie, chilling, cursed, fantastic, unreal, paranormal, supernatural, occultism, phenomenon, rare, intriguing, curious"
308
  )
309
  voices = asyncio.run(get_voices())
310
  voice_dropdown = gr.Dropdown(choices=list(voices.keys()), label="Select Voice")
 
1
+ import requests
2
  import gradio as gr
3
  from tts_module import get_voices, text_to_speech
4
  from moviepy.editor import (
 
10
  import os
11
  import json
12
  import time
 
13
  import random
14
  from googleapiclient.discovery import build
15
  from google.oauth2 import service_account
 
20
 
21
  MIN_WIDTH = 1920
22
  MIN_HEIGHT = 1080
23
+ TARGET_ASPECT_RATIO = 16 / 9
24
 
25
  output_folder = "outputs"
26
  temp_dir = "temp_files"
 
29
 
30
  FOLDER_ID = "12S6adpanAXjf71pKKGRRPqpzbJa5XEh3"
31
 
32
+ # Función para cargar proxies desde un archivo
33
  def load_proxies(proxy_file="proxys.txt"):
34
  try:
35
  with open(proxy_file, 'r') as f:
36
  proxies = [line.strip() for line in f if line.strip()]
37
  print(f"Loaded {len(proxies)} proxies from file")
38
+ return [{"http": f"http://{proxy}", "https": f"http://{proxy}"} for proxy in proxies]
39
  except Exception as e:
40
  print(f"Error loading proxies: {e}")
41
  return []
42
+
43
+ # Función para buscar imágenes en Google Custom Search API
44
  def search_google_images(query, num_images=1):
45
  try:
46
  api_key = os.getenv('GOOGLE_API_KEY')
47
  cse_id = os.getenv('GOOGLE_CSE_ID')
48
  proxies = load_proxies()
49
+
50
  print(f"Buscando imágenes para: {query}")
51
+
52
+ # Intenta con proxies si están disponibles
53
+ if proxies:
54
+ for proxy in proxies:
55
+ try:
56
+ print(f"Trying with proxy: {proxy['http']}")
57
+ result = requests.get(
58
+ "https://www.googleapis.com/customsearch/v1",
59
+ params={
60
+ "q": query,
61
+ "cx": cse_id,
62
+ "searchType": "image",
63
+ "num": num_images * 3,
64
+ "safe": "off",
65
+ "imgSize": "LARGE",
66
+ "rights": "cc_publicdomain|cc_attribute|cc_sharealike",
67
+ "key": api_key
68
+ },
69
+ proxies=proxy,
70
+ timeout=10
71
+ ).json()
72
+ break # Sale del bucle si la solicitud es exitosa
73
+ except Exception as e:
74
+ print(f"Error using proxy {proxy['http']}: {e}")
75
+ continue
76
  else:
77
+ print("No proxies available, trying without proxy")
78
+ result = requests.get(
79
+ "https://www.googleapis.com/customsearch/v1",
80
+ params={
81
+ "q": query,
82
+ "cx": cse_id,
83
+ "searchType": "image",
84
+ "num": num_images * 3,
85
+ "safe": "off",
86
+ "imgSize": "LARGE",
87
+ "rights": "cc_publicdomain|cc_attribute|cc_sharealike",
88
+ "key": api_key
89
+ },
90
+ timeout=10
91
+ ).json()
92
+
93
  if 'items' in result:
94
  image_urls = []
95
  for item in result.get('items', []):
 
100
  image_urls.append(item['link'])
101
  if len(image_urls) >= num_images:
102
  break
103
+
104
  print(f"Encontradas {len(image_urls)} imágenes de tamaño adecuado")
105
  return image_urls
106
+
107
  print("No se encontraron imágenes después de probar todos los proxies")
108
  return []
109
+
110
  except Exception as e:
111
  print(f"Error general en la búsqueda de imágenes: {str(e)}")
112
  return []
113
 
114
+ # Procesa una imagen para ajustar su tamaño
115
  def process_image(image):
116
  try:
117
  width, height = image.size
118
  current_ratio = width / height
119
+
120
  if current_ratio > TARGET_ASPECT_RATIO:
121
  new_width = max(MIN_WIDTH, width)
122
  new_height = int(new_width / TARGET_ASPECT_RATIO)
123
  else:
124
  new_height = max(MIN_HEIGHT, height)
125
  new_width = int(new_height * TARGET_ASPECT_RATIO)
126
+
127
  image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
128
  background = Image.new('RGB', (max(new_width, MIN_WIDTH), max(new_height, MIN_HEIGHT)), 'black')
129
+
130
+ offset = ((background.width - image.width) // 2, (background.height - image.height) // 2)
 
131
  background.paste(image, offset)
132
+
133
  return background
134
  except Exception as e:
135
  print(f"Error processing image: {e}")
136
  return None
137
 
138
+ # Descarga una imagen desde una URL
139
  def download_image(url):
140
  proxies = load_proxies()
141
  if not proxies:
142
  proxies = [None]
143
+
144
  for proxy in proxies:
145
  try:
146
  response = requests.get(url, proxies=proxy, timeout=10)
147
  image = Image.open(BytesIO(response.content))
148
+
149
  if image.mode in ('RGBA', 'LA') or (image.mode == 'P' and 'transparency' in image.info):
150
  background = Image.new('RGB', image.size, (0, 0, 0))
151
  background.paste(image, mask=image.split()[-1])
152
  image = background
153
+
154
  processed_image = process_image(image)
155
  if processed_image:
156
  return processed_image
 
157
  except Exception as e:
158
  print(f"Error downloading image with proxy {proxy}: {e}")
159
  continue
160
  return None
161
 
162
+ # Crea un clip animado a partir de una imagen
163
  def create_animated_clip(image, duration=5, zoom_factor=1.1):
164
  img_array = np.array(image)
165
  img_clip = ImageClip(img_array).set_duration(duration)
166
+
167
  if img_clip.size[0] < MIN_WIDTH or img_clip.size[1] < MIN_HEIGHT:
168
  img_clip = img_clip.resize(width=MIN_WIDTH, height=MIN_HEIGHT)
169
+
170
  return img_clip.resize(lambda t: 1 + (zoom_factor - 1) * t / duration)
171
 
172
+ # Concatena clips de video basados en palabras clave
173
  def concatenate_google_images(keywords, clip_duration=5, num_images_per_keyword=1):
174
  keyword_list = [keyword.strip() for keyword in keywords.split(",") if keyword.strip()]
175
  if not keyword_list:
176
  keyword_list = ["nature"]
177
+
178
  video_clips = []
179
  for keyword in keyword_list:
180
  try:
 
189
  except Exception as e:
190
  print(f"Error processing keyword '{keyword}': {e}")
191
  continue
192
+
193
  if not video_clips:
194
  return ColorClip(size=(MIN_WIDTH, MIN_HEIGHT), color=[0, 0, 0], duration=5)
195
+
196
  random.shuffle(video_clips)
197
  return concatenate_videoclips(video_clips, method="compose")
198
 
199
+ # Ajusta la música de fondo para que coincida con la duración del video
200
  def adjust_background_music(video_duration, music_file):
201
  try:
202
  music = AudioFileClip(music_file)
 
210
  print(f"Error adjusting music: {e}")
211
  return None
212
 
213
+ # Combina audio y video en un solo archivo
214
  def combine_audio_video(audio_file, video_clip, music_clip=None):
215
  try:
216
  audio_clip = AudioFileClip(audio_file)
217
  total_duration = audio_clip.duration + 2
218
+
219
  video_clip = video_clip.loop(duration=total_duration)
220
  video_clip = video_clip.set_duration(total_duration).fadeout(2)
221
+
222
  final_clip = video_clip.set_audio(audio_clip)
223
  if music_clip:
224
  music_clip = music_clip.set_duration(total_duration).audio_fadeout(2)
225
  final_clip = final_clip.set_audio(CompositeAudioClip([audio_clip, music_clip]))
226
+
227
  output_filename = f"final_video_{int(time.time())}.mp4"
228
  output_path = os.path.join(output_folder, output_filename)
229
+
230
  final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=24)
231
+
232
  final_clip.close()
233
  video_clip.close()
234
  audio_clip.close()
235
  if music_clip:
236
  music_clip.close()
237
+
238
  return output_path
239
  except Exception as e:
240
  print(f"Error combining audio and video: {e}")
 
242
  final_clip.close()
243
  return None
244
 
245
+ # Sube un archivo al Google Drive
246
  def upload_to_google_drive(file_path, folder_id):
247
  try:
248
  creds = service_account.Credentials.from_service_account_info(
 
271
  print(f"Error uploading to Google Drive: {e}")
272
  return None
273
 
274
+ # Limpia archivos temporales
275
+ def cleanup_temp_files():
276
+ try:
277
+ if os.path.exists(temp_dir) and os.path.isdir(temp_dir):
278
+ shutil.rmtree(temp_dir)
279
+ os.makedirs(temp_dir, exist_ok=True)
280
+ print("Temporal files cleaned up successfully.")
281
+ except Exception as e:
282
+ print(f"Error cleaning up temporary files: {e}")
283
+
284
+ # Procesa la entrada del usuario y genera el video
285
  def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch, keywords):
286
  try:
287
  if text.strip():
 
290
  final_text = txt_file.decode("utf-8")
291
  else:
292
  raise ValueError("No text input provided")
293
+
294
  audio_file = asyncio.run(text_to_speech(final_text, selected_voice, rate, pitch))
295
  if not audio_file:
296
  raise ValueError("Failed to generate audio")
297
+
298
  video_clip = concatenate_google_images(keywords, clip_duration=5, num_images_per_keyword=1)
299
  if not video_clip:
300
  raise ValueError("Failed to generate video")
301
+
302
  music_clip = None
303
  if mp3_file is not None:
304
  music_clip = adjust_background_music(video_clip.duration, mp3_file.name)
305
+
306
  final_video_path = combine_audio_video(audio_file, video_clip, music_clip)
307
  if not final_video_path:
308
  raise ValueError("Failed to combine audio and video")
309
+
310
  download_link = upload_to_google_drive(final_video_path, folder_id=FOLDER_ID)
311
  if download_link:
 
312
  return f"[Download video]({download_link})"
313
  else:
314
  raise ValueError("Error uploading video to Google Drive")
 
318
  finally:
319
  cleanup_temp_files()
320
 
321
+ # Interfaz Gradio
322
  with gr.Blocks() as demo:
323
  gr.Markdown("# Text-to-Video Generator")
324
  with gr.Row():
 
328
  mp3_file_input = gr.File(label="Upload background music (.mp3)", file_types=[".mp3"])
329
  keyword_input = gr.Textbox(
330
  label="Enter keywords separated by commas",
331
+ value="nature, landscape, city, people"
332
  )
333
  voices = asyncio.run(get_voices())
334
  voice_dropdown = gr.Dropdown(choices=list(voices.keys()), label="Select Voice")