codelion commited on
Commit
ffe3b64
·
verified ·
1 Parent(s): ebfbf2f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -30
app.py CHANGED
@@ -9,6 +9,10 @@ import json
9
  import random
10
  import urllib.parse
11
  import time
 
 
 
 
12
 
13
  # Initialize the Google Generative AI client with the API key from environment variables
14
  try:
@@ -79,6 +83,7 @@ def clean_response_text(response_text):
79
  """
80
  Clean the API response by removing Markdown code block markers.
81
  """
 
82
  cleaned_text = response_text.strip()
83
  if cleaned_text.startswith("```json"):
84
  cleaned_text = cleaned_text[len("```json"):].strip()
@@ -90,6 +95,7 @@ def generate_ideas(user_input):
90
  """
91
  Generate a diverse set of ideas based on the user's input concept using the LLM.
92
  """
 
93
  prompt = f"""
94
  The user has provided the concept: "{user_input}". You must generate 5 diverse and creative ideas for a TikTok video that are directly and explicitly related to "{user_input}".
95
  Each idea must clearly incorporate and focus on the core theme of "{user_input}" without deviating into unrelated topics.
@@ -106,15 +112,17 @@ def generate_ideas(user_input):
106
  safety_settings=SAFETY_SETTINGS
107
  )
108
  )
 
109
  if not response.text or response.text.isspace():
110
  raise ValueError("Empty response from API")
111
  cleaned_text = clean_response_text(response.text)
112
  response_json = json.loads(cleaned_text)
113
  if 'ideas' not in response_json or not isinstance(response_json['ideas'], list) or len(response_json['ideas']) != 5:
114
  raise ValueError("Invalid JSON format: 'ideas' key missing, not a list, or incorrect length")
 
115
  return response_json['ideas']
116
  except Exception as e:
117
- print(f"Error generating ideas: {e}")
118
  return [
119
  f"A dramatic {user_input} scene with cinematic lighting",
120
  f"A close-up of {user_input} in a futuristic setting",
@@ -128,12 +136,15 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
128
  Generate a single feed item with progress updates.
129
  Yields progress stage and message for UI updates.
130
  """
 
131
  video_base64 = None
132
  max_total_attempts = 3
133
-
 
134
  total_attempts = 0
135
  while total_attempts < max_total_attempts:
136
  total_attempts += 1
 
137
 
138
  yield {"stage": "initializing", "message": random.choice(PROGRESS_STAGES["initializing"]), "progress": 10}
139
 
@@ -143,6 +154,7 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
143
  image_prompt = None
144
 
145
  for image_attempt in range(max_retries):
 
146
  yield {"stage": "creating_image", "message": random.choice(PROGRESS_STAGES["creating_image"]), "progress": 30 + (image_attempt * 10)}
147
 
148
  selected_idea = random.choice(ideas)
@@ -155,6 +167,7 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
155
  Ensure the response is strictly in JSON format.
156
  """
157
  try:
 
158
  response = client.models.generate_content(
159
  model='gemini-2.0-flash-lite',
160
  contents=[prompt],
@@ -163,16 +176,20 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
163
  safety_settings=SAFETY_SETTINGS
164
  )
165
  )
 
 
 
166
  cleaned_text = clean_response_text(response.text)
167
  response_json = json.loads(cleaned_text)
168
  text = response_json['caption']
169
  image_prompt = response_json['image_prompt']
170
  except Exception as e:
171
- print(f"Error generating item: {e}")
172
  text = f"Amazing {user_input}! 🔥 #{user_input.replace(' ', '')}"
173
  image_prompt = f"A vivid scene of {selected_idea} related to {user_input}, in a vibrant pop art style, no text or letters"
174
 
175
  try:
 
176
  imagen = client.models.generate_images(
177
  model='imagen-3.0-generate-002',
178
  prompt=image_prompt,
@@ -181,6 +198,8 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
181
  number_of_images=1
182
  )
183
  )
 
 
184
  if imagen.generated_images and len(imagen.generated_images) > 0:
185
  generated_image = imagen.generated_images[0]
186
  image = Image.open(BytesIO(generated_image.image.image_bytes))
@@ -190,42 +209,43 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
190
  buffered = BytesIO()
191
  image.save(buffered, format="PNG")
192
  img_str = base64.b64encode(buffered.getvalue()).decode()
 
193
  break
194
  else:
195
- if image_attempt == max_retries - 1:
196
- if total_attempts == max_total_attempts:
197
- image = Image.new('RGB', (360, 640), color='gray')
198
- buffered = BytesIO()
199
- image.save(buffered, format="PNG")
200
- img_str = base64.b64encode(buffered.getvalue()).decode()
201
- yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
202
- return {
203
- 'text': text,
204
- 'image_base64': img_str,
205
- 'video_base64': None,
206
- 'ideas': ideas
207
- }
208
- break
209
- yield {"stage": "retrying_image", "message": random.choice(PROGRESS_STAGES["retrying_image"]), "progress": 40 + (image_attempt * 10)}
210
- except Exception as e:
211
- print(f"Error generating image: {e}")
212
- if image_attempt == max_retries - 1:
213
- if total_attempts == max_total_attempts:
214
  image = Image.new('RGB', (360, 640), color='gray')
215
  buffered = BytesIO()
216
  image.save(buffered, format="PNG")
217
  img_str = base64.b64encode(buffered.getvalue()).decode()
218
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
 
219
  return {
220
  'text': text,
221
  'image_base64': img_str,
222
  'video_base64': None,
223
  'ideas': ideas
224
  }
225
- break
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  yield {"stage": "retrying_image", "message": random.choice(PROGRESS_STAGES["retrying_image"]), "progress": 40 + (image_attempt * 10)}
227
 
228
  if generate_video and generated_image is not None:
 
229
  yield {"stage": "generating_video", "message": random.choice(PROGRESS_STAGES["generating_video"]), "progress": 70}
230
  try:
231
  video_prompt = f"""
