codelion commited on
Commit
02a494e
Β·
verified Β·
1 Parent(s): 7535fbf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -65
app.py CHANGED
@@ -34,22 +34,22 @@ def clean_response_text(response_text):
34
  cleaned_text = cleaned_text[:-len("```")].strip()
35
  return cleaned_text
36
 
37
- def generate_ideas(tag):
38
  """
39
- Generate a diverse set of ideas related to the tag using the LLM.
40
 
41
  Args:
42
- tag (str): The tag to base the ideas on.
43
 
44
  Returns:
45
  list: A list of ideas as strings.
46
  """
47
  prompt = f"""
48
- Generate a list of 5 diverse and creative ideas related to {tag} that can be used for a TikTok video.
49
- Each idea should be a short sentence describing a specific scene or concept.
50
  Return the response as a JSON object with a single key 'ideas' containing a list of 5 ideas.
51
  Ensure the response is strictly in JSON format.
52
- Example: {{"ideas": ["A neon-lit gaming setup with RGB lights flashing", "A futuristic robot assembling a gadget"]}}
53
  """
54
  try:
55
  response = client.models.generate_content(
@@ -68,19 +68,19 @@ def generate_ideas(tag):
68
  except Exception as e:
69
  print(f"Error generating ideas: {e}")
70
  return [
71
- f"A vibrant {tag} scene at sunset",
72
- f"A close-up of {tag} with neon lights",
73
- f"A futuristic take on {tag} with holograms",
74
- f"A cozy {tag} moment with warm lighting",
75
- f"An action-packed {tag} scene with dynamic colors"
76
  ]
77
 
78
- def generate_item(tag, ideas, generate_video=False, max_retries=3):
79
  """
80
  Generate a single feed item (image and optionally video) using one of the ideas.
81
 
82
  Args:
83
- tag (str): The tag to base the content on.
84
  ideas (list): List of ideas to choose from.
85
  generate_video (bool): Whether to generate a video from the image.
86
  max_retries (int): Maximum number of retries if image generation fails.
@@ -93,13 +93,13 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
93
  for attempt in range(max_retries):
94
  selected_idea = random.choice(ideas)
95
  prompt = f"""
96
- Based on the idea "{selected_idea}", create content for a TikTok video about {tag}.
97
  Return a JSON object with two keys:
98
- - 'caption': A short, viral TikTok-style caption with hashtags.
99
- - 'image_prompt': A detailed image prompt for generating a high-quality visual scene.
100
  The image prompt should describe the scene vividly, specify a perspective and style, and ensure no text or letters are included.
101
  Ensure the response is strictly in JSON format.
102
- Example: {{"caption": "Neon vibes only! 🌌 #tech", "image_prompt": "A close-up view of a neon-lit gaming setup with RGB lights flashing, in a futuristic style, no text or letters"}}
103
  """
104
  try:
105
  response = client.models.generate_content(
@@ -118,8 +118,8 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
118
  image_prompt = response_json['image_prompt']
119
  except Exception as e:
120
  print(f"Error generating item (attempt {attempt + 1}): {e}")
121
- text = f"Obsessed with {tag}! πŸ”₯ #{tag}"
122
- image_prompt = f"A vivid scene of {selected_idea}, in a vibrant pop art style, no text or letters"
123
 
124
  # Attempt to generate the image
125
  try:
@@ -148,7 +148,8 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
148
  try:
149
  # Enhance the image prompt for video generation
150
  video_prompt = f"""
151
- {image_prompt} Create a close-up shot with a slow dolly shot circling around the subject,
 
152
  using shallow focus on the main subject to emphasize details, in a realistic style with cinematic lighting.
153
  """
154
  operation = client.models.generate_videos(
@@ -160,6 +161,7 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
160
  number_of_videos=2,
161
  duration_seconds=8,
162
  negative_prompt="blurry, low quality, text, letters",
 
163
  )
164
  )
165
  # Wait for videos to generate
@@ -167,6 +169,12 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
167
  time.sleep(20)
168
  operation = client.operations.get(operation)
169
 
 
 
 
 
 
 
170
  for n, video in enumerate(operation.response.generated_videos):
171
  fname = f'with_image_input{n}.mp4'
172
  print(f"Generated video: {fname}")
@@ -200,7 +208,7 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
200
  'ideas': ideas
201
  }
202
  # Retry with new ideas
203
- ideas = generate_ideas(tag)
204
  continue
205
  except Exception as e:
206
  print(f"Error generating image (attempt {attempt + 1}): {e}")
@@ -217,33 +225,33 @@ def generate_item(tag, ideas, generate_video=False, max_retries=3):
217
  'ideas': ideas
218
  }
219
  # Retry with new ideas
220
- ideas = generate_ideas(tag)
221
  continue
222
 
223
- def start_feed(tag, generate_video, current_index, feed_items):
224
  """
225
- Start or update the feed based on the tag.
226
 
227
  Args:
228
- tag (str): The tag to generate content for.
229
  generate_video (bool): Whether to generate a video.
230
  current_index (int): The current item index.
231
  feed_items (list): The current list of feed items.
232
 
233
  Returns:
234
- tuple: (current_tag, current_index, feed_items, html_content, share_links, is_loading)
235
  """
236
- if not tag.strip():
237
- tag = "trending"
238
 
239
  # Set loading state
240
  is_loading = True
241
- html_content = generate_html([], False, 0, tag, is_loading)
242
  share_links = ""
243
 
244
  try:
245
- ideas = generate_ideas(tag)
246
- item = generate_item(tag, ideas, generate_video=generate_video)
247
  feed_items = [item]
248
  current_index = 0
249
  share_links = generate_share_links(
@@ -274,41 +282,41 @@ def start_feed(tag, generate_video, current_index, feed_items):
274
  </div>
275
  """
276
  is_loading = False
277
- return tag, current_index, feed_items, html_content, share_links, is_loading
278
 
279
  # Set loading state to False and update UI
280
  is_loading = False
281
- html_content = generate_html(feed_items, False, current_index, tag, is_loading)
282
- return tag, current_index, feed_items, html_content, share_links, is_loading
283
 
284
- def load_next(tag, generate_video, current_index, feed_items):
285
  """
286
  Load the next item in the feed.
287
 
288
  Args:
289
- tag (str): The tag to generate content for.
290
  generate_video (bool): Whether to generate a video.
291
  current_index (int): The current item index.
292
  feed_items (list): The current list of feed items.
293
 
294
  Returns:
295
- tuple: (current_tag, current_index, feed_items, html_content, share_links, is_loading)
296
  """
297
  is_loading = True
298
- html_content = generate_html(feed_items, False, current_index, tag, is_loading)
299
  share_links = ""
300
 
301
  try:
302
  if current_index + 1 < len(feed_items):
303
  current_index += 1
304
  else:
305
- ideas = feed_items[-1]['ideas'] if feed_items else generate_ideas(tag)
306
- new_item = generate_item(tag, ideas, generate_video=generate_video)
307
  feed_items.append(new_item)
308
  current_index = len(feed_items) - 1
309
  share_links = generate_share_links(
310
  feed_items[current_index]['image_base64'],
311
- feed_items[current_index]['video_base64_list'], # Fixed typo: IRfeed_items -> feed_items
312
  feed_items[current_index]['text']
313
  )
314
  except Exception as e:
@@ -332,34 +340,34 @@ def load_next(tag, generate_video, current_index, feed_items):
332
  </div>
333
  """
334
  is_loading = False
335
- return tag, current_index, feed_items, html_content, share_links, is_loading
336
 
337
  is_loading = False
338
- html_content = generate_html(feed_items, False, current_index, tag, is_loading)
339
- return tag, current_index, feed_items, html_content, share_links, is_loading
340
 
341
- def load_previous(tag, generate_video, current_index, feed_items):
342
  """
343
  Load the previous item in the feed.
344
 
345
  Args:
346
- tag (str): The tag to generate content for.
347
  generate_video (bool): Whether to generate a video (not used here).
348
  current_index (int): The current item index.
349
  feed_items (list): The current list of feed items.
350
 
351
  Returns:
352
- tuple: (current_tag, current_index, feed_items, html_content, share_links, is_loading)
353
  """
354
  if current_index > 0:
355
  current_index -= 1
356
- html_content = generate_html(feed_items, False, current_index, tag, False)
357
  share_links = generate_share_links(
358
  feed_items[current_index]['image_base64'],
359
  feed_items[current_index]['video_base64_list'],
360
  feed_items[current_index]['text']
361
  )
362
- return tag, current_index, feed_items, html_content, share_links, False
363
 
364
  def generate_share_links(image_base64, video_base64_list, caption):
365
  """
@@ -460,7 +468,7 @@ def generate_share_links(image_base64, video_base64_list, caption):
460
  """
461
  return share_links
462
 
463
- def generate_html(feed_items, scroll_to_latest=False, current_index=0, tag="", is_loading=False):
464
  """
465
  Generate an HTML string to display the current feed item with click navigation.
466
 
@@ -468,18 +476,18 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0, tag="", i
468
  feed_items (list): List of dictionaries containing 'text' and 'image_base64'.
469
  scroll_to_latest (bool): Whether to auto-scroll to the latest item (not used here).
470
  current_index (int): The index of the item to display.
471
- tag (str): The current tag for loading messages.
472
  is_loading (bool): Whether the feed is currently loading.
473
 
474
  Returns:
475
  str: HTML string representing the feed.
476
  """
477
  loading_messages = [
478
- f"Cooking up a {tag} masterpiece... 🍳",
479
- f"Snapping a vibrant {tag} moment... πŸ“Έ",
480
- f"Creating a {tag} vibe that pops... ✨",
481
- f"Getting that perfect {tag} shot... πŸŽ₯",
482
- f"Bringing {tag} to life... 🌟"
483
  ]
484
 
485
  if is_loading:
@@ -640,7 +648,7 @@ with gr.Blocks(
640
  title="Create Your Feed"
641
  ) as demo:
642
  # State variables
643
- current_tag = gr.State(value="")
644
  current_index = gr.State(value=0)
645
  feed_items = gr.State(value=[])
646
  is_loading = gr.State(value=False)
@@ -649,7 +657,7 @@ with gr.Blocks(
649
  # Input section
650
  with gr.Column(elem_classes="gr-form"):
651
  gr.Markdown("### Create Your Feed")
652
- tag_input = gr.Textbox(
653
  label="Enter Concept or Ideas",
654
  value="",
655
  placeholder="e.g., sushi adventure, neon tech",
@@ -667,17 +675,17 @@ with gr.Blocks(
667
 
668
  # Event handlers
669
  # Handle Enter keypress in the concept input
670
- tag_input.submit(
671
  fn=start_feed,
672
- inputs=[tag_input, generate_video_checkbox, current_index, feed_items],
673
- outputs=[current_tag, current_index, feed_items, feed_html, share_html, is_loading]
674
  )
675
 
676
  # Handle magic button click to generate next item
677
  magic_button.click(
678
  fn=load_next,
679
- inputs=[current_tag, generate_video_checkbox, current_index, feed_items],
680
- outputs=[current_tag, current_index, feed_items, feed_html, share_html, is_loading]
681
  )
682
 
683
  # Hidden button for previous item navigation
@@ -686,8 +694,8 @@ with gr.Blocks(
686
  # Handle click to go to previous item
687
  previous_button.click(
688
  fn=load_previous,
689
- inputs=[current_tag, generate_video_checkbox, current_index, feed_items],
690
- outputs=[current_tag, current_index, feed_items, feed_html, share_html, is_loading]
691
  )
692
 
693
  # Launch the app
 
34
  cleaned_text = cleaned_text[:-len("```")].strip()
35
  return cleaned_text
36
 
37
+ def generate_ideas(user_input):
38
  """
39
+ Generate a diverse set of ideas based on the user's input concept using the LLM.
40
 
41
  Args:
42
+ user_input (str): The user's input concept or idea (e.g., "blindfolded Rubik's Cube challenge").
43
 
44
  Returns:
45
  list: A list of ideas as strings.
46
  """
47
  prompt = f"""
48
+ The user has provided the concept: "{user_input}". Based on this concept, generate a list of 5 diverse and creative ideas for a TikTok video that directly relate to "{user_input}".
49
+ Each idea should be a short sentence describing a specific scene or concept, ensuring the core theme of "{user_input}" is central to each idea.
50
  Return the response as a JSON object with a single key 'ideas' containing a list of 5 ideas.
51
  Ensure the response is strictly in JSON format.
52
+ Example: {{"ideas": ["A neon-lit Rubik's Cube challenge in the dark", "A blindfolded speedcubing competition with dramatic music"]}}
53
  """
54
  try:
55
  response = client.models.generate_content(
 
68
  except Exception as e:
69
  print(f"Error generating ideas: {e}")
70
  return [
71
+ f"A dramatic {user_input} scene with cinematic lighting",
72
+ f"A close-up of {user_input} in a futuristic setting",
73
+ f"A high-energy {user_input} moment with vibrant colors",
74
+ f"A serene {user_input} scene with soft focus",
75
+ f"An action-packed {user_input} challenge with dynamic angles"
76
  ]
77
 
78
+ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
79
  """
80
  Generate a single feed item (image and optionally video) using one of the ideas.
81
 
82
  Args:
83
+ user_input (str): The user's input concept or idea.
84
  ideas (list): List of ideas to choose from.
85
  generate_video (bool): Whether to generate a video from the image.
86
  max_retries (int): Maximum number of retries if image generation fails.
 
93
  for attempt in range(max_retries):
94
  selected_idea = random.choice(ideas)
95
  prompt = f"""
96
+ The user has provided the concept: "{user_input}". Based on this concept and the specific idea "{selected_idea}", create content for a TikTok video.
97
  Return a JSON object with two keys:
98
+ - 'caption': A short, viral TikTok-style caption with hashtags that reflects "{user_input}".
99
+ - 'image_prompt': A detailed image prompt for generating a high-quality visual scene, ensuring the theme of "{user_input}" is central.
100
  The image prompt should describe the scene vividly, specify a perspective and style, and ensure no text or letters are included.
101
  Ensure the response is strictly in JSON format.
102
+ Example: {{"caption": "Blindfolded Rubik's Cube MAGIC! 🀯 #rubiks", "image_prompt": "A close-up view of a person solving a Rubik's Cube blindfolded, in a dramatic style, no text or letters"}}
103
  """
104
  try:
105
  response = client.models.generate_content(
 
118
  image_prompt = response_json['image_prompt']
119
  except Exception as e:
120
  print(f"Error generating item (attempt {attempt + 1}): {e}")
121
+ text = f"Amazing {user_input}! πŸ”₯ #{user_input.replace(' ', '')}"
122
+ image_prompt = f"A vivid scene of {selected_idea} related to {user_input}, in a vibrant pop art style, no text or letters"
123
 
124
  # Attempt to generate the image
125
  try:
 
148
  try:
149
  # Enhance the image prompt for video generation
150
  video_prompt = f"""
151
+ The user concept is "{user_input}". Based on this and the scene: {image_prompt}, create a video.
152
+ Use a close-up shot with a slow dolly shot circling around the subject,
153
  using shallow focus on the main subject to emphasize details, in a realistic style with cinematic lighting.
154
  """
155
  operation = client.models.generate_videos(
 
161
  number_of_videos=2,
162
  duration_seconds=8,
163
  negative_prompt="blurry, low quality, text, letters",
164
+ enhance_prompt=True
165
  )
166
  )
167
  # Wait for videos to generate
 
169
  time.sleep(20)
170
  operation = client.operations.get(operation)
171
 
172
+ # Check if operation succeeded and has a valid response
173
+ if operation.response is None:
174
+ raise ValueError("Video generation operation failed: No response")
175
+ if not hasattr(operation.response, 'generated_videos'):
176
+ raise ValueError("Video generation operation failed: No generated_videos in response")
177
+
178
  for n, video in enumerate(operation.response.generated_videos):
179
  fname = f'with_image_input{n}.mp4'
180
  print(f"Generated video: {fname}")
 
208
  'ideas': ideas
209
  }
