Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -284,10 +284,20 @@ def generate_all_scenes(prompts_text):
|
|
284 |
|
285 |
generated_images = []
|
286 |
formatted_prompts = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
|
288 |
sections = prompts_text.split('='*50)
|
289 |
|
290 |
-
for section in sections:
|
291 |
if not section.strip():
|
292 |
continue
|
293 |
|
@@ -304,7 +314,11 @@ def generate_all_scenes(prompts_text):
|
|
304 |
if scene_prompt:
|
305 |
try:
|
306 |
clear_memory()
|
307 |
-
|
|
|
|
|
|
|
|
|
308 |
|
309 |
image = generate_story_image(scene_prompt)
|
310 |
|
@@ -317,78 +331,39 @@ def generate_all_scenes(prompts_text):
|
|
317 |
# Verify array shape and type
|
318 |
if len(img_array.shape) == 3 and img_array.shape[2] == 3:
|
319 |
generated_images.append(img_array)
|
320 |
-
|
321 |
else:
|
322 |
-
|
323 |
else:
|
324 |
-
|
325 |
|
326 |
clear_memory()
|
327 |
|
328 |
except Exception as e:
|
329 |
-
|
|
|
330 |
clear_memory()
|
331 |
continue
|
|
|
|
|
|
|
332 |
|
333 |
-
#
|
334 |
if not generated_images:
|
335 |
-
|
336 |
-
|
|
|
337 |
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
def overlay_text_on_image(image, text):
|
342 |
-
if image is None:
|
343 |
-
return None
|
344 |
|
345 |
-
try:
|
346 |
-
img = image.convert('RGB')
|
347 |
-
draw = ImageDraw.Draw(img)
|
348 |
-
|
349 |
-
font_size = int(img.width * 0.025)
|
350 |
-
try:
|
351 |
-
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", font_size)
|
352 |
-
except:
|
353 |
-
font = ImageFont.load_default()
|
354 |
-
|
355 |
-
y_position = int(img.height * 0.005)
|
356 |
-
x_margin = int(img.width * 0.005)
|
357 |
-
available_width = img.width - (2 * x_margin)
|
358 |
-
|
359 |
-
wrapped_text = textwrap.fill(text, width=int(available_width / (font_size * 0.6)))
|
360 |
-
|
361 |
-
outline_color = (255, 255, 255)
|
362 |
-
text_color = (0, 0, 0)
|
363 |
-
offsets = [-2, -1, 1, 2]
|
364 |
-
|
365 |
-
for dx in offsets:
|
366 |
-
for dy in offsets:
|
367 |
-
draw.multiline_text(
|
368 |
-
(x_margin + dx, y_position + dy),
|
369 |
-
wrapped_text,
|
370 |
-
font=font,
|
371 |
-
fill=outline_color
|
372 |
-
)
|
373 |
-
|
374 |
-
draw.multiline_text(
|
375 |
-
(x_margin, y_position),
|
376 |
-
wrapped_text,
|
377 |
-
font=font,
|
378 |
-
fill=text_color
|
379 |
-
)
|
380 |
-
|
381 |
-
return img
|
382 |
-
|
383 |
-
except Exception as e:
|
384 |
-
print(f"Error overlaying text: {e}")
|
385 |
-
return None
|
386 |
-
|
387 |
@spaces.GPU(duration=60)
|
388 |
def add_text_to_scenes(gallery_images, prompts_text):
|
389 |
if not isinstance(gallery_images, list):
|
390 |
return [], []
|
391 |
|
|
|
|
|
392 |
sections = prompts_text.split('='*50)
|
393 |
overlaid_images = []
|
394 |
output_files = []
|
@@ -410,10 +385,21 @@ def add_text_to_scenes(gallery_images, prompts_text):
|
|
410 |
|
411 |
if paragraph and image_data is not None:
|
412 |
try:
|
|
|
|
|
|
|
|
|
|
|
413 |
if isinstance(image_data, np.ndarray):
|
414 |
image = Image.fromarray(image_data)
|
415 |
else:
|
416 |
image = image_data
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
|
418 |
overlaid_img = overlay_text_on_image(image, paragraph)
|
419 |
if overlaid_img is not None:
|
@@ -423,13 +409,73 @@ def add_text_to_scenes(gallery_images, prompts_text):
|
|
423 |
output_path = os.path.join(temp_dir, f"panel_{i+1}.png")
|
424 |
overlaid_img.save(output_path)
|
425 |
output_files.append(output_path)
|
|
|
426 |
except Exception as e:
|
427 |
print(f"Error processing image {i+1}: {str(e)}")
|
428 |
continue
|
429 |
|
|
|
|
|
|
|
|
|
|
|
430 |
clear_memory()
|
431 |
return overlaid_images, output_files
|
432 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
433 |
def generate_combined_audio_from_story(story_text, voice='af_heart', speed=1):
|
434 |
clear_memory()
|
435 |
|
@@ -555,19 +601,19 @@ def create_interface():
|
|
555 |
|
556 |
with gr.Row():
|
557 |
prompts_btn = gr.Button("4. Generate Scene Prompts")
|
558 |
-
with gr.Row():
|
559 |
prompts_output = gr.Textbox(label="Generated Scene Prompts", lines=20)
|
560 |
|
561 |
with gr.Row():
|
562 |
generate_scenes_btn = gr.Button("5. Generate Story Scenes", variant="primary")
|
563 |
|
564 |
with gr.Row():
|
565 |
-
|
566 |
-
label="
|
567 |
-
lines=
|
568 |
interactive=False
|
569 |
)
|
570 |
-
|
571 |
with gr.Row():
|
572 |
gallery = gr.Gallery(
|
573 |
label="Story Scenes",
|
@@ -576,6 +622,13 @@ def create_interface():
|
|
576 |
height="auto",
|
577 |
interactive=False
|
578 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
579 |
|
580 |
with gr.Row():
|
581 |
add_text_btn = gr.Button("6. Add Text to Scenes", variant="primary")
|
@@ -627,7 +680,7 @@ def create_interface():
|
|
627 |
generate_scenes_btn.click(
|
628 |
fn=generate_all_scenes,
|
629 |
inputs=[prompts_output],
|
630 |
-
outputs=[gallery, scene_prompts_display]
|
631 |
)
|
632 |
|
633 |
add_text_btn.click(
|
@@ -643,7 +696,6 @@ def create_interface():
|
|
643 |
)
|
644 |
|
645 |
return demo
|
646 |
-
|
647 |
if __name__ == "__main__":
|
648 |
demo = create_interface()
|
649 |
demo.launch()
|
|
|
284 |
|
285 |
generated_images = []
|
286 |
formatted_prompts = []
|
287 |
+
progress_messages = []
|
288 |
+
total_scenes = len([s for s in prompts_text.split('='*50) if s.strip()])
|
289 |
+
|
290 |
+
def update_progress():
|
291 |
+
"""Create a progress message showing completed/total scenes"""
|
292 |
+
completed = len(generated_images)
|
293 |
+
message = f"Generated {completed}/{total_scenes} scenes\n\n"
|
294 |
+
if progress_messages:
|
295 |
+
message += "\n".join(progress_messages[-3:]) # Show last 3 status messages
|
296 |
+
return message
|
297 |
|
298 |
sections = prompts_text.split('='*50)
|
299 |
|
300 |
+
for section_num, section in enumerate(sections, 1):
|
301 |
if not section.strip():
|
302 |
continue
|
303 |
|
|
|
314 |
if scene_prompt:
|
315 |
try:
|
316 |
clear_memory()
|
317 |
+
status_msg = f"🎨 Creating scene {section_num}: '{scene_prompt[:50]}...'"
|
318 |
+
progress_messages.append(status_msg)
|
319 |
+
|
320 |
+
# Yield progress update
|
321 |
+
yield generated_images, "\n\n".join(formatted_prompts), update_progress()
|
322 |
|
323 |
image = generate_story_image(scene_prompt)
|
324 |
|
|
|
331 |
# Verify array shape and type
|
332 |
if len(img_array.shape) == 3 and img_array.shape[2] == 3:
|
333 |
generated_images.append(img_array)
|
334 |
+
progress_messages.append(f"✅ Successfully completed scene {section_num}")
|
335 |
else:
|
336 |
+
progress_messages.append(f"❌ Error: Invalid image format for scene {section_num}")
|
337 |
else:
|
338 |
+
progress_messages.append(f"❌ Failed to generate scene {section_num}")
|
339 |
|
340 |
clear_memory()
|
341 |
|
342 |
except Exception as e:
|
343 |
+
error_msg = f"❌ Error generating scene {section_num}: {str(e)}"
|
344 |
+
progress_messages.append(error_msg)
|
345 |
clear_memory()
|
346 |
continue
|
347 |
+
|
348 |
+
# Yield progress update after each scene
|
349 |
+
yield generated_images, "\n\n".join(formatted_prompts), update_progress()
|
350 |
|
351 |
+
# Final status update
|
352 |
if not generated_images:
|
353 |
+
progress_messages.append("❌ No images were successfully generated")
|
354 |
+
else:
|
355 |
+
progress_messages.append(f"✅ Successfully completed all {len(generated_images)} scenes!")
|
356 |
|
357 |
+
# Final yield
|
358 |
+
yield generated_images, "\n\n".join(formatted_prompts), update_progress()
|
|
|
|
|
|
|
|
|
359 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
@spaces.GPU(duration=60)
|
361 |
def add_text_to_scenes(gallery_images, prompts_text):
|
362 |
if not isinstance(gallery_images, list):
|
363 |
return [], []
|
364 |
|
365 |
+
clear_memory()
|
366 |
+
|
367 |
sections = prompts_text.split('='*50)
|
368 |
overlaid_images = []
|
369 |
output_files = []
|
|
|
385 |
|
386 |
if paragraph and image_data is not None:
|
387 |
try:
|
388 |
+
# Handle tuple case (image, label) from gallery
|
389 |
+
if isinstance(image_data, tuple):
|
390 |
+
image_data = image_data[0]
|
391 |
+
|
392 |
+
# Convert numpy array to PIL Image
|
393 |
if isinstance(image_data, np.ndarray):
|
394 |
image = Image.fromarray(image_data)
|
395 |
else:
|
396 |
image = image_data
|
397 |
+
|
398 |
+
print(f"Processing image {i+1}, type: {type(image)}")
|
399 |
+
|
400 |
+
# Ensure we have a PIL Image
|
401 |
+
if not isinstance(image, Image.Image):
|
402 |
+
raise TypeError(f"Expected PIL Image, got {type(image)}")
|
403 |
|
404 |
overlaid_img = overlay_text_on_image(image, paragraph)
|
405 |
if overlaid_img is not None:
|
|
|
409 |
output_path = os.path.join(temp_dir, f"panel_{i+1}.png")
|
410 |
overlaid_img.save(output_path)
|
411 |
output_files.append(output_path)
|
412 |
+
print(f"Successfully processed image {i+1}")
|
413 |
except Exception as e:
|
414 |
print(f"Error processing image {i+1}: {str(e)}")
|
415 |
continue
|
416 |
|
417 |
+
if not overlaid_images:
|
418 |
+
print("No images were successfully processed")
|
419 |
+
else:
|
420 |
+
print(f"Successfully processed {len(overlaid_images)} images")
|
421 |
+
|
422 |
clear_memory()
|
423 |
return overlaid_images, output_files
|
424 |
|
425 |
+
def overlay_text_on_image(image, text):
|
426 |
+
"""Helper function to overlay text on an image"""
|
427 |
+
if image is None:
|
428 |
+
return None
|
429 |
+
|
430 |
+
try:
|
431 |
+
# Ensure we're working with RGB mode
|
432 |
+
img = image.convert('RGB')
|
433 |
+
draw = ImageDraw.Draw(img)
|
434 |
+
|
435 |
+
# Calculate font size based on image dimensions
|
436 |
+
font_size = int(img.width * 0.025)
|
437 |
+
try:
|
438 |
+
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", font_size)
|
439 |
+
except:
|
440 |
+
font = ImageFont.load_default()
|
441 |
+
|
442 |
+
# Calculate text positioning
|
443 |
+
y_position = int(img.height * 0.005)
|
444 |
+
x_margin = int(img.width * 0.005)
|
445 |
+
available_width = img.width - (2 * x_margin)
|
446 |
+
|
447 |
+
# Wrap text to fit image width
|
448 |
+
wrapped_text = textwrap.fill(text, width=int(available_width / (font_size * 0.6)))
|
449 |
+
|
450 |
+
# Add white outline to text for better readability
|
451 |
+
outline_color = (255, 255, 255)
|
452 |
+
text_color = (0, 0, 0)
|
453 |
+
offsets = [-2, -1, 1, 2]
|
454 |
+
|
455 |
+
# Draw text outline
|
456 |
+
for dx in offsets:
|
457 |
+
for dy in offsets:
|
458 |
+
draw.multiline_text(
|
459 |
+
(x_margin + dx, y_position + dy),
|
460 |
+
wrapped_text,
|
461 |
+
font=font,
|
462 |
+
fill=outline_color
|
463 |
+
)
|
464 |
+
|
465 |
+
# Draw main text
|
466 |
+
draw.multiline_text(
|
467 |
+
(x_margin, y_position),
|
468 |
+
wrapped_text,
|
469 |
+
font=font,
|
470 |
+
fill=text_color
|
471 |
+
)
|
472 |
+
|
473 |
+
return img
|
474 |
+
|
475 |
+
except Exception as e:
|
476 |
+
print(f"Error in overlay_text_on_image: {e}")
|
477 |
+
return None
|
478 |
+
|
479 |
def generate_combined_audio_from_story(story_text, voice='af_heart', speed=1):
|
480 |
clear_memory()
|
481 |
|
|
|
601 |
|
602 |
with gr.Row():
|
603 |
prompts_btn = gr.Button("4. Generate Scene Prompts")
|
604 |
+
with gr.Row():
|
605 |
prompts_output = gr.Textbox(label="Generated Scene Prompts", lines=20)
|
606 |
|
607 |
with gr.Row():
|
608 |
generate_scenes_btn = gr.Button("5. Generate Story Scenes", variant="primary")
|
609 |
|
610 |
with gr.Row():
|
611 |
+
scene_progress = gr.Textbox(
|
612 |
+
label="Generation Progress",
|
613 |
+
lines=6,
|
614 |
interactive=False
|
615 |
)
|
616 |
+
|
617 |
with gr.Row():
|
618 |
gallery = gr.Gallery(
|
619 |
label="Story Scenes",
|
|
|
622 |
height="auto",
|
623 |
interactive=False
|
624 |
)
|
625 |
+
|
626 |
+
with gr.Row():
|
627 |
+
scene_prompts_display = gr.Textbox(
|
628 |
+
label="Scene Descriptions",
|
629 |
+
lines=8,
|
630 |
+
interactive=False
|
631 |
+
)
|
632 |
|
633 |
with gr.Row():
|
634 |
add_text_btn = gr.Button("6. Add Text to Scenes", variant="primary")
|
|
|
680 |
generate_scenes_btn.click(
|
681 |
fn=generate_all_scenes,
|
682 |
inputs=[prompts_output],
|
683 |
+
outputs=[gallery, scene_prompts_display, scene_progress]
|
684 |
)
|
685 |
|
686 |
add_text_btn.click(
|
|
|
696 |
)
|
697 |
|
698 |
return demo
|
|
|
699 |
if __name__ == "__main__":
|
700 |
demo = create_interface()
|
701 |
demo.launch()
|