gnosticdev commited on
Commit
a3cb7cc
·
verified ·
1 Parent(s): 6b756c1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -94
app.py CHANGED
@@ -1,4 +1,4 @@
1
- import requests
2
  import gradio as gr
3
  from tts_module import get_voices, text_to_speech
4
  from moviepy.editor import (
@@ -10,6 +10,7 @@ import asyncio
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,7 +21,7 @@ import numpy as np
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,67 +30,74 @@ os.makedirs(temp_dir, exist_ok=True)
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,81 +108,80 @@ def search_google_images(query, num_images=1):
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,14 +196,13 @@ def concatenate_google_images(keywords, clip_duration=5, num_images_per_keyword=
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,31 +216,30 @@ def adjust_background_music(video_duration, 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,7 +247,6 @@ def combine_audio_video(audio_file, video_clip, music_clip=None):
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,17 +275,6 @@ def upload_to_google_drive(file_path, folder_id):
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,25 +283,26 @@ def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch, keyword
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,7 +312,6 @@ def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch, keyword
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,7 +321,7 @@ with gr.Blocks() as demo:
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")
 
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
  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
 
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
 
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
+ else:
85
+ with requests_proxy.ProxyManager(proxies) as proxy_manager:
86
+ result = proxy_manager.get(
87
+ f"https://www.googleapis.com/customsearch/v1",
88
+ params={
89
+ "q": query,
90
+ "cx": cse_id,
91
+ "searchType": "image",
92
+ "num": num_images * 3,
93
+ "safe": 'off',
94
+ "imgSize": 'HUGE',
95
+ "imgType": 'photo',
96
+ "rights": 'cc_publicdomain|cc_attribute|cc_sharealike',
97
+ "key": api_key
98
+ }
99
+ ).json()
100
+
101
  if 'items' in result:
102
  image_urls = []
103
  for item in result.get('items', []):
 
108
  image_urls.append(item['link'])
109
  if len(image_urls) >= num_images:
110
  break
111
+
112
  print(f"Encontradas {len(image_urls)} imágenes de tamaño adecuado")
113
  return image_urls
114
+
115
  print("No se encontraron imágenes después de probar todos los proxies")
116
  return []
117
+
118
  except Exception as e:
119
  print(f"Error general en la búsqueda de imágenes: {str(e)}")
120
  return []
121
 
122
+
123
  def process_image(image):
124
  try:
125
  width, height = image.size
126
  current_ratio = width / height
127
+
128
  if current_ratio > TARGET_ASPECT_RATIO:
129
  new_width = max(MIN_WIDTH, width)
130
  new_height = int(new_width / TARGET_ASPECT_RATIO)
131
  else:
132
  new_height = max(MIN_HEIGHT, height)
133
  new_width = int(new_height * TARGET_ASPECT_RATIO)
134
+
135
  image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
136
  background = Image.new('RGB', (max(new_width, MIN_WIDTH), max(new_height, MIN_HEIGHT)), 'black')
137
+
138
+ offset = ((background.width - image.width) // 2,
139
+ (background.height - image.height) // 2)
140
  background.paste(image, offset)
141
+
142
  return background
143
  except Exception as e:
144
  print(f"Error processing image: {e}")
145
  return None
146
 
 
147
  def download_image(url):
148
  proxies = load_proxies()
149
  if not proxies:
150
  proxies = [None]
151
+
152
  for proxy in proxies:
153
  try:
154
  response = requests.get(url, proxies=proxy, timeout=10)
155
  image = Image.open(BytesIO(response.content))
156
+
157
  if image.mode in ('RGBA', 'LA') or (image.mode == 'P' and 'transparency' in image.info):
158
  background = Image.new('RGB', image.size, (0, 0, 0))
159
  background.paste(image, mask=image.split()[-1])
160
  image = background
161
+
162
  processed_image = process_image(image)
163
  if processed_image:
164
  return processed_image
165
+
166
  except Exception as e:
167
  print(f"Error downloading image with proxy {proxy}: {e}")
168
  continue
169
  return None
170
 
 
171
  def create_animated_clip(image, duration=5, zoom_factor=1.1):
172
  img_array = np.array(image)
173
  img_clip = ImageClip(img_array).set_duration(duration)
174
+
175
  if img_clip.size[0] < MIN_WIDTH or img_clip.size[1] < MIN_HEIGHT:
176
  img_clip = img_clip.resize(width=MIN_WIDTH, height=MIN_HEIGHT)
177
+
178
  return img_clip.resize(lambda t: 1 + (zoom_factor - 1) * t / duration)
179
 
 
180
  def concatenate_google_images(keywords, clip_duration=5, num_images_per_keyword=1):
181
  keyword_list = [keyword.strip() for keyword in keywords.split(",") if keyword.strip()]
182
  if not keyword_list:
183
  keyword_list = ["nature"]
184
+
185
  video_clips = []
186
  for keyword in keyword_list:
187
  try:
 
196
  except Exception as e:
197
  print(f"Error processing keyword '{keyword}': {e}")
198
  continue
199
+
200
  if not video_clips:
201
  return ColorClip(size=(MIN_WIDTH, MIN_HEIGHT), color=[0, 0, 0], duration=5)
202
+
203
  random.shuffle(video_clips)
204
  return concatenate_videoclips(video_clips, method="compose")
205
 
 
206
  def adjust_background_music(video_duration, music_file):
207
  try:
208
  music = AudioFileClip(music_file)
 
216
  print(f"Error adjusting music: {e}")
217
  return None
218
 
 
219
  def combine_audio_video(audio_file, video_clip, music_clip=None):
220
  try:
221
  audio_clip = AudioFileClip(audio_file)
222
  total_duration = audio_clip.duration + 2
223
+
224
  video_clip = video_clip.loop(duration=total_duration)
225
  video_clip = video_clip.set_duration(total_duration).fadeout(2)
226
+
227
  final_clip = video_clip.set_audio(audio_clip)
228
  if music_clip:
229
  music_clip = music_clip.set_duration(total_duration).audio_fadeout(2)
230
  final_clip = final_clip.set_audio(CompositeAudioClip([audio_clip, music_clip]))
231
+
232
  output_filename = f"final_video_{int(time.time())}.mp4"
233
  output_path = os.path.join(output_folder, output_filename)
234
+
235
  final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=24)
236
+
237
  final_clip.close()
238
  video_clip.close()
239
  audio_clip.close()
240
  if music_clip:
241
  music_clip.close()
242
+
243
  return output_path
244
  except Exception as e:
245
  print(f"Error combining audio and video: {e}")
 
247
  final_clip.close()
248
  return None
249
 
 
250
  def upload_to_google_drive(file_path, folder_id):
251
  try:
252
  creds = service_account.Credentials.from_service_account_info(
 
275
  print(f"Error uploading to Google Drive: {e}")
276
  return None
277
 
 
 
 
 
 
 
 
 
 
 
 
278
  def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch, keywords):
279
  try:
280
  if text.strip():
 
283
  final_text = txt_file.decode("utf-8")
284
  else:
285
  raise ValueError("No text input provided")
286
+
287
  audio_file = asyncio.run(text_to_speech(final_text, selected_voice, rate, pitch))
288
  if not audio_file:
289
  raise ValueError("Failed to generate audio")
290
+
291
  video_clip = concatenate_google_images(keywords, clip_duration=5, num_images_per_keyword=1)
292
  if not video_clip:
293
  raise ValueError("Failed to generate video")
294
+
295
  music_clip = None
296
  if mp3_file is not None:
297
  music_clip = adjust_background_music(video_clip.duration, mp3_file.name)
298
+
299
  final_video_path = combine_audio_video(audio_file, video_clip, music_clip)
300
  if not final_video_path:
301
  raise ValueError("Failed to combine audio and video")
302
+
303
  download_link = upload_to_google_drive(final_video_path, folder_id=FOLDER_ID)
304
  if download_link:
305
+ print(f"Video uploaded to Google Drive. Download link: {download_link}")
306
  return f"[Download video]({download_link})"
307
  else:
308
  raise ValueError("Error uploading video to Google Drive")
 
312
  finally:
313
  cleanup_temp_files()
314
 
 
315
  with gr.Blocks() as demo:
316
  gr.Markdown("# Text-to-Video Generator")
317
  with gr.Row():
 
321
  mp3_file_input = gr.File(label="Upload background music (.mp3)", file_types=[".mp3"])
322
  keyword_input = gr.Textbox(
323
  label="Enter keywords separated by commas",
324
+ 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"
325
  )
326
  voices = asyncio.run(get_voices())
327
  voice_dropdown = gr.Dropdown(choices=list(voices.keys()), label="Select Voice")