codelion commited on
Commit
2a952b2
·
verified ·
1 Parent(s): 56772bb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -27
app.py CHANGED
@@ -45,11 +45,19 @@ def generate_ideas(user_input):
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(
@@ -62,9 +70,22 @@ def generate_ideas(user_input):
62
  raise ValueError("Empty response from API")
63
  cleaned_text = clean_response_text(response.text)
64
  response_json = json.loads(cleaned_text)
65
- if 'ideas' not in response_json or not isinstance(response_json['ideas'], list):
66
- raise ValueError("Invalid JSON format: 'ideas' key missing or not a list")
67
- return response_json['ideas']
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  except Exception as e:
69
  print(f"Error generating ideas: {e}")
70
  return [
@@ -161,7 +182,6 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
161
  number_of_videos=2,
162
  duration_seconds=8,
163
  negative_prompt="blurry, low quality, text, letters"
164
- # Removed enhance_prompt=True since it's the default
165
  )
166
  )
167
  # Wait for videos to generate
@@ -183,10 +203,19 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
183
  raise ValueError(f"Video {n} is invalid or missing video data")
184
  fname = f'with_image_input{n}.mp4'
185
  print(f"Generated video: {fname}")
186
- client.files.download(file=video.video)
187
- video_buffer = BytesIO()
188
- video.video.save(video_buffer)
189
- video_base64 = base64.b64encode(video_buffer.getvalue()).decode()
 
 
 
 
 
 
 
 
 
190
  video_base64_list.append(video_base64)
191
  except Exception as e:
192
  print(f"Error generating video: {e}")
@@ -476,9 +505,10 @@ def generate_share_links(image_base64, video_base64_list, caption):
476
  def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_input="", is_loading=False):
477
  """
478
  Generate an HTML string to display the current feed item with click navigation.
 
479
 
480
  Args:
481
- feed_items (list): List of dictionaries containing 'text' and 'image_base64'.
482
  scroll_to_latest (bool): Whether to auto-scroll to the latest item (not used here).
483
  current_index (int): The index of the item to display.
484
  user_input (str): The user's input concept or idea for loading messages.
@@ -576,7 +606,37 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_inpu
576
  """
577
 
578
  item = feed_items[current_index]
579
- html_str = """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  <div id="feed-container" style="
581
  display: flex;
582
  flex-direction: column;
@@ -599,15 +659,7 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_inpu
599
  overflow: hidden;
600
  cursor: pointer;
601
  " onclick="handleClick(event)">
602
- <img id="feed-image" src="data:image/png;base64,{image_base64}" style="
603
- width: 100%;
604
- height: 100%;
605
- object-fit: cover;
606
- position: absolute;
607
- top: 0;
608
- left: 0;
609
- z-index: 1;
610
- ">
611
  <div style="
612
  position: relative;
613
  z-index: 2;
@@ -619,14 +671,14 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_inpu
619
  font-weight: bold;
620
  text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
621
  ">
622
- {text}
623
  </div>
624
  </div>
625
  </div>
626
  <script>
627
  function handleClick(event) {{
628
- const image = document.getElementById('feed-image');
629
- const rect = image.getBoundingClientRect();
630
  const clickX = event.clientX - rect.left;
631
  const width = rect.width;
632
  if (clickX > width * 0.75) {{
@@ -635,8 +687,7 @@ def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_inpu
635
  }}
636
  </script>
637
  <button id="previous-button" style="display: none;" onclick="document.getElementById('previous-button').click()"></button>
638
- """.format(image_base64=item['image_base64'], text=item['text'])
639
-
640
  return html_str
641
 
642
  # Define the Gradio interface
 
45
  list: A list of ideas as strings.
46
  """
47
  prompt = f"""
48
+ 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}".
49
+ Each idea must clearly incorporate and focus on the core theme of "{user_input}" without deviating into unrelated topics.
50
+ Each idea should be a short sentence describing a specific scene or concept.
51
  Return the response as a JSON object with a single key 'ideas' containing a list of 5 ideas.
52
  Ensure the response is strictly in JSON format.