210
  # Retry with new ideas
211
+ ideas = generate_ideas(user_input)
212
  continue
213
  except Exception as e:
214
  print(f"Error generating image (attempt {attempt + 1}): {e}")
 
225
  'ideas': ideas
226
  }
227
  # Retry with new ideas
228
+ ideas = generate_ideas(user_input)
229
  continue
230
 
231
+ def start_feed(user_input, generate_video, current_index, feed_items):
232
  """
233
+ Start or update the feed based on the user input.
234
 
235
  Args:
236
+ user_input (str): The user's input concept or idea.
237
  generate_video (bool): Whether to generate a video.
238
  current_index (int): The current item index.
239
  feed_items (list): The current list of feed items.
240
 
241
  Returns:
242
+ tuple: (current_user_input, current_index, feed_items, html_content, share_links, is_loading)
243
  """
244
+ if not user_input.strip():
245
+ user_input = "trending"
246
 
247
  # Set loading state
248
  is_loading = True
249
+ html_content = generate_html([], False, 0, user_input, is_loading)
250
  share_links = ""
251
 
252
  try:
253
+ ideas = generate_ideas(user_input)
254
+ item = generate_item(user_input, ideas, generate_video=generate_video)
255
  feed_items = [item]
256
  current_index = 0
257
  share_links = generate_share_links(
 
282
  </div>
283
  """
284
  is_loading = False
285
+ return user_input, current_index, feed_items, html_content, share_links, is_loading
286
 
287
  # Set loading state to False and update UI
288
  is_loading = False
289
+ html_content = generate_html(feed_items, False, current_index, user_input, is_loading)
290
+ return user_input, current_index, feed_items, html_content, share_links, is_loading
291
 
292
+ def load_next(user_input, generate_video, current_index, feed_items):
293
  """
294
  Load the next item in the feed.
295
 
296
  Args:
297
+ user_input (str): The user's input concept or idea.
298
  generate_video (bool): Whether to generate a video.
299
  current_index (int): The current item index.
300
  feed_items (list): The current list of feed items.
301
 
302
  Returns:
303
+ tuple: (current_user_input, current_index, feed_items, html_content, share_links, is_loading)
304
  """
305
  is_loading = True
306
+ html_content = generate_html(feed_items, False, current_index, user_input, is_loading)
307
  share_links = ""
308
 
309
  try:
310
  if current_index + 1 < len(feed_items):
311
  current_index += 1
312
  else:
313
+ ideas = feed_items[-1]['ideas'] if feed_items else generate_ideas(user_input)
314
+ new_item = generate_item(user_input, ideas, generate_video=generate_video)
315
  feed_items.append(new_item)
316
  current_index = len(feed_items) - 1
317
  share_links = generate_share_links(
318
  feed_items[current_index]['image_base64'],
319
+ feed_items[current_index]['video_base64_list'],
320
  feed_items[current_index]['text']
321
  )
322
  except Exception as e:
 
340
  </div>
341
  """
342
  is_loading = False
343
+ return user_input, current_index, feed_items, html_content, share_links, is_loading
344
 
345
  is_loading = False
346
+ html_content = generate_html(feed_items, False, current_index, user_input, is_loading)
347
+ return user_input, current_index, feed_items, html_content, share_links, is_loading
348
 
349
+ def load_previous(user_input, generate_video, current_index, feed_items):
350
  """
351
  Load the previous item in the feed.
352
 
353
  Args:
354
+ user_input (str): The user's input concept or idea.
355
  generate_video (bool): Whether to generate a video (not used here).
356
  current_index (int): The current item index.
357
  feed_items (list): The current list of feed items.
358
 
359
  Returns:
360
+ tuple: (current_user_input, current_index, feed_items, html_content, share_links, is_loading)
361
  """
362
  if current_index > 0:
363
  current_index -= 1
364
+ html_content = generate_html(feed_items, False, current_index, user_input, False)
365
  share_links = generate_share_links(
366
  feed_items[current_index]['image_base64'],
367
  feed_items[current_index]['video_base64_list'],
368
  feed_items[current_index]['text']
369
  )
370
+ return user_input, current_index, feed_items, html_content, share_links, False
371
 
372
  def generate_share_links(image_base64, video_base64_list, caption):
373
  """
 
468
  """
469
  return share_links
470
 
471
+ def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_input="", is_loading=False):
472
  """
473
  Generate an HTML string to display the current feed item with click navigation.
474
 
 
476
  feed_items (list): List of dictionaries containing 'text' and 'image_base64'.
477
  scroll_to_latest (bool): Whether to auto-scroll to the latest item (not used here).
478
  current_index (int): The index of the item to display.
479
+ user_input (str): The user's input concept or idea for loading messages.
480
  is_loading (bool): Whether the feed is currently loading.
481
 
482
  Returns:
483
  str: HTML string representing the feed.
484
  """