@@ -233,6 +253,7 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
233
  Use a close-up shot with a slow dolly shot circling around the subject,
234
  using shallow focus on the main subject to emphasize details, in a realistic style with cinematic lighting.
235
  """
 
236
  operation = client.models.generate_videos(
237
  model="veo-2.0-generate-001",
238
  prompt=video_prompt,
@@ -245,7 +266,9 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
245
  )
246
  )
247
  while not operation.done:
248
- time.sleep(20)
 
 
249
  operation = client.operations.get(operation)
250
  if operation.error:
251
  raise ValueError(f"Video generation failed: {operation.error.message}")
@@ -257,6 +280,7 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
257
  video_bytes = video_data if isinstance(video_data, bytes) else BytesIO(video_data).getvalue()
258
  video_base64 = base64.b64encode(video_bytes).decode()
259
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
 
260
  return {
261
  'text': text,
262
  'image_base64': img_str,
@@ -267,9 +291,11 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
267
  else:
268
  raise ValueError("Video generation operation failed: No generated_videos in response")
269
  except Exception as e:
270
- print(f"Error generating video: {e}")
 
271
  yield {"stage": "generating_video", "message": random.choice(PROGRESS_STAGES["generating_video"]), "progress": 80}
272
  try:
 
273
  operation = client.models.generate_videos(
274
  model="veo-2.0-generate-001",
275
  prompt=video_prompt,
@@ -281,7 +307,9 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
281
  )
282
  )
283
  while not operation.done:
284
- time.sleep(20)
 
 
285
  operation = client.operations.get(operation)
286
  if operation.error:
287
  raise ValueError(f"Video generation failed: {operation.error.message}")
@@ -293,6 +321,7 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
293
  video_bytes = video_data if isinstance(video_data, bytes) else BytesIO(video_data).getvalue()
294
  video_base64 = base64.b64encode(video_bytes).decode()
295
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
 
296
  return {
297
  'text': text,
298
  'image_base64': img_str,
@@ -303,9 +332,10 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
303
  else:
304
  raise ValueError("Video generation operation failed: No generated_videos in response")
305
  except Exception as e:
306
- print(f"Error generating text-to-video: {e}")
307
  if total_attempts == max_total_attempts:
308
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
 
309
  return {
310
  'text': text,
311
  'image_base64': img_str,
@@ -315,6 +345,7 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
315
 
316
  if img_str is not None:
317
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
 
318
  return {
319
  'text': text,
320
  'image_base64': img_str,
@@ -327,6 +358,7 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
327
  image.save(buffered, format="PNG")
328
  img_str = base64.b64encode(buffered.getvalue()).decode()
329
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
 
330
  return {
331
  'text': f"Amazing {user_input}! 🔥 #{user_input.replace(' ', '')}",
332
  'image_base64': img_str,
@@ -338,6 +370,7 @@ def start_feed(user_input, generate_video, current_index, feed_items):
338
  """
339
  Start or update the feed based on the user input with progress updates.
