codelion commited on
Commit
fae6e99
·
verified ·
1 Parent(s): 4f86d21

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -54
app.py CHANGED
@@ -41,7 +41,6 @@ def generate_ideas(tag):
41
  ideas = response_json['ideas']
42
  return ideas
43
  except (json.JSONDecodeError, KeyError):
44
- # Fallback ideas if parsing fails
45
  return [
46
  f"A vibrant {tag} scene at sunset",
47
  f"A close-up of {tag} with neon lights",
@@ -61,10 +60,7 @@ def generate_item(tag, ideas):
61
  Returns:
62
  dict: A dictionary with 'text' (str) and 'image_base64' (str).
63
  """
64
- # Select a random idea for diversity
65
  selected_idea = random.choice(ideas)
66
-
67
- # Second LLM call to generate the precise image prompt and caption
68
  prompt = f"""
69
  Based on the idea "{selected_idea}", create content for a TikTok video about {tag}.
70
  Return a JSON object with two keys:
@@ -83,11 +79,9 @@ def generate_item(tag, ideas):
83
  text = response_json['caption']
84
  image_prompt = response_json['image_prompt']
85
  except (json.JSONDecodeError, KeyError):
86
- # Fallback if parsing fails
87
  text = f"Obsessed with {tag}! 🔥 #{tag}"
88
  image_prompt = f"A vivid scene of {selected_idea}, in a vibrant pop art style, no text or letters"
89
 
90
- # Generate the image using the precise prompt
91
  image_response = client.models.generate_images(
92
  model='imagen-3.0-generate-002',
93
  prompt=image_prompt,
@@ -98,15 +92,12 @@ def generate_item(tag, ideas):
98
  )
99
  )
100
 
101
- # Check if images were generated
102
  if image_response.generated_images and len(image_response.generated_images) > 0:
103
  generated_image = image_response.generated_images[0]
104
  image = Image.open(BytesIO(generated_image.image.image_bytes))
105
  else:
106
- # Fallback to a placeholder image
107
  image = Image.new('RGB', (360, 640), color='gray')
108
 
109
- # Convert the image to base64
110
  buffered = BytesIO()
111
  image.save(buffered, format="PNG")
112
  img_str = base64.b64encode(buffered.getvalue()).decode()
@@ -129,20 +120,16 @@ def start_feed(tag, current_index, feed_items, is_loading):
129
  if not tag.strip():
130
  tag = "trending"
131
 
132
- # Set loading state to True
133
  is_loading = True
134
- yield tag, current_index, feed_items, generate_html([], False, 0), is_loading
135
 
136
- # Generate new ideas for the tag
137
  ideas = generate_ideas(tag)
138
- # Generate the first item
139
  item = generate_item(tag, ideas)
140
- feed_items = [item] # Reset feed with the new item
141
  current_index = 0
142
 
143
- # Set loading state to False
144
  is_loading = False
145
- return tag, current_index, feed_items, generate_html(feed_items, False, current_index), is_loading
146
 
147
  def load_next(tag, current_index, feed_items, is_loading):
148
  """
@@ -157,23 +144,19 @@ def load_next(tag, current_index, feed_items, is_loading):
157
  Returns:
158
  tuple: (current_tag, current_index, feed_items, html_content, is_loading)
159
  """
160
- # Set loading state to True
161
  is_loading = True
162
- yield tag, current_index, feed_items, generate_html(feed_items, False, current_index), is_loading
163
 
164
- # If there’s a next item, show it; otherwise, generate a new one
165
  if current_index + 1 < len(feed_items):
166
  current_index += 1
167
  else:
168
- # Use the ideas from the last item to generate a new one
169
  ideas = feed_items[-1]['ideas'] if feed_items else generate_ideas(tag)
170
  new_item = generate_item(tag, ideas)
171
  feed_items.append(new_item)
172
  current_index = len(feed_items) - 1
173
 
174
- # Set loading state to False
175
  is_loading = False
176
- return tag, current_index, feed_items, generate_html(feed_items, False, current_index), is_loading
177
 
178
  def load_previous(tag, current_index, feed_items, is_loading):
179
  """
@@ -190,9 +173,9 @@ def load_previous(tag, current_index, feed_items, is_loading):
190
  """
