Update app.py
Browse files
app.py
CHANGED
@@ -104,13 +104,14 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
|
|
104 |
user_input (str): The user's input concept or idea.
|
105 |
ideas (list): List of ideas to choose from.
|
106 |
generate_video (bool): Whether to generate a video from the image.
|
107 |
-
max_retries (int): Maximum number of retries
|
108 |
|
109 |
Returns:
|
110 |
dict: A dictionary with 'text' (str), 'image_base64' (str), 'video_base64' (str or None), and 'ideas' (list).
|
111 |
"""
|
112 |
-
video_base64 = None
|
113 |
|
|
|
114 |
for attempt in range(max_retries):
|
115 |
selected_idea = random.choice(ideas)
|
116 |
prompt = f"""
|
@@ -149,7 +150,7 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
|
|
149 |
prompt=image_prompt,
|
150 |
config=types.GenerateImagesConfig(
|
151 |
aspect_ratio="9:16",
|
152 |
-
number_of_images=1
|
153 |
)
|
154 |
)
|
155 |
if imagen.generated_images and len(imagen.generated_images) > 0:
|
@@ -164,69 +165,91 @@ def generate_item(user_input, ideas, generate_video=False, max_retries=3):
|
|
164 |
image.save(buffered, format="PNG")
|
165 |
img_str = base64.b64encode(buffered.getvalue()).decode()
|
166 |
|
167 |
-
# Generate video if enabled (
|
168 |
if generate_video:
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
)
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
else:
|
213 |
-
#
|
214 |
-
video_buffer = BytesIO()
|
215 |
-
for chunk in video_data:
|
216 |
-
video_buffer.write(chunk)
|
217 |
-
video_bytes = video_buffer.getvalue()
|
218 |
-
# Encode the video bytes as base64
|
219 |
-
video_base64 = base64.b64encode(video_bytes).decode()
|
220 |
-
else:
|
221 |
-
raise ValueError("No video was generated")
|
222 |
-
except Exception as e:
|
223 |
-
print(f"Error generating video: {e}")
|
224 |
-
video_base64 = None # Proceed without video if generation fails
|
225 |
|
226 |
return {
|
227 |
'text': text,
|
228 |
'image_base64': img_str,
|
229 |
-
'video_base64': video_base64,
|
230 |
'ideas': ideas
|
231 |
}
|
232 |
else:
|
@@ -309,7 +332,7 @@ def start_feed(user_input, generate_video, current_index, feed_items):
|
|
309 |
margin: 0 auto;
|
310 |
background-color: #000;
|
311 |
height: 640px;
|
312 |
-
border: 1px
|
313 |
border-radius: 10px;
|
314 |
color: white;
|
315 |
font-family: Arial, sans-serif;
|
|
|
104 |
user_input (str): The user's input concept or idea.
|
105 |
ideas (list): List of ideas to choose from.
|
106 |
generate_video (bool): Whether to generate a video from the image.
|
107 |
+
max_retries (int): Maximum number of retries for both image and video generation.
|
108 |
|
109 |
Returns:
|
110 |
dict: A dictionary with 'text' (str), 'image_base64' (str), 'video_base64' (str or None), and 'ideas' (list).
|
111 |
"""
|
112 |
+
video_base64 = None
|
113 |
|
114 |
+
# Retry loop for image generation
|
115 |
for attempt in range(max_retries):
|
116 |
selected_idea = random.choice(ideas)
|
117 |
prompt = f"""
|
|
|
150 |
prompt=image_prompt,
|
151 |
config=types.GenerateImagesConfig(
|
152 |
aspect_ratio="9:16",
|
153 |
+
number_of_images=1
|
154 |
)
|
155 |
)
|
156 |
if imagen.generated_images and len(imagen.generated_images) > 0:
|
|
|
165 |
image.save(buffered, format="PNG")
|
166 |
img_str = base64.b64encode(buffered.getvalue()).decode()
|
167 |
|
168 |
+
# Generate video if enabled (with retries)
|
169 |
if generate_video:
|
170 |
+
for video_attempt in range(max_retries):
|
171 |
+
try:
|
172 |
+
# Base video prompt
|
173 |
+
video_prompt_base = f"""
|
174 |
+
The user concept is "{user_input}". Based on this and the scene: {image_prompt}, create a video.
|
175 |
+
Use a close-up shot with a slow dolly shot circling around the subject,
|
176 |
+
using shallow focus on the main subject to emphasize details, in a realistic style with cinematic lighting.
|
177 |
+
"""
|
178 |
+
# Modify the prompt slightly for each retry
|
179 |
+
if video_attempt == 0:
|
180 |
+
video_prompt = video_prompt_base
|
181 |
+
elif video_attempt == 1:
|
182 |
+
video_prompt = f"""
|
183 |
+
The user concept is "{user_input}". Based on this and the scene: {image_prompt}, create a video.
|
184 |
+
Use a close-up shot focusing on the subject,
|
185 |
+
with soft lighting and a realistic style.
|
186 |
+
"""
|
187 |
+
else:
|
188 |
+
video_prompt = f"""
|
189 |
+
The user concept is "{user_input}". Based on this and a simplified scene: {image_prompt}, create a video.
|
190 |
+
Use a static close-up shot of the subject in a realistic style.
|
191 |
+
"""
|
192 |
+
|
193 |
+
print(f"Attempting video generation (attempt {video_attempt + 1}): {video_prompt}")
|
194 |
+
operation = client.models.generate_videos(
|
195 |
+
model="veo-2.0-generate-001",
|
196 |
+
prompt=video_prompt,
|
197 |
+
image=generated_image.image,
|
198 |
+
config=types.GenerateVideosConfig(
|
199 |
+
aspect_ratio="9:16",
|
200 |
+
number_of_videos=1,
|
201 |
+
duration_seconds=8,
|
202 |
+
negative_prompt="blurry, low quality, text, letters"
|
203 |
+
)
|
204 |
)
|
205 |
+
# Wait for video to generate
|
206 |
+
while not operation.done:
|
207 |
+
time.sleep(20)
|
208 |
+
operation = client.operations.get(operation)
|
209 |
+
|
210 |
+
# Enhanced error handling for video generation response
|
211 |
+
if operation.error:
|
212 |
+
raise ValueError(f"Video generation operation failed with error: {operation.error.message}")
|
213 |
+
if operation.response is None:
|
214 |
+
raise ValueError("Video generation operation failed: No response")
|
215 |
+
if not hasattr(operation.response, 'generated_videos') or operation.response.generated_videos is None:
|
216 |
+
raise ValueError("Video generation operation failed: No generated_videos in response")
|
217 |
+
|
218 |
+
# Process the single generated video
|
219 |
+
if len(operation.response.generated_videos) > 0:
|
220 |
+
video = operation.response.generated_videos[0]
|
221 |
+
if video is None or not hasattr(video, 'video'):
|
222 |
+
raise ValueError("Video is invalid or missing video data")
|
223 |
+
fname = 'with_image_input.mp4'
|
224 |
+
print(f"Generated video: {fname}")
|
225 |
+
# Download the video and get the raw bytes
|
226 |
+
video_data = client.files.download(file=video.video)
|
227 |
+
# Ensure video_data is in bytes
|
228 |
+
if isinstance(video_data, bytes):
|
229 |
+
video_bytes = video_data
|
230 |
+
else:
|
231 |
+
# If video_data is a file-like object, read the bytes
|
232 |
+
video_buffer = BytesIO()
|
233 |
+
for chunk in video_data:
|
234 |
+
video_buffer.write(chunk)
|
235 |
+
video_bytes = video_buffer.getvalue()
|
236 |
+
# Encode the video bytes as base64
|
237 |
+
video_base64 = base64.b64encode(video_bytes).decode()
|
238 |
+
break # Success, exit the retry loop
|
239 |
+
else:
|
240 |
+
raise ValueError("No video was generated")
|
241 |
+
except Exception as e:
|
242 |
+
print(f"Error generating video (attempt {video_attempt + 1}): {e}")
|
243 |
+
if video_attempt == max_retries - 1:
|
244 |
+
print("Max retries reached for video generation. Proceeding without video.")
|
245 |
+
video_base64 = None
|
246 |
else:
|
247 |
+
continue # Retry with a modified prompt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
|
249 |
return {
|
250 |
'text': text,
|
251 |
'image_base64': img_str,
|
252 |
+
'video_base64': video_base64,
|
253 |
'ideas': ideas
|
254 |
}
|
255 |
else:
|
|
|
332 |
margin: 0 auto;
|
333 |
background-color: #000;
|
334 |
height: 640px;
|
335 |
+
border: 1px solid #333;
|
336 |
border-radius: 10px;
|
337 |
color: white;
|
338 |
font-family: Arial, sans-serif;
|