Spaces:
Running
Running
burtenshaw
commited on
Commit
·
99f7dee
1
Parent(s):
de93716
fix status updates
Browse files- app/app.py +72 -65
app/app.py
CHANGED
@@ -287,7 +287,7 @@ def step1_fetch_and_generate_presentation(
|
|
287 |
logger.info(f"Step 1: Fetching & Generating for {url}")
|
288 |
|
289 |
status_update = f"Starting Step 1: Fetching content from {url}..."
|
290 |
-
yield
|
291 |
|
292 |
# --- Cache Check ---
|
293 |
try:
|
@@ -340,9 +340,9 @@ def step1_fetch_and_generate_presentation(
|
|
340 |
status_update = (
|
341 |
"Loaded presentation from cache. Preparing editor..."
|
342 |
)
|
343 |
-
yield
|
344 |
logger.info(f"Using cached data for {len(slides_data)} slides.")
|
345 |
-
#
|
346 |
yield (
|
347 |
gr.update(value=status_update),
|
348 |
temp_dir,
|
@@ -370,14 +370,14 @@ def step1_fetch_and_generate_presentation(
|
|
370 |
raise gr.Error("LLM Client not initialized. Check API Key.")
|
371 |
|
372 |
status_update = "Fetching webpage content..."
|
373 |
-
yield
|
374 |
web_content = fetch_webpage_content(url)
|
375 |
if not web_content:
|
376 |
raise gr.Error("Failed to fetch or parse content from the URL.")
|
377 |
|
378 |
progress(0.3, desc="Generating presentation with LLM...")
|
379 |
status_update = "Generating presentation with LLM..."
|
380 |
-
yield
|
381 |
try:
|
382 |
presentation_md = generate_presentation_with_llm(
|
383 |
hf_client, LLM_MODEL, PRESENTATION_PROMPT, web_content, url
|
@@ -402,7 +402,7 @@ def step1_fetch_and_generate_presentation(
|
|
402 |
|
403 |
progress(0.7, desc="Parsing presentation slides...")
|
404 |
status_update = "Parsing presentation slides..."
|
405 |
-
yield
|
406 |
slides_data = parse_presentation_markdown(presentation_md)
|
407 |
if not slides_data:
|
408 |
logger.error("Parsing markdown resulted in zero slides.")
|
@@ -446,10 +446,10 @@ def step1_fetch_and_generate_presentation(
|
|
446 |
|
447 |
progress(0.9, desc="Preparing editor...")
|
448 |
status_update = "Generated presentation. Preparing editor..."
|
449 |
-
yield
|
450 |
logger.info(f"Prepared data for {len(slides_data)} slides.")
|
451 |
|
452 |
-
#
|
453 |
yield (
|
454 |
gr.update(value=status_update),
|
455 |
temp_dir,
|
@@ -463,18 +463,18 @@ def step1_fetch_and_generate_presentation(
|
|
463 |
except Exception as e:
|
464 |
logger.error(f"Error in step 1 (fetch/generate): {e}", exc_info=True)
|
465 |
status_update = f"Error during presentation setup: {e}"
|
466 |
-
yield
|
467 |
-
#
|
468 |
yield (
|
469 |
gr.update(value=status_update),
|
470 |
None,
|
471 |
None,
|
472 |
[],
|
473 |
-
gr.update(),
|
474 |
-
gr.update(),
|
475 |
-
gr.update(interactive=True),
|
476 |
)
|
477 |
-
#
|
478 |
# raise gr.Error(f"Error during presentation setup: {e}")
|
479 |
|
480 |
|
@@ -491,7 +491,7 @@ def step2_build_slides(
|
|
491 |
raise gr.Error("Session state missing.")
|
492 |
logger.info("Step 2: Building Slides (PDF + Images)")
|
493 |
status_update = "Starting Step 2: Building slides..."
|
494 |
-
yield
|
495 |
|
496 |
num_slides = len(state_slides_data)
|
497 |
MAX_SLIDES = 20
|
@@ -505,7 +505,7 @@ def step2_build_slides(
|
|
505 |
|
506 |
progress(0.1, desc="Saving edited markdown...")
|
507 |
status_update = "Saving edited markdown..."
|
508 |
-
yield
|
509 |
updated_slides = []
|
510 |
for i in range(num_slides):
|
511 |
updated_slides.append(
|
@@ -518,20 +518,21 @@ def step2_build_slides(
|
|
518 |
logger.info(f"Saved edited markdown: {state_md_path}")
|
519 |
except IOError as e:
|
520 |
status_update = f"Failed to save markdown: {e}"
|
521 |
-
yield
|
|
|
522 |
yield (
|
523 |
gr.update(value=status_update),
|
524 |
None,
|
525 |
[],
|
526 |
gr.update(),
|
|
|
527 |
gr.update(),
|
528 |
-
|
529 |
-
)
|
530 |
raise gr.Error(f"Failed to save markdown: {e}")
|
531 |
|
532 |
progress(0.3, desc="Generating PDF...")
|
533 |
status_update = "Generating PDF..."
|
534 |
-
yield
|
535 |
pdf_output_path = os.path.join(state_temp_dir, "presentation.pdf")
|
536 |
try:
|
537 |
generated_pdf_path = generate_pdf_from_markdown(state_md_path, pdf_output_path)
|
@@ -539,7 +540,8 @@ def step2_build_slides(
|
|
539 |
raise gr.Error("PDF generation failed (check logs).")
|
540 |
except gr.Error as e:
|
541 |
status_update = f"PDF Generation Error: {e}"
|
542 |
-
yield
|
|
|
543 |
yield (
|
544 |
gr.update(value=status_update),
|
545 |
None,
|
@@ -547,11 +549,12 @@ def step2_build_slides(
|
|
547 |
gr.update(),
|
548 |
gr.update(visible=True),
|
549 |
gr.update(),
|
550 |
-
)
|
551 |
raise e
|
552 |
except Exception as e:
|
553 |
status_update = f"Unexpected PDF Error: {e}"
|
554 |
-
yield
|
|
|
555 |
yield (
|
556 |
gr.update(value=status_update),
|
557 |
None,
|
@@ -559,12 +562,12 @@ def step2_build_slides(
|
|
559 |
gr.update(),
|
560 |
gr.update(visible=True),
|
561 |
gr.update(),
|
562 |
-
)
|
563 |
raise gr.Error(f"Unexpected error generating PDF: {e}")
|
564 |
|
565 |
progress(0.7, desc="Converting PDF to images...")
|
566 |
status_update = "Converting PDF to images..."
|
567 |
-
yield
|
568 |
pdf_images = []
|
569 |
try:
|
570 |
pdf_images = convert_pdf_to_images(
|
@@ -581,7 +584,8 @@ def step2_build_slides(
|
|
581 |
except Exception as e:
|
582 |
logger.error(f"Error converting PDF to images: {e}", exc_info=True)
|
583 |
status_update = f"Failed to convert PDF to images: {e}"
|
584 |
-
yield
|
|
|
585 |
yield (
|
586 |
gr.update(value=status_update),
|
587 |
generated_pdf_path,
|
@@ -589,7 +593,7 @@ def step2_build_slides(
|
|
589 |
gr.update(),
|
590 |
gr.update(visible=True),
|
591 |
gr.update(value=generated_pdf_path, visible=True),
|
592 |
-
)
|
593 |
# Proceed without images? Or raise error? Let's raise.
|
594 |
raise gr.Error(f"Failed to convert PDF to images: {e}")
|
595 |
|
@@ -655,7 +659,7 @@ def step3_generate_audio(*args, progress=gr.Progress(track_tqdm=True)):
|
|
655 |
|
656 |
logger.info(f"Processing {num_slides} slides for audio generation.")
|
657 |
status_update = "Starting Step 3: Generating audio..."
|
658 |
-
yield
|
659 |
|
660 |
audio_dir = os.path.join(state_temp_dir, "audio")
|
661 |
os.makedirs(audio_dir, exist_ok=True)
|
@@ -665,7 +669,7 @@ def step3_generate_audio(*args, progress=gr.Progress(track_tqdm=True)):
|
|
665 |
# but ensures the audio matches the *latest* notes displayed.
|
666 |
progress(0.1, desc="Saving latest notes...")
|
667 |
status_update = "Saving latest notes..."
|
668 |
-
yield
|
669 |
updated_slides_data = []
|
670 |
for i in range(num_slides):
|
671 |
updated_slides_data.append(
|
@@ -685,17 +689,11 @@ def step3_generate_audio(*args, progress=gr.Progress(track_tqdm=True)):
|
|
685 |
warning_msg = f"Warning: Could not save latest notes to markdown file: {e}"
|
686 |
gr.Warning(warning_msg)
|
687 |
status_update += f" ({warning_msg})"
|
688 |
-
yield
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
[],
|
694 |
-
gr.update(),
|
695 |
-
gr.update(visible=True),
|
696 |
-
gr.update(),
|
697 |
-
)
|
698 |
-
raise gr.Error(f"Failed to save updated markdown before audio gen: {e}")
|
699 |
|
700 |
generated_audio_paths = ["" for _ in range(num_slides)]
|
701 |
audio_generation_failed = False
|
@@ -710,7 +708,7 @@ def step3_generate_audio(*args, progress=gr.Progress(track_tqdm=True)):
|
|
710 |
desc=f"Audio slide {slide_num}/{num_slides}",
|
711 |
)
|
712 |
status_update = f"Generating audio for slide {slide_num}/{num_slides}..."
|
713 |
-
yield
|
714 |
|
715 |
output_file_path = Path(audio_dir) / f"{slide_num}.wav"
|
716 |
if not note_text or not note_text.strip():
|
@@ -774,6 +772,7 @@ def step3_generate_audio(*args, progress=gr.Progress(track_tqdm=True)):
|
|
774 |
status_update = f"Step 3 Complete: {info_msg}"
|
775 |
|
776 |
# Return tuple including status update + original outputs
|
|
|
777 |
yield (
|
778 |
gr.update(value=status_update),
|
779 |
audio_dir,
|
@@ -803,7 +802,7 @@ def step4_generate_video(
|
|
803 |
|
804 |
video_output_path = os.path.join(state_temp_dir, "final_presentation.mp4")
|
805 |
status_update = "Starting Step 4: Generating video..."
|
806 |
-
yield
|
807 |
|
808 |
progress(0.1, desc="Preparing video components...")
|
809 |
pdf_images = [] # Initialize to ensure cleanup happens
|
@@ -820,7 +819,7 @@ def step4_generate_video(
|
|
820 |
# Convert PDF to images
|
821 |
progress(0.2, desc="Converting PDF to images...")
|
822 |
status_update = "Converting PDF back to images for video..."
|
823 |
-
yield
|
824 |
pdf_images = convert_pdf_to_images(state_pdf_path, dpi=150)
|
825 |
if not pdf_images:
|
826 |
raise gr.Error(f"Failed to convert PDF ({state_pdf_path}) to images.")
|
@@ -832,12 +831,12 @@ def step4_generate_video(
|
|
832 |
logger.warning(warning_msg)
|
833 |
status_update += f" ({warning_msg})"
|
834 |
# yield status_update # Old yield
|
835 |
-
yield
|
836 |
|
837 |
progress(0.5, desc="Creating individual video clips...")
|
838 |
status_update = "Creating individual video clips..."
|
839 |
# yield status_update # Old yield
|
840 |
-
yield
|
841 |
buffer_seconds = 1.0
|
842 |
output_fps = 10
|
843 |
video_clips = create_video_clips(
|
@@ -850,7 +849,7 @@ def step4_generate_video(
|
|
850 |
progress(0.8, desc="Concatenating clips...")
|
851 |
status_update = "Concatenating clips into final video..."
|
852 |
# yield status_update # Old yield
|
853 |
-
yield
|
854 |
concatenate_clips(video_clips, video_output_path, output_fps)
|
855 |
|
856 |
logger.info(f"Video concatenation complete: {video_output_path}")
|
@@ -858,7 +857,7 @@ def step4_generate_video(
|
|
858 |
progress(0.95, desc="Cleaning up temp images...")
|
859 |
status_update = "Cleaning up temporary image files..."
|
860 |
# yield status_update # Old yield
|
861 |
-
yield
|
862 |
cleanup_temp_files(pdf_images) # Pass the list of image paths
|
863 |
|
864 |
except Exception as e:
|
@@ -866,8 +865,13 @@ def step4_generate_video(
|
|
866 |
cleanup_temp_files(pdf_images)
|
867 |
logger.error(f"Video generation failed: {e}", exc_info=True)
|
868 |
status_update = f"Video generation failed: {e}"
|
869 |
-
yield
|
870 |
-
yield
|
|
|
|
|
|
|
|
|
|
|
871 |
raise gr.Error(f"Video generation failed: {e}")
|
872 |
|
873 |
info_msg = f"Video generated: {os.path.basename(video_output_path)}"
|
@@ -1132,10 +1136,11 @@ with gr.Blocks(
|
|
1132 |
show_progress="full",
|
1133 |
).then(
|
1134 |
fn=lambda s_data: (
|
1135 |
-
gr.update(
|
1136 |
-
|
1137 |
-
|
1138 |
-
|
|
|
1139 |
upd
|
1140 |
for i, slide in enumerate(s_data)
|
1141 |
if i < MAX_SLIDES
|
@@ -1157,8 +1162,8 @@ with gr.Blocks(
|
|
1157 |
upd
|
1158 |
for i in range(len(s_data), MAX_SLIDES)
|
1159 |
for upd in [gr.update(visible=False)] * 7
|
1160 |
-
]
|
1161 |
-
), #
|
1162 |
inputs=[state_slides_data],
|
1163 |
outputs=[status_textbox] + all_editor_components, # Add status_textbox output
|
1164 |
show_progress="hidden",
|
@@ -1185,17 +1190,18 @@ with gr.Blocks(
|
|
1185 |
show_progress="full",
|
1186 |
).then(
|
1187 |
fn=lambda image_paths: (
|
1188 |
-
gr.update(
|
1189 |
-
|
1190 |
-
|
1191 |
-
|
|
|
1192 |
gr.update(
|
1193 |
value=image_paths[i] if i < len(image_paths) else None,
|
1194 |
visible=(i < len(image_paths)),
|
1195 |
)
|
1196 |
for i in range(MAX_SLIDES)
|
1197 |
-
]
|
1198 |
-
), #
|
1199 |
inputs=[state_pdf_image_paths],
|
1200 |
outputs=[status_textbox] + all_slide_images, # Add status_textbox output
|
1201 |
show_progress="hidden",
|
@@ -1223,12 +1229,13 @@ with gr.Blocks(
|
|
1223 |
outputs=step3_outputs,
|
1224 |
show_progress="full",
|
1225 |
).then(
|
1226 |
-
lambda: (
|
1227 |
gr.update(value="Audio generated. Proceed to Step 4."),
|
1228 |
gr.update(selected=3),
|
1229 |
-
), #
|
1230 |
-
|
1231 |
-
|
|
|
1232 |
)
|
1233 |
|
1234 |
# Step 4 Click Handler
|
|
|
287 |
logger.info(f"Step 1: Fetching & Generating for {url}")
|
288 |
|
289 |
status_update = f"Starting Step 1: Fetching content from {url}..."
|
290 |
+
yield status_update
|
291 |
|
292 |
# --- Cache Check ---
|
293 |
try:
|
|
|
340 |
status_update = (
|
341 |
"Loaded presentation from cache. Preparing editor..."
|
342 |
)
|
343 |
+
yield status_update
|
344 |
logger.info(f"Using cached data for {len(slides_data)} slides.")
|
345 |
+
# Final yield must match outputs list
|
346 |
yield (
|
347 |
gr.update(value=status_update),
|
348 |
temp_dir,
|
|
|
370 |
raise gr.Error("LLM Client not initialized. Check API Key.")
|
371 |
|
372 |
status_update = "Fetching webpage content..."
|
373 |
+
yield status_update
|
374 |
web_content = fetch_webpage_content(url)
|
375 |
if not web_content:
|
376 |
raise gr.Error("Failed to fetch or parse content from the URL.")
|
377 |
|
378 |
progress(0.3, desc="Generating presentation with LLM...")
|
379 |
status_update = "Generating presentation with LLM..."
|
380 |
+
yield status_update
|
381 |
try:
|
382 |
presentation_md = generate_presentation_with_llm(
|
383 |
hf_client, LLM_MODEL, PRESENTATION_PROMPT, web_content, url
|
|
|
402 |
|
403 |
progress(0.7, desc="Parsing presentation slides...")
|
404 |
status_update = "Parsing presentation slides..."
|
405 |
+
yield status_update
|
406 |
slides_data = parse_presentation_markdown(presentation_md)
|
407 |
if not slides_data:
|
408 |
logger.error("Parsing markdown resulted in zero slides.")
|
|
|
446 |
|
447 |
progress(0.9, desc="Preparing editor...")
|
448 |
status_update = "Generated presentation. Preparing editor..."
|
449 |
+
yield status_update
|
450 |
logger.info(f"Prepared data for {len(slides_data)} slides.")
|
451 |
|
452 |
+
# Final yield must match outputs list
|
453 |
yield (
|
454 |
gr.update(value=status_update),
|
455 |
temp_dir,
|
|
|
463 |
except Exception as e:
|
464 |
logger.error(f"Error in step 1 (fetch/generate): {e}", exc_info=True)
|
465 |
status_update = f"Error during presentation setup: {e}"
|
466 |
+
yield status_update
|
467 |
+
# Yield a final tuple matching outputs, indicating error state if possible
|
468 |
yield (
|
469 |
gr.update(value=status_update),
|
470 |
None,
|
471 |
None,
|
472 |
[],
|
473 |
+
gr.update(visible=False), # Keep editor hidden
|
474 |
+
gr.update(visible=False), # Keep build button hidden
|
475 |
+
gr.update(interactive=True), # Re-enable fetch button
|
476 |
)
|
477 |
+
# Do not re-raise if we want the Gradio app to stay alive
|
478 |
# raise gr.Error(f"Error during presentation setup: {e}")
|
479 |
|
480 |
|
|
|
491 |
raise gr.Error("Session state missing.")
|
492 |
logger.info("Step 2: Building Slides (PDF + Images)")
|
493 |
status_update = "Starting Step 2: Building slides..."
|
494 |
+
yield status_update
|
495 |
|
496 |
num_slides = len(state_slides_data)
|
497 |
MAX_SLIDES = 20
|
|
|
505 |
|
506 |
progress(0.1, desc="Saving edited markdown...")
|
507 |
status_update = "Saving edited markdown..."
|
508 |
+
yield status_update
|
509 |
updated_slides = []
|
510 |
for i in range(num_slides):
|
511 |
updated_slides.append(
|
|
|
518 |
logger.info(f"Saved edited markdown: {state_md_path}")
|
519 |
except IOError as e:
|
520 |
status_update = f"Failed to save markdown: {e}"
|
521 |
+
yield status_update
|
522 |
+
# Final yield must match outputs
|
523 |
yield (
|
524 |
gr.update(value=status_update),
|
525 |
None,
|
526 |
[],
|
527 |
gr.update(),
|
528 |
+
gr.update(visible=True),
|
529 |
gr.update(),
|
530 |
+
) # Keep build button visible
|
|
|
531 |
raise gr.Error(f"Failed to save markdown: {e}")
|
532 |
|
533 |
progress(0.3, desc="Generating PDF...")
|
534 |
status_update = "Generating PDF..."
|
535 |
+
yield status_update
|
536 |
pdf_output_path = os.path.join(state_temp_dir, "presentation.pdf")
|
537 |
try:
|
538 |
generated_pdf_path = generate_pdf_from_markdown(state_md_path, pdf_output_path)
|
|
|
540 |
raise gr.Error("PDF generation failed (check logs).")
|
541 |
except gr.Error as e:
|
542 |
status_update = f"PDF Generation Error: {e}"
|
543 |
+
yield status_update
|
544 |
+
# Final yield must match outputs
|
545 |
yield (
|
546 |
gr.update(value=status_update),
|
547 |
None,
|
|
|
549 |
gr.update(),
|
550 |
gr.update(visible=True),
|
551 |
gr.update(),
|
552 |
+
) # Keep build button visible
|
553 |
raise e
|
554 |
except Exception as e:
|
555 |
status_update = f"Unexpected PDF Error: {e}"
|
556 |
+
yield status_update
|
557 |
+
# Final yield must match outputs
|
558 |
yield (
|
559 |
gr.update(value=status_update),
|
560 |
None,
|
|
|
562 |
gr.update(),
|
563 |
gr.update(visible=True),
|
564 |
gr.update(),
|
565 |
+
) # Keep build button visible
|
566 |
raise gr.Error(f"Unexpected error generating PDF: {e}")
|
567 |
|
568 |
progress(0.7, desc="Converting PDF to images...")
|
569 |
status_update = "Converting PDF to images..."
|
570 |
+
yield status_update
|
571 |
pdf_images = []
|
572 |
try:
|
573 |
pdf_images = convert_pdf_to_images(
|
|
|
584 |
except Exception as e:
|
585 |
logger.error(f"Error converting PDF to images: {e}", exc_info=True)
|
586 |
status_update = f"Failed to convert PDF to images: {e}"
|
587 |
+
yield status_update
|
588 |
+
# Final yield must match outputs
|
589 |
yield (
|
590 |
gr.update(value=status_update),
|
591 |
generated_pdf_path,
|
|
|
593 |
gr.update(),
|
594 |
gr.update(visible=True),
|
595 |
gr.update(value=generated_pdf_path, visible=True),
|
596 |
+
) # Keep build button visible
|
597 |
# Proceed without images? Or raise error? Let's raise.
|
598 |
raise gr.Error(f"Failed to convert PDF to images: {e}")
|
599 |
|
|
|
659 |
|
660 |
logger.info(f"Processing {num_slides} slides for audio generation.")
|
661 |
status_update = "Starting Step 3: Generating audio..."
|
662 |
+
yield status_update
|
663 |
|
664 |
audio_dir = os.path.join(state_temp_dir, "audio")
|
665 |
os.makedirs(audio_dir, exist_ok=True)
|
|
|
669 |
# but ensures the audio matches the *latest* notes displayed.
|
670 |
progress(0.1, desc="Saving latest notes...")
|
671 |
status_update = "Saving latest notes..."
|
672 |
+
yield status_update
|
673 |
updated_slides_data = []
|
674 |
for i in range(num_slides):
|
675 |
updated_slides_data.append(
|
|
|
689 |
warning_msg = f"Warning: Could not save latest notes to markdown file: {e}"
|
690 |
gr.Warning(warning_msg)
|
691 |
status_update += f" ({warning_msg})"
|
692 |
+
yield status_update # Yield the warning status string
|
693 |
+
# Note: We continue processing audio even if saving markdown fails
|
694 |
+
# If we need to stop and return final state, do it here:
|
695 |
+
# yield (gr.update(value=status_update), state_audio_dir, gr.update(), gr.update(visible=True), *[gr.update()]*N, *[gr.update()]*N)
|
696 |
+
# raise gr.Error(f"Failed to save updated markdown before audio gen: {e}") # Old raise
|
|
|
|
|
|
|
|
|
|
|
|
|
697 |
|
698 |
generated_audio_paths = ["" for _ in range(num_slides)]
|
699 |
audio_generation_failed = False
|
|
|
708 |
desc=f"Audio slide {slide_num}/{num_slides}",
|
709 |
)
|
710 |
status_update = f"Generating audio for slide {slide_num}/{num_slides}..."
|
711 |
+
yield status_update
|
712 |
|
713 |
output_file_path = Path(audio_dir) / f"{slide_num}.wav"
|
714 |
if not note_text or not note_text.strip():
|
|
|
772 |
status_update = f"Step 3 Complete: {info_msg}"
|
773 |
|
774 |
# Return tuple including status update + original outputs
|
775 |
+
# Final yield must match outputs list
|
776 |
yield (
|
777 |
gr.update(value=status_update),
|
778 |
audio_dir,
|
|
|
802 |
|
803 |
video_output_path = os.path.join(state_temp_dir, "final_presentation.mp4")
|
804 |
status_update = "Starting Step 4: Generating video..."
|
805 |
+
yield status_update
|
806 |
|
807 |
progress(0.1, desc="Preparing video components...")
|
808 |
pdf_images = [] # Initialize to ensure cleanup happens
|
|
|
819 |
# Convert PDF to images
|
820 |
progress(0.2, desc="Converting PDF to images...")
|
821 |
status_update = "Converting PDF back to images for video..."
|
822 |
+
yield status_update
|
823 |
pdf_images = convert_pdf_to_images(state_pdf_path, dpi=150)
|
824 |
if not pdf_images:
|
825 |
raise gr.Error(f"Failed to convert PDF ({state_pdf_path}) to images.")
|
|
|
831 |
logger.warning(warning_msg)
|
832 |
status_update += f" ({warning_msg})"
|
833 |
# yield status_update # Old yield
|
834 |
+
yield status_update # Yield the warning status string
|
835 |
|
836 |
progress(0.5, desc="Creating individual video clips...")
|
837 |
status_update = "Creating individual video clips..."
|
838 |
# yield status_update # Old yield
|
839 |
+
yield status_update
|
840 |
buffer_seconds = 1.0
|
841 |
output_fps = 10
|
842 |
video_clips = create_video_clips(
|
|
|
849 |
progress(0.8, desc="Concatenating clips...")
|
850 |
status_update = "Concatenating clips into final video..."
|
851 |
# yield status_update # Old yield
|
852 |
+
yield status_update
|
853 |
concatenate_clips(video_clips, video_output_path, output_fps)
|
854 |
|
855 |
logger.info(f"Video concatenation complete: {video_output_path}")
|
|
|
857 |
progress(0.95, desc="Cleaning up temp images...")
|
858 |
status_update = "Cleaning up temporary image files..."
|
859 |
# yield status_update # Old yield
|
860 |
+
yield status_update
|
861 |
cleanup_temp_files(pdf_images) # Pass the list of image paths
|
862 |
|
863 |
except Exception as e:
|
|
|
865 |
cleanup_temp_files(pdf_images)
|
866 |
logger.error(f"Video generation failed: {e}", exc_info=True)
|
867 |
status_update = f"Video generation failed: {e}"
|
868 |
+
yield status_update
|
869 |
+
# Final yield must match outputs
|
870 |
+
yield (
|
871 |
+
gr.update(value=status_update),
|
872 |
+
gr.update(),
|
873 |
+
gr.update(visible=True),
|
874 |
+
) # Keep button visible
|
875 |
raise gr.Error(f"Video generation failed: {e}")
|
876 |
|
877 |
info_msg = f"Video generated: {os.path.basename(video_output_path)}"
|
|
|
1136 |
show_progress="full",
|
1137 |
).then(
|
1138 |
fn=lambda s_data: (
|
1139 |
+
gr.update(
|
1140 |
+
value="Editor populated. Proceed to Step 2."
|
1141 |
+
), # Status update first
|
1142 |
+
# Then unpack the list/tuple of editor updates
|
1143 |
+
*[
|
1144 |
upd
|
1145 |
for i, slide in enumerate(s_data)
|
1146 |
if i < MAX_SLIDES
|
|
|
1162 |
upd
|
1163 |
for i in range(len(s_data), MAX_SLIDES)
|
1164 |
for upd in [gr.update(visible=False)] * 7
|
1165 |
+
],
|
1166 |
+
), # Correctly construct the output tuple
|
1167 |
inputs=[state_slides_data],
|
1168 |
outputs=[status_textbox] + all_editor_components, # Add status_textbox output
|
1169 |
show_progress="hidden",
|
|
|
1190 |
show_progress="full",
|
1191 |
).then(
|
1192 |
fn=lambda image_paths: (
|
1193 |
+
gr.update(
|
1194 |
+
value="Slide images updated. Proceed to Step 3."
|
1195 |
+
), # Status update first
|
1196 |
+
# Then unpack the list/tuple of image updates
|
1197 |
+
*[
|
1198 |
gr.update(
|
1199 |
value=image_paths[i] if i < len(image_paths) else None,
|
1200 |
visible=(i < len(image_paths)),
|
1201 |
)
|
1202 |
for i in range(MAX_SLIDES)
|
1203 |
+
],
|
1204 |
+
), # Correctly construct the output tuple
|
1205 |
inputs=[state_pdf_image_paths],
|
1206 |
outputs=[status_textbox] + all_slide_images, # Add status_textbox output
|
1207 |
show_progress="hidden",
|
|
|
1229 |
outputs=step3_outputs,
|
1230 |
show_progress="full",
|
1231 |
).then(
|
1232 |
+
fn=lambda: (
|
1233 |
gr.update(value="Audio generated. Proceed to Step 4."),
|
1234 |
gr.update(selected=3),
|
1235 |
+
), # Status update is handled by the main function yield now
|
1236 |
+
# No inputs needed for this simple status update + tab switch
|
1237 |
+
outputs=[status_textbox, tabs_widget],
|
1238 |
+
show_progress="hidden",
|
1239 |
)
|
1240 |
|
1241 |
# Step 4 Click Handler
|