191
  if current_index > 0:
192
  current_index -= 1
193
- return tag, current_index, feed_items, generate_html(feed_items, False, current_index), is_loading
194
 
195
- def generate_html(feed_items, scroll_to_latest=False, current_index=0):
196
  """
197
  Generate an HTML string to display the current feed item with click navigation.
198
 
@@ -200,10 +183,81 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0):
200
  feed_items (list): List of dictionaries containing 'text' and 'image_base64'.
201
  scroll_to_latest (bool): Whether to auto-scroll to the latest item (not used here).
202
  current_index (int): The index of the item to display.
 
 
203
 
204
  Returns:
205
  str: HTML string representing the feed.
206
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  if not feed_items or current_index >= len(feed_items):
208
  return """
209
  <div style="
@@ -279,10 +333,8 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0):
279
  const clickX = event.clientX - rect.left;
280
  const width = rect.width;
281
  if (clickX > width * 0.75) {{
282
- // Click on the right 25% to go to previous
283
  document.getElementById('previous-button').click();
284
  }} else {{
285
- // Click anywhere else to go to next
286
  document.getElementById('next-button').click();
287
  }}
288
  }}
@@ -300,7 +352,6 @@ with gr.Blocks(
300
  .gradio-container { max-width: 400px; margin: 0 auto; padding: 10px; }
301
  input, select { border-radius: 5px; background-color: #222; color: #fff; border: 1px solid #444; }
302
  .gr-form { background-color: #111; padding: 15px; border-radius: 10px; }
303
- .gr-progress { background-color: #ff2d55; }
304
  """,
305
  title="TikTok-Style Infinite Feed"
306
  ) as demo:
@@ -323,18 +374,9 @@ with gr.Blocks(
323
  label="Or Enter a Custom Tag",
324
  value="food",
325
  placeholder="e.g., sushi, adventure",
326
- submit_btn=False # Disable default submit button
327
  )
328
 
329
- # Progress bar
330
- progress_bar = gr.Slider(
331
- minimum=0,
332
- maximum=1,
333
- value=0,
334
- label="Loading Feed...",
335
- visible=False
336
- )
337
-
338
  # Output display
339
  feed_html = gr.HTML()
340
 
@@ -343,10 +385,6 @@ with gr.Blocks(
343
  """Update the tag input when a suggested tag is selected and start the feed."""
344
  return selected_tag
345
 
346
- def update_progress(is_loading):
347
- """Show or hide the progress bar based on loading state."""
348
- return gr.update(visible=is_loading, value=0 if is_loading else 1)
349
-
350
  # Handle dropdown selection
351
  suggested_tags.change(
352
  fn=set_tag,
@@ -356,10 +394,6 @@ with gr.Blocks(
356
  fn=start_feed,
357
  inputs=[tag_input, current_index, feed_items, is_loading],
358
  outputs=[current_tag, current_index, feed_items, feed_html, is_loading]
359
- ).then(
360
- fn=update_progress,
361
- inputs=is_loading,
362
- outputs=progress_bar
363
  )
364
 
365
  # Handle Enter keypress in the custom tag input
@@ -367,13 +401,9 @@ with gr.Blocks(
367
  fn=start_feed,
368
  inputs=[tag_input, current_index, feed_items, is_loading],
369
  outputs=[current_tag, current_index, feed_items, feed_html, is_loading]
370
- ).then(
371
- fn=update_progress,
372
- inputs=is_loading,
373
- outputs=progress_bar
374
  )
375
 
376
- # Hidden buttons for navigation
377
  next_button = gr.Button("Next", elem_id="next-button", visible=False)
378
  previous_button = gr.Button("Previous", elem_id="previous-button", visible=False)
379
 
@@ -382,10 +412,6 @@ with gr.Blocks(
382
  fn=load_next,
383
  inputs=[current_tag, current_index, feed_items, is_loading],
384
  outputs=[current_tag, current_index, feed_items, feed_html, is_loading]
385
- ).then(
386
- fn=update_progress,
387
- inputs=is_loading,
388
- outputs=progress_bar
389
  )
390
 
391
  # Handle click to go to previous item
 
41
  ideas = response_json['ideas']
42
  return ideas
43
  except (json.JSONDecodeError, KeyError):
 
44
  return [
45
  f"A vibrant {tag} scene at sunset",
46
  f"A close-up of {tag} with neon lights",
 
60
  Returns:
61
  dict: A dictionary with 'text' (str) and 'image_base64' (str).
62
  """
 
63
  selected_idea = random.choice(ideas)
 
 
64
  prompt = f"""
65
  Based on the idea "{selected_idea}", create content for a TikTok video about {tag}.
66
  Return a JSON object with two keys:
 
79
  text = response_json['caption']
80
  image_prompt = response_json['image_prompt']
81
  except (json.JSONDecodeError, KeyError):
 
82
  text = f"Obsessed with {tag}! 🔥 #{tag}"
83
  image_prompt = f"A vivid scene of {selected_idea}, in a vibrant pop art style, no text or letters"
84
 
 
85
  image_response = client.models.generate_images(
86
  model='imagen-3.0-generate-002',
87
  prompt=image_prompt,
 
92
  )
93
  )
94
 
 
95
  if image_response.generated_images and len(image_response.generated_images) > 0:
96
  generated_image = image_response.generated_images[0]
97
  image = Image.open(BytesIO(generated_image.image.image_bytes))
98
  else:
 
99
  image = Image.new('RGB', (360, 640), color='gray')
100
 
 
101
  buffered = BytesIO()
102
  image.save(buffered, format="PNG")
103
  img_str = base64.b64encode(buffered.getvalue()).decode()
 
120
  if not tag.strip():
121
  tag = "trending"
122
 
 
123
  is_loading = True
124
+ yield tag, current_index, feed_items, generate_html([], False, 0, tag, is_loading), is_loading
125
 
 
126
  ideas = generate_ideas(tag)
 
127
  item = generate_item(tag, ideas)
128
+ feed_items = [item]
129
  current_index = 0
130
 
 
131
  is_loading = False
132
+ return tag, current_index, feed_items, generate_html(feed_items, False, current_index, tag, is_loading), is_loading
133
 
134
  def load_next(tag, current_index, feed_items, is_loading):
135
  """
 
144
  Returns:
145
  tuple: (current_tag, current_index, feed_items, html_content, is_loading)
146
  """
 
147
  is_loading = True
148
+ yield tag, current_index, feed_items, generate_html(feed_items, False, current_index, tag, is_loading), is_loading
149
 
 
150
  if current_index + 1 < len(feed_items):
151
  current_index += 1
152
  else:
 
153
  ideas = feed_items[-1]['ideas'] if feed_items else generate_ideas(tag)
154
  new_item = generate_item(tag, ideas)
155
  feed_items.append(new_item)
156
  current_index = len(feed_items) - 1
157
 
 
158
  is_loading = False
159
+ return tag, current_index, feed_items, generate_html(feed_items, False, current_index, tag, is_loading), is_loading
160
 
161
  def load_previous(tag, current_index, feed_items, is_loading):
162
  """
 
173
  """
174
  if current_index > 0:
175
  current_index -= 1
176
+ return tag, current_index, feed_items, generate_html(feed_items, False, current_index, tag, is_loading), is_loading
177
 
178
+ def generate_html(feed_items, scroll_to_latest=False, current_index=0, tag="", is_loading=False):
179
  """
180
  Generate an HTML string to display the current feed item with click navigation.
181
 
 
183
  feed_items (list): List of dictionaries containing 'text' and 'image_base64'.
184
  scroll_to_latest (bool): Whether to auto-scroll to the latest item (not used here).
185
  current_index (int): The index of the item to display.
186
+ tag (str): The current tag for loading messages.
187
+ is_loading (bool): Whether the feed is currently loading.
188
 
189
  Returns:
190
  str: HTML string representing the feed.
191
  """
192
+ # Define loading messages based on the tag
193
+ loading_messages = [
194
+ f"Cooking up a {tag} masterpiece... 🍳",
195
+ f"Snapping a vibrant {tag} moment... 📸",
196
+ f"Creating a {tag} vibe that pops... ✨",
197
+ f"Getting that perfect {tag} shot... 🎥",
198
+ f"Bringing {tag} to life... 🌟"
199
+ ]
200
+
201
+ if is_loading:
202
+ return f"""
203
+ <div id="feed-container" style="
204
+ display: flex;
205
+ flex-direction: column;
206
+ align-items: center;
207
+ justify-content: center;
208
+ max-width: 360px;
209
+ margin: 0 auto;
210
+ background-color: #000;
211
+ height: 640px;
212
+ border: 1px solid #333;
213
+ border-radius: 10px;
214
+ color: white;
215
+ font-family: Arial, sans-serif;
216
+ position: relative;
217
+ ">
218
+ <div id="loading-message" style="
219
+ font-size: 18px;
220
+ font-weight: bold;
221
+ text-align: center;
222
+ margin-bottom: 20px;
223
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
224
+ ">
225
+ {loading_messages[0]}
226
+ </div>
227
+ <div style="
228
+ width: 80%;
229
+ height: 10px;
230
+ background-color: #333;
231
+ border-radius: 5px;
232
+ overflow: hidden;
233
+ ">
234
+ <div style="
235
+ width: 0%;
236
+ height: 100%;
237
+ background: linear-gradient(to right, #ff2d55, #ff5e78);
238
+ animation: loading 2s infinite;
239
+ "></div>
240
+ </div>
241
+ <style>
242
+ @keyframes loading {{
243
+ 0% {{ width: 0%; }}
244
+ 50% {{ width: 100%; }}
245
+ 100% {{ width: 0%; }}
246
+ }}
247
+ </style>
248
+ <script>
249
+ const messages = {json.dumps(loading_messages)};
250
+ let currentMessageIndex = 0;
251
+ const messageElement = document.getElementById('loading-message');
252
+ function rotateMessages() {{
253
+ currentMessageIndex = (currentMessageIndex + 1) % messages.length;
254
+ messageElement.textContent = messages[currentMessageIndex];
255
+ }}
256
+ setInterval(rotateMessages, 2000);
257
+ </script>
258
+ </div>
259
+ """
260
+
261
  if not feed_items or current_index >= len(feed_items):
262
  return """
263
  <div style="
 
333
  const clickX = event.clientX - rect.left;
334
  const width = rect.width;
335
  if (clickX > width * 0.75) {{
 
336
  document.getElementById('previous-button').click();
337
  }} else {{
 
338
  document.getElementById('next-button').click();
339
  }}
340
  }}
 
352
  .gradio-container { max-width: 400px; margin: 0 auto; padding: 10px; }
353
  input, select { border-radius: 5px; background-color: #222; color: #fff; border: 1px solid #444; }
354
  .gr-form { background-color: #111; padding: 15px; border-radius: 10px; }
 
355
  """,
356
  title="TikTok-Style Infinite Feed"
357
  ) as demo:
 
374
  label="Or Enter a Custom Tag",
375
  value="food",
376
  placeholder="e.g., sushi, adventure",
377
+ submit_btn=False
378
  )
379
 
 
 
 
 
 
 
 
 
 
380
  # Output display
381
  feed_html = gr.HTML()
382
 
 
385
  """Update the tag input when a suggested tag is selected and start the feed."""
386
  return selected_tag
387
 
 
 
 
 
388
  # Handle dropdown selection
389
  suggested_tags.change(
390
  fn=set_tag,
 
394
  fn=start_feed,
395
  inputs=[tag_input, current_index, feed_items, is_loading],
396
  outputs=[current_tag, current_index, feed_items, feed_html, is_loading]
 
 
 
 
397
  )
398
 
399
  # Handle Enter keypress in the custom tag input
 
401
  fn=start_feed,
402
  inputs=[tag_input, current_index, feed_items, is_loading],
403
  outputs=[current_tag, current_index, feed_items, feed_html, is_loading]
 
 
 
 
404
  )
405
 
406
+ # Hidden buttonsAPPROXIMATELY Hidden buttons for navigation
407
  next_button = gr.Button("Next", elem_id="next-button", visible=False)
408
  previous_button = gr.Button("Previous", elem_id="previous-button", visible=False)
409
 
 
412
  fn=load_next,
413
  inputs=[current_tag, current_index, feed_items, is_loading],
414
  outputs=[current_tag, current_index, feed_items, feed_html, is_loading]
 
 
 
 
415
  )
416
 
417
  # Handle click to go to previous item