340
  """
 
341
  if not user_input.strip():
342
  user_input = "trending"
343
  current_user_input = user_input
@@ -354,6 +387,7 @@ def start_feed(user_input, generate_video, current_index, feed_items):
354
 
355
  item_generator = generate_item(user_input, ideas, generate_video=generate_video)
356
  for progress in item_generator:
 
357
  if isinstance(progress, dict) and "stage" in progress:
358
  html_content = generate_html([], False, 0, user_input, is_loading, progress["stage"], progress["message"], progress["progress"])
359
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
@@ -364,10 +398,11 @@ def start_feed(user_input, generate_video, current_index, feed_items):
364
  share_links = generate_share_links(item['image_base64'], item['video_base64'], item['text'])
365
  is_loading = False
366
  html_content = generate_html(feed_items, False, current_index, user_input, is_loading)
 
367
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
368
  return
369
  except Exception as e:
370
- print(f"Error in start_feed: {e}")
371
  html_content = """
372
  <div style="
373
  display: flex;
@@ -394,6 +429,7 @@ def load_next(user_input, generate_video, current_index, feed_items):
394
  """
395
  Load the next item in the feed with progress updates.
396
  """
 
397
  current_user_input = user_input if user_input.strip() else "trending"
398
  user_input = current_user_input
399
  is_loading = True
@@ -412,6 +448,7 @@ def load_next(user_input, generate_video, current_index, feed_items):
412
  feed_items[current_index]['video_base64'],
413
  feed_items[current_index]['text']
414
  )
 
415
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
416
  return
417
  else:
@@ -421,6 +458,7 @@ def load_next(user_input, generate_video, current_index, feed_items):
421
 
422
  item_generator = generate_item(user_input, ideas, generate_video=generate_video)
423
  for progress in item_generator:
 
424
  if isinstance(progress, dict) and "stage" in progress:
425
  html_content = generate_html(feed_items, False, current_index, user_input, is_loading, progress["stage"], progress["message"], progress["progress"])
426
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
@@ -435,10 +473,11 @@ def load_next(user_input, generate_video, current_index, feed_items):
435
  feed_items[current_index]['video_base64'],
436
  feed_items[current_index]['text']
437
  )
 
438
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
439
  return
440
  except Exception as e:
441
- print(f"Error in load_next: {e}")
442
  html_content = """
443
  <div style="
444
  display: flex;
@@ -465,6 +504,7 @@ def load_previous(user_input, generate_video, current_index, feed_items):
465
  """
466
  Load the previous item in the feed.
467
  """
 
468
  current_user_input = user_input if user_input.strip() else "trending"
469
 
470
  if current_index > 0:
@@ -475,12 +515,14 @@ def load_previous(user_input, generate_video, current_index, feed_items):
475
  feed_items[current_index]['video_base64'],
476
  feed_items[current_index]['text']
477
  )
 
478
  return current_user_input, current_index, feed_items, html_content, share_links, False
479
 
480
  def generate_share_links(image_base64, video_base64, caption):
481
  """
482
  Generate share links for social media platforms with download links for image and video.
483
  """
 
484
  image_data_url = f"data:image/png;base64,{image_base64}"
485
  encoded_caption = urllib.parse.quote(caption)
486
 
@@ -623,6 +665,7 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_inpu
623
  """
624
  Generate an HTML string to display the current feed item or a loading screen with a progress bar.
625
  """
 
626
  if is_loading:
627
  progress_percent = max(0, min(100, progress_percent))
628
  return f"""
@@ -692,6 +735,7 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_inpu
692
  """
693
 
694
  if not feed_items or current_index >= len(feed_items):
 
695
  return """
696
  <div style="
697
  display: flex;
@@ -788,6 +832,7 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_inpu
788
  }}
789
  </script>
790
  """
 
791
  return html_str
792
 
793
  # Define the Gradio interface
@@ -821,7 +866,7 @@ with gr.Blocks(
821
  label="Generate Video (may take longer)",
822
  value=False
823
  )
824
- magic_button = gr.Button("✨ Create ✨", elem_classes="gr-button")
825
 
826
  feed_html = gr.HTML()
827
  share_html = gr.HTML(label="Share this item:")
 
9
  import random
10
  import urllib.parse
11
  import time
12
+ import logging
13
+
14
+ # Set up logging
15
+ logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
16
 
17
  # Initialize the Google Generative AI client with the API key from environment variables
18
  try:
 
83
  """
84
  Clean the API response by removing Markdown code block markers.