485
  loading_messages = [
486
+ f"Cooking up a {user_input} masterpiece... 🍳",
487
+ f"Snapping a vibrant {user_input} moment... πŸ“Έ",
488
+ f"Creating a {user_input} vibe that pops... ✨",
489
+ f"Getting that perfect {user_input} shot... πŸŽ₯",
490
+ f"Bringing {user_input} to life... 🌟"
491
  ]
492
 
493
  if is_loading:
 
648
  title="Create Your Feed"
649
  ) as demo:
650
  # State variables
651
+ current_user_input = gr.State(value="")
652
  current_index = gr.State(value=0)
653
  feed_items = gr.State(value=[])
654
  is_loading = gr.State(value=False)
 
657
  # Input section
658
  with gr.Column(elem_classes="gr-form"):
659
  gr.Markdown("### Create Your Feed")
660
+ user_input = gr.Textbox(
661
  label="Enter Concept or Ideas",
662
  value="",
663
  placeholder="e.g., sushi adventure, neon tech",
 
675
 
676
  # Event handlers
677
  # Handle Enter keypress in the concept input
678
+ user_input.submit(
679
  fn=start_feed,
680
+ inputs=[user_input, generate_video_checkbox, current_index, feed_items],
681
+ outputs=[current_user_input, current_index, feed_items, feed_html, share_html, is_loading]
682
  )
683
 
684
  # Handle magic button click to generate next item
685
  magic_button.click(
686
  fn=load_next,
687
+ inputs=[current_user_input, generate_video_checkbox, current_index, feed_items],
688
+ outputs=[current_user_input, current_index, feed_items, feed_html, share_html, is_loading]
689
  )
690
 
691
  # Hidden button for previous item navigation
 
694
  # Handle click to go to previous item
695
  previous_button.click(
696
  fn=load_previous,
697
+ inputs=[current_user_input, generate_video_checkbox, current_index, feed_items],
698
+ outputs=[current_user_input, current_index, feed_items, feed_html, share_html, is_loading]
699
  )
700
 
701
  # Launch the app