53
+ Example for "blindfolded Rubik's Cube challenge":
54
+ {{"ideas": [
55
+ "A blindfolded speedcubing competition with dramatic music",
56
+ "A close-up of a person solving a Rubik's Cube blindfolded under a spotlight",
57
+ "A time-lapse of a blindfolded Rubik's Cube solve with colorful lighting",
58
+ "A blindfolded Rubik's Cube challenge in a futuristic setting",
59
+ "A split-screen of two people racing to solve a Rubik's Cube blindfolded"
60
+ ]}}
61
  """
62
  try:
63
  response = client.models.generate_content(
 
70
  raise ValueError("Empty response from API")
71
  cleaned_text = clean_response_text(response.text)
72
  response_json = json.loads(cleaned_text)
73
+ if 'ideas' not in response_json or not isinstance(response_json['ideas'], list) or len(response_json['ideas']) != 5:
74
+ raise ValueError("Invalid JSON format: 'ideas' key missing, not a list, or incorrect length")
75
+
76
+ # Validate that ideas are related to user_input
77
+ ideas = response_json['ideas']
78
+ for idea in ideas:
79
+ if user_input.lower() not in idea.lower():
80
+ print(f"Warning: Idea '{idea}' does not seem related to '{user_input}'. Falling back to default ideas.")
81
+ return [
82
+ f"A dramatic {user_input} scene with cinematic lighting",
83
+ f"A close-up of {user_input} in a futuristic setting",
84
+ f"A high-energy {user_input} moment with vibrant colors",
85
+ f"A serene {user_input} scene with soft focus",
86
+ f"An action-packed {user_input} challenge with dynamic angles"
87
+ ]
88
+ return ideas
89
  except Exception as e:
90
  print(f"Error generating ideas: {e}")
91
  return [
 
182
  number_of_videos=2,
183
  duration_seconds=8,
184
  negative_prompt="blurry, low quality, text, letters"
 
185
  )
186
  )
187
  # Wait for videos to generate
 
203
  raise ValueError(f"Video {n} is invalid or missing video data")
204
  fname = f'with_image_input{n}.mp4'
205
  print(f"Generated video: {fname}")
206
+ # Download the video and get the raw bytes
207
+ video_data = client.files.download(file=video.video)
208
+ # Ensure video_data is in bytes
209
+ if isinstance(video_data, bytes):
210
+ video_bytes = video_data
211
+ else:
212
+ # If video_data is a file-like object, read the bytes
213
+ video_buffer = BytesIO()
214
+ for chunk in video_data:
215
+ video_buffer.write(chunk)
216
+ video_bytes = video_buffer.getvalue()
217
+ # Encode the video bytes as base64
218
+ video_base64 = base64.b64encode(video_bytes).decode()
219
  video_base64_list.append(video_base64)
220
  except Exception as e:
221
  print(f"Error generating video: {e}")
 
505
  def generate_html(feed_items, scroll_to_latest=False, current_index=0, user_input="", is_loading=False):
506
  """
507
  Generate an HTML string to display the current feed item with click navigation.
508
+ Displays a video if available, otherwise falls back to the image.
509
 
510
  Args:
511
+ feed_items (list): List of dictionaries containing 'text', 'image_base64', and 'video_base64_list'.
512
  scroll_to_latest (bool): Whether to auto-scroll to the latest item (not used here).
513
  current_index (int): The index of the item to display.
514
  user_input (str): The user's input concept or idea for loading messages.
 
606
  """
607
 
608
  item = feed_items[current_index]
609
+ # Check if there are videos to display; if so, show the first video
610
+ if item['video_base64_list']:
611
+ media_element = f"""
612
+ <video id="feed-video" controls style="
613
+ width: 100%;
614
+ height: 100%;
615
+ object-fit: cover;
616
+ position: absolute;
617
+ top: 0;
618
+ left: 0;
619
+ z-index: 1;
620
+ ">
621
+ <source src="data:video/mp4;base64,{item['video_base64_list'][0]}" type="video/mp4">
622
+ Your browser does not support the video tag.
623
+ </video>
624
+ """
625
+ else:
626
+ # Fallback to image if no video is available
627
+ media_element = f"""
628
+ <img id="feed-image" src="data:image/png;base64,{item['image_base64']}" style="
629
+ width: 100%;
630
+ height: 100%;
631
+ object-fit: cover;
632
+ position: absolute;
633
+ top: 0;
634
+ left: 0;
635
+ z-index: 1;
636
+ ">
637
+ """
638
+
639
+ html_str = f"""
640
  <div id="feed-container" style="
641
  display: flex;
642
  flex-direction: column;
 
659
  overflow: hidden;
660
  cursor: pointer;
661
  " onclick="handleClick(event)">
662
+ {media_element}
 
 
 
 
 
 
 
 
663
  <div style="
664
  position: relative;
665
  z-index: 2;
 
671
  font-weight: bold;
672
  text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
673
  ">
674
+ {item['text']}
675
  </div>
676
  </div>
677
  </div>
678
  <script>
679
  function handleClick(event) {{
680
+ const media = document.getElementById('feed-video') || document.getElementById('feed-image');
681
+ const rect = media.getBoundingClientRect();
682
  const clickX = event.clientX - rect.left;
683
  const width = rect.width;
684
  if (clickX > width * 0.75) {{
 
687
  }}
688
  </script>
689
  <button id="previous-button" style="display: none;" onclick="document.getElementById('previous-button').click()"></button>
690
+ """
 
691
  return html_str
692
 
693
  # Define the Gradio interface