85
  """
86
+ logging.debug("Cleaning response text")
87
  cleaned_text = response_text.strip()
88
  if cleaned_text.startswith("```json"):
89
  cleaned_text = cleaned_text[len("```json"):].strip()
 
95
  """
96
  Generate a diverse set of ideas based on the user's input concept using the LLM.
97
  """
98
+ logging.debug(f"Generating ideas for input: {user_input}")
99
  prompt = f"""
100
  The user has provided the concept: "{user_input}". You must generate 5 diverse and creative ideas for a TikTok video that are directly and explicitly related to "{user_input}".
101
  Each idea must clearly incorporate and focus on the core theme of "{user_input}" without deviating into unrelated topics.
 
112
  safety_settings=SAFETY_SETTINGS
113
  )
114
  )
115
+ logging.debug(f"Generate ideas response: {response.text}")
116
  if not response.text or response.text.isspace():
117
  raise ValueError("Empty response from API")
118
  cleaned_text = clean_response_text(response.text)
119
  response_json = json.loads(cleaned_text)
120
  if 'ideas' not in response_json or not isinstance(response_json['ideas'], list) or len(response_json['ideas']) != 5:
121
  raise ValueError("Invalid JSON format: 'ideas' key missing, not a list, or incorrect length")
122
+ logging.debug(f"Generated ideas: {response_json['ideas']}")
123
  return response_json['ideas']
124
  except Exception as e:
125
+ logging.error(f"Error generating ideas: {e}")
126
  return [
127
  f"A dramatic {user_input} scene with cinematic lighting",
128
  f"A close-up of {user_input} in a futuristic setting",
 
136
  Generate a single feed item with progress updates.
137
  Yields progress stage and message for UI updates.
138
  """
139
+ logging.debug("Starting generate_item")
140
  video_base64 = None
141
  max_total_attempts = 3
142
+ timeout_seconds = 60 # Timeout for API calls
143
+
144
  total_attempts = 0
145
  while total_attempts < max_total_attempts:
146
  total_attempts += 1
147
+ logging.debug(f"Total attempt {total_attempts}")
148
 
149
  yield {"stage": "initializing", "message": random.choice(PROGRESS_STAGES["initializing"]), "progress": 10}
150
 
 
154
  image_prompt = None
155
 
156
  for image_attempt in range(max_retries):
157
+ logging.debug(f"Image attempt {image_attempt + 1}")
158
  yield {"stage": "creating_image", "message": random.choice(PROGRESS_STAGES["creating_image"]), "progress": 30 + (image_attempt * 10)}
159
 
160
  selected_idea = random.choice(ideas)
 
167
  Ensure the response is strictly in JSON format.
168
  """
169
  try:
170
+ start_time = time.time()
171
  response = client.models.generate_content(
172
  model='gemini-2.0-flash-lite',
173
  contents=[prompt],
 
176
  safety_settings=SAFETY_SETTINGS
177
  )
178
  )
179
+ if time.time() - start_time > timeout_seconds:
180
+ raise TimeoutError("Image caption generation timed out")
181
+ logging.debug(f"Generate content response: {response.text}")
182
  cleaned_text = clean_response_text(response.text)
183
  response_json = json.loads(cleaned_text)
184
  text = response_json['caption']
185
  image_prompt = response_json['image_prompt']
186
  except Exception as e:
187
+ logging.error(f"Error generating item: {e}")
188
  text = f"Amazing {user_input}! 🔥 #{user_input.replace(' ', '')}"
189
  image_prompt = f"A vivid scene of {selected_idea} related to {user_input}, in a vibrant pop art style, no text or letters"
190
 
191
  try:
192
+ start_time = time.time()
193
  imagen = client.models.generate_images(
194
  model='imagen-3.0-generate-002',
195
  prompt=image_prompt,
 
198
  number_of_images=1
199
  )
200
  )
201
+ if time.time() - start_time > timeout_seconds:
202
+ raise TimeoutError("Image generation timed out")
203
  if imagen.generated_images and len(imagen.generated_images) > 0:
204
  generated_image = imagen.generated_images[0]
205
  image = Image.open(BytesIO(generated_image.image.image_bytes))
 
209
  buffered = BytesIO()
210
  image.save(buffered, format="PNG")
211
  img_str = base64.b64encode(buffered.getvalue()).decode()
212
+ logging.debug("Image generated successfully")
213
  break
214
  else:
215
+ logging.warning("No images generated")
216
+ if image_attempt == max_retries - 1 and total_attempts == max_total_attempts:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  image = Image.new('RGB', (360, 640), color='gray')
218
  buffered = BytesIO()
219
  image.save(buffered, format="PNG")
220
  img_str = base64.b64encode(buffered.getvalue()).decode()
221
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
222
+ logging.debug("Returning with placeholder image")
223
  return {
224
  'text': text,
225
  'image_base64': img_str,
226
  'video_base64': None,
227
  'ideas': ideas
228
  }
229
+ yield {"stage": "retrying_image", "message": random.choice(PROGRESS_STAGES["retrying_image"]), "progress": 40 + (image_attempt * 10)}
230
+ except Exception as e:
231
+ logging.error(f"Error generating image: {e}")
232
+ if image_attempt == max_retries - 1 and total_attempts == max_total_attempts:
233
+ image = Image.new('RGB', (360, 640), color='gray')
234
+ buffered = BytesIO()
235
+ image.save(buffered, format="PNG")
236
+ img_str = base64.b64encode(buffered.getvalue()).decode()
237
+ yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
238
+ logging.debug("Returning with placeholder image")
239
+ return {
240
+ 'text': text,
241
+ 'image_base64': img_str,
242
+ 'video_base64': None,
243
+ 'ideas': ideas
244
+ }
245
  yield {"stage": "retrying_image", "message": random.choice(PROGRESS_STAGES["retrying_image"]), "progress": 40 + (image_attempt * 10)}
246
 
247
  if generate_video and generated_image is not None:
248
+ logging.debug("Attempting video generation")
249
  yield {"stage": "generating_video", "message": random.choice(PROGRESS_STAGES["generating_video"]), "progress": 70}
250
  try:
251
  video_prompt = f"""
 
253
  Use a close-up shot with a slow dolly shot circling around the subject,
254
  using shallow focus on the main subject to emphasize details, in a realistic style with cinematic lighting.
255
  """
256
+ start_time = time.time()
257
  operation = client.models.generate_videos(
258
  model="veo-2.0-generate-001",
259
  prompt=video_prompt,
 
266
  )
267
  )
268
  while not operation.done:
269
+ if time.time() - start_time > timeout_seconds:
270
+ raise TimeoutError("Video generation timed out")
271
+ time.sleep(5) # Reduced polling interval
272
  operation = client.operations.get(operation)
273
  if operation.error:
274
  raise ValueError(f"Video generation failed: {operation.error.message}")
 
280
  video_bytes = video_data if isinstance(video_data, bytes) else BytesIO(video_data).getvalue()
281
  video_base64 = base64.b64encode(video_bytes).decode()
282
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
283
+ logging.debug("Video generated successfully")
284
  return {
285
  'text': text,
286
  'image_base64': img_str,
 
291
  else:
292
  raise ValueError("Video generation operation failed: No generated_videos in response")
293
  except Exception as e:
294
+ logging.error(f"Error generating video: {e}")
295
+ logging.debug("Falling back to text-to-video")
296
  yield {"stage": "generating_video", "message": random.choice(PROGRESS_STAGES["generating_video"]), "progress": 80}
297
  try:
298
+ start_time = time.time()
299
  operation = client.models.generate_videos(
300
  model="veo-2.0-generate-001",
301
  prompt=video_prompt,
 
307
  )
308
  )
309
  while not operation.done:
310
+ if time.time() - start_time > timeout_seconds:
311
+ raise TimeoutError("Text-to-video generation timed out")
312
+ time.sleep(5)
313
  operation = client.operations.get(operation)
314
  if operation.error:
315
  raise ValueError(f"Video generation failed: {operation.error.message}")
 
321
  video_bytes = video_data if isinstance(video_data, bytes) else BytesIO(video_data).getvalue()
322
  video_base64 = base64.b64encode(video_bytes).decode()
323
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
324
+ logging.debug("Text-to-video generated successfully")
325
  return {
326
  'text': text,
327
  'image_base64': img_str,
 
332
  else:
333
  raise ValueError("Video generation operation failed: No generated_videos in response")
334
  except Exception as e:
335
+ logging.error(f"Error generating text-to-video: {e}")
336
  if total_attempts == max_total_attempts:
337
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
338
+ logging.debug("Returning without video")
339
  return {
340
  'text': text,
341
  'image_base64': img_str,
 
345
 
346
  if img_str is not None:
347
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
348
+ logging.debug("Returning with image only")
349
  return {
350
  'text': text,
351
  'image_base64': img_str,
 
358
  image.save(buffered, format="PNG")
359
  img_str = base64.b64encode(buffered.getvalue()).decode()
360
  yield {"stage": "finalizing", "message": random.choice(PROGRESS_STAGES["finalizing"]), "progress": 90}
361
+ logging.debug("Returning with placeholder image")
362
  return {
363
  'text': f"Amazing {user_input}! 🔥 #{user_input.replace(' ', '')}",
364
  'image_base64': img_str,
 
370
  """
371
  Start or update the feed based on the user input with progress updates.
372
  """
373
+ logging.debug("Starting start_feed")
374
  if not user_input.strip():
375
  user_input = "trending"
376
  current_user_input = user_input
 
387
 
388
  item_generator = generate_item(user_input, ideas, generate_video=generate_video)
389
  for progress in item_generator:
390
+ logging.debug(f"Progress update: {progress}")
391
  if isinstance(progress, dict) and "stage" in progress:
392
  html_content = generate_html([], False, 0, user_input, is_loading, progress["stage"], progress["message"], progress["progress"])
393
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
 
398
  share_links = generate_share_links(item['image_base64'], item['video_base64'], item['text'])
399
  is_loading = False
400
  html_content = generate_html(feed_items, False, current_index, user_input, is_loading)
401
+ logging.debug("Feed generation complete")
402
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
403
  return
404
  except Exception as e:
405
+ logging.error(f"Error in start_feed: {e}")
406
  html_content = """
407
  <div style="
408
  display: flex;
 
429
  """
430
  Load the next item in the feed with progress updates.
431
  """
432
+ logging.debug("Starting load_next")
433
  current_user_input = user_input if user_input.strip() else "trending"
434
  user_input = current_user_input
435
  is_loading = True
 
448
  feed_items[current_index]['video_base64'],
449
  feed_items[current_index]['text']
450
  )
451
+ logging.debug("Loaded existing feed item")
452
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
453
  return
454
  else:
 
458
 
459
  item_generator = generate_item(user_input, ideas, generate_video=generate_video)
460
  for progress in item_generator:
461
+ logging.debug(f"Progress update: {progress}")
462
  if isinstance(progress, dict) and "stage" in progress:
463
  html_content = generate_html(feed_items, False, current_index, user_input, is_loading, progress["stage"], progress["message"], progress["progress"])
464
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
 
473
  feed_items[current_index]['video_base64'],
474
  feed_items[current_index]['text']
475
  )
476
+ logging.debug("New feed item generated")
477
  yield current_user_input, current_index, feed_items, html_content, share_links, is_loading
478
  return
479
  except Exception as e:
480
+ logging.error(f"Error in load_next: {e}")
481
  html_content = """
482
  <div style="
483
  display: flex;
 
504
  """
505
  Load the previous item in the feed.
506
  """
507
+ logging.debug("Loading previous item")
508
  current_user_input = user_input if user_input.strip() else "trending"
509
 
510
  if current_index > 0:
 
515
  feed_items[current_index]['video_base64'],
516
  feed_items[current_index]['text']
517
  )
518
+ logging.debug("Previous item loaded")
519
  return current_user_input, current_index, feed_items, html_content, share_links, False
520
 
521
  def generate_share_links(image_base64, video_base64, caption):
522
  """
523
  Generate share links for social media platforms with download links for image and video.
524
  """
525
+ logging.debug("Generating share links")
526
  image_data_url = f"data:image/png;base64,{image_base64}"
527
  encoded_caption = urllib.parse.quote(caption)
528
 
 
665
  """
666
  Generate an HTML string to display the current feed item or a loading screen with a progress bar.
667
  """
668
+ logging.debug(f"Generating HTML, is_loading: {is_loading}, progress_stage: {progress_stage}")
669
  if is_loading:
670
  progress_percent = max(0, min(100, progress_percent))
671
  return f"""
 
735
  """
736
 
737
  if not feed_items or current_index >= len(feed_items):
738
+ logging.debug("No feed items to display")
739
  return """
740
  <div style="
741
  display: flex;
 
832
  }}
833
  </script>
834
  """
835
+ logging.debug("Feed item HTML generated")
836
  return html_str
837
 
838
  # Define the Gradio interface
 
866
  label="Generate Video (may take longer)",
867
  value=False
868
  )
869
+ magic_button = gr.Button("✨Create✨", elem_classes="gr-button")
870
 
871
  feed_html = gr.HTML()
872
  share_html = gr.HTML(label="Share this item:")