Tophness2022 commited on
Commit
ba35fb6
·
1 Parent(s): 8143bed

add save and exit, fix vace attachments

Browse files
Files changed (1) hide show
  1. wgp.py +176 -51
wgp.py CHANGED
@@ -31,6 +31,7 @@ from PIL import Image
31
  import zipfile
32
  import tempfile
33
  import atexit
 
34
  global_queue_ref = []
35
  AUTOSAVE_FILENAME = "queue.zip"
36
  PROMPT_VARS_MAX = 10
@@ -364,21 +365,23 @@ def save_queue_action(state):
364
 
365
  if not queue or len(queue) <=1 :
366
  gr.Info("Queue is empty. Nothing to save.")
367
- return None
368
 
369
  zip_buffer = io.BytesIO()
370
 
371
  with tempfile.TemporaryDirectory() as tmpdir:
372
  queue_manifest = []
373
- image_paths_in_zip = {}
374
 
375
  for task_index, task in enumerate(queue):
376
- if task is None or not isinstance(task, dict) or task_index == 0: continue
377
 
378
  params_copy = task.get('params', {}).copy()
379
  task_id_s = task.get('id', f"task_{task_index}")
380
 
381
  image_keys = ["image_start", "image_end", "image_refs"]
 
 
382
  for key in image_keys:
383
  images_pil = params_copy.get(key)
384
  if images_pil is None:
@@ -395,8 +398,8 @@ def save_queue_action(state):
395
  continue
396
 
397
  img_id = id(pil_image)
398
- if img_id in image_paths_in_zip:
399
- image_filenames_for_json.append(image_paths_in_zip[img_id])
400
  continue
401
 
402
  img_filename_in_zip = f"task{task_id_s}_{key}_{img_index}.png"
@@ -405,7 +408,8 @@ def save_queue_action(state):
405
  try:
406
  pil_image.save(img_save_path, "PNG")
407
  image_filenames_for_json.append(img_filename_in_zip)
408
- image_paths_in_zip[img_id] = img_filename_in_zip
 
409
  except Exception as e:
410
  print(f"Error saving image {img_filename_in_zip} for task {task_id_s}: {e}")
411
 
@@ -414,17 +418,47 @@ def save_queue_action(state):
414
  else:
415
  params_copy.pop(key, None)
416
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
 
418
  params_copy.pop('state', None)
419
  params_copy.pop('start_image_data_base64', None)
420
  params_copy.pop('end_image_data_base64', None)
421
  params_copy.pop('start_image_data', None)
422
  params_copy.pop('end_image_data', None)
 
 
423
 
424
  manifest_entry = {
425
  "id": task.get('id'),
426
  "params": params_copy,
427
  }
 
428
  queue_manifest.append(manifest_entry)
429
 
430
  manifest_path = os.path.join(tmpdir, "queue.json")
@@ -440,12 +474,13 @@ def save_queue_action(state):
440
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
441
  zf.write(manifest_path, arcname="queue.json")
442
 
443
- for saved_img_rel_path in image_paths_in_zip.values():
444
- saved_img_abs_path = os.path.join(tmpdir, saved_img_rel_path)
445
- if os.path.exists(saved_img_abs_path):
446
- zf.write(saved_img_abs_path, arcname=saved_img_rel_path)
 
447
  else:
448
- print(f"Warning: Image file {saved_img_rel_path} not found during zipping.")
449
 
450
  zip_buffer.seek(0)
451
  zip_binary_content = zip_buffer.getvalue()
@@ -464,6 +499,8 @@ def load_queue_action(filepath, state):
464
  global task_id
465
  gen = get_gen_info(state)
466
  original_queue = gen.get("queue", [])
 
 
467
 
468
  if not filepath or not hasattr(filepath, 'name') or not Path(filepath.name).is_file():
469
  print("[load_queue_action] Warning: No valid file selected or file not found.")
@@ -476,6 +513,9 @@ def load_queue_action(filepath, state):
476
 
477
  try:
478
  print(f"[load_queue_action] Attempting to load queue from: {filepath.name}")
 
 
 
479
  with tempfile.TemporaryDirectory() as tmpdir:
480
  with zipfile.ZipFile(filepath.name, 'r') as zf:
481
  if "queue.json" not in zf.namelist(): raise ValueError("queue.json not found in zip file")
@@ -497,21 +537,29 @@ def load_queue_action(filepath, state):
497
  params = task_data.get('params', {})
498
  task_id_loaded = task_data.get('id', 0)
499
  max_id_in_file = max(max_id_in_file, task_id_loaded)
500
- loaded_pil_images = {}
501
- image_keys = ["image_start", "image_end", "image_refs"]
502
  params['state'] = state
503
 
 
 
 
 
 
 
504
  for key in image_keys:
505
  image_filenames = params.get(key)
506
  if image_filenames is None: continue
 
507
  is_list = isinstance(image_filenames, list)
508
  if not is_list: image_filenames = [image_filenames]
 
509
  loaded_pils = []
510
  for img_filename_in_zip in image_filenames:
511
- if not isinstance(img_filename_in_zip, str): continue
 
 
512
  img_load_path = os.path.join(tmpdir, img_filename_in_zip)
513
  if not os.path.exists(img_load_path):
514
- print(f"[load_queue_action] Image file not found during load: {img_load_path}")
515
  continue
516
  try:
517
  pil_image = Image.open(img_load_path)
@@ -519,30 +567,53 @@ def load_queue_action(filepath, state):
519
  converted_image = convert_image(pil_image)
520
  loaded_pils.append(converted_image)
521
  pil_image.close()
 
522
  except Exception as img_e:
523
  print(f"[load_queue_action] Error loading image {img_filename_in_zip}: {img_e}")
524
  if loaded_pils:
525
  params[key] = loaded_pils if is_list else loaded_pils[0]
526
  loaded_pil_images[key] = params[key]
527
- else: params.pop(key, None)
 
528
 
529
- primary_preview_pil, secondary_preview_pil = None, None
530
- start_prev_pil_list = loaded_pil_images.get("image_start")
531
- end_prev_pil_list = loaded_pil_images.get("image_end")
532
- ref_prev_pil_list = loaded_pil_images.get("image_refs")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
 
534
- if start_prev_pil_list:
535
- primary_preview_pil = start_prev_pil_list[0] if isinstance(start_prev_pil_list, list) and start_prev_pil_list else start_prev_pil_list if not isinstance(start_prev_pil_list, list) else None
536
- if end_prev_pil_list:
537
- secondary_preview_pil = end_prev_pil_list[0] if isinstance(end_prev_pil_list, list) and end_prev_pil_list else end_prev_pil_list if not isinstance(end_prev_pil_list, list) else None
538
- elif ref_prev_pil_list and isinstance(ref_prev_pil_list, list) and ref_prev_pil_list:
539
- primary_preview_pil = ref_prev_pil_list[0]
 
 
 
 
 
540
 
541
  start_b64 = [pil_to_base64_uri(primary_preview_pil, format="jpeg", quality=70)] if primary_preview_pil else None
542
  end_b64 = [pil_to_base64_uri(secondary_preview_pil, format="jpeg", quality=70)] if secondary_preview_pil else None
543
 
544
- top_level_start_image = loaded_pil_images.get("image_start")
545
- top_level_end_image = loaded_pil_images.get("image_end")
546
 
547
  runtime_task = {
548
  "id": task_id_loaded,
@@ -557,19 +628,20 @@ def load_queue_action(filepath, state):
557
  "end_image_data_base64": end_b64,
558
  }
559
  newly_loaded_queue.append(runtime_task)
560
- print(f"[load_queue_action] Processed task {task_index+1}/{len(loaded_manifest)}, ID: {task_id_loaded}")
561
 
562
  with lock:
563
  print("[load_queue_action] Acquiring lock to update state...")
564
  gen["queue"] = newly_loaded_queue[:]
565
  local_queue_copy_for_global_ref = gen["queue"][:]
566
- current_max_id_in_new_queue = max([t['id'] for t in newly_loaded_queue if 'id' in t] + [0])
567
 
568
- if current_max_id_in_new_queue > task_id:
569
- print(f"[load_queue_action] Updating global task_id from {task_id} to {current_max_id_in_new_queue + 1}")
570
- task_id = current_max_id_in_new_queue + 1
 
 
571
  else:
572
- print(f"[load_queue_action] Global task_id ({task_id}) is >= max in file ({current_max_id_in_new_queue}). Not changing task_id.")
573
 
574
  gen["prompts_max"] = len(newly_loaded_queue)
575
  print("[load_queue_action] State update complete. Releasing lock.")
@@ -593,11 +665,14 @@ def load_queue_action(filepath, state):
593
  return update_queue_data(original_queue)
594
  finally:
595
  if filepath and hasattr(filepath, 'name') and filepath.name and os.path.exists(filepath.name):
596
- try:
597
- pass
598
- except OSError as e:
599
- print(f"[load_queue_action] Info: Could not remove temp file {filepath.name}: {e}")
600
- pass
 
 
 
601
 
602
  def clear_queue_action(state):
603
  gen = get_gen_info(state)
@@ -636,6 +711,12 @@ def clear_queue_action(state):
636
 
637
  return update_queue_data([])
638
 
 
 
 
 
 
 
639
  def autosave_queue():
640
  global global_queue_ref
641
  if not global_queue_ref:
@@ -649,14 +730,20 @@ def autosave_queue():
649
 
650
  def _save_queue_to_file(queue_to_save, output_filename):
651
  if not queue_to_save: return None
 
652
  with tempfile.TemporaryDirectory() as tmpdir:
653
  queue_manifest = []
654
- image_paths_in_zip = {}
 
655
  for task_index, task in enumerate(queue_to_save):
656
- if task is None or not isinstance(task, dict): continue
 
657
  params_copy = task.get('params', {}).copy()
658
  task_id_s = task.get('id', f"task_{task_index}")
 
659
  image_keys = ["image_start", "image_end", "image_refs"]
 
 
660
  for key in image_keys:
661
  images_pil = params_copy.get(key)
662
  if images_pil is None: continue
@@ -666,36 +753,70 @@ def autosave_queue():
666
  for img_index, pil_image in enumerate(images_pil):
667
  if not isinstance(pil_image, Image.Image): continue
668
  img_id = id(pil_image)
669
- if img_id in image_paths_in_zip:
670
- image_filenames_for_json.append(image_paths_in_zip[img_id])
671
  continue
672
  img_filename_in_zip = f"task{task_id_s}_{key}_{img_index}.png"
673
  img_save_path = os.path.join(tmpdir, img_filename_in_zip)
674
  try:
675
  pil_image.save(img_save_path, "PNG")
676
  image_filenames_for_json.append(img_filename_in_zip)
677
- image_paths_in_zip[img_id] = img_filename_in_zip
678
  except Exception as e:
679
  print(f"Autosave error saving image {img_filename_in_zip}: {e}")
680
  if image_filenames_for_json:
681
  params_copy[key] = image_filenames_for_json if is_list else image_filenames_for_json[0]
682
  else:
683
  params_copy.pop(key, None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
684
  params_copy.pop('state', None)
685
  params_copy.pop('start_image_data_base64', None)
686
  params_copy.pop('end_image_data_base64', None)
 
 
 
687
  manifest_entry = {
688
- "id": task.get('id'), "params": params_copy,
 
689
  }
 
690
  queue_manifest.append(manifest_entry)
 
691
  manifest_path = os.path.join(tmpdir, "queue.json")
692
  with open(manifest_path, 'w', encoding='utf-8') as f: json.dump(queue_manifest, f, indent=4)
693
  with zipfile.ZipFile(output_filename, 'w', zipfile.ZIP_DEFLATED) as zf:
694
  zf.write(manifest_path, arcname="queue.json")
695
- for saved_img_rel_path in image_paths_in_zip.values():
696
- saved_img_abs_path = os.path.join(tmpdir, saved_img_rel_path)
697
- if os.path.exists(saved_img_abs_path):
698
- zf.write(saved_img_abs_path, arcname=saved_img_rel_path)
 
 
699
  return output_filename
700
  return None
701
 
@@ -1160,7 +1281,6 @@ text_encoder_choices = ["ckpts/models_t5_umt5-xxl-enc-bf16.safetensors", "ckpts/
1160
  server_config_filename = "wgp_config.json"
1161
 
1162
  if not os.path.isfile(server_config_filename) and os.path.isfile("gradio_config.json"):
1163
- import shutil
1164
  shutil.move("gradio_config.json", server_config_filename)
1165
 
1166
  if not Path(server_config_filename).is_file():
@@ -2965,7 +3085,6 @@ def download_loras():
2965
  lora_dir = get_lora_dir(get_model_filename("i2v"), quantizeTransformer)
2966
  log_path = os.path.join(lora_dir, "log.txt")
2967
  if not os.path.isfile(log_path):
2968
- import shutil
2969
  tmp_path = os.path.join(lora_dir, "tmp_lora_dowload")
2970
  import glob
2971
  snapshot_download(repo_id="DeepBeepMeep/Wan2.1", allow_patterns="loras_i2v/*", local_dir= tmp_path)
@@ -3483,6 +3602,7 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
3483
  save_queue_btn = gr.DownloadButton("Save Queue", size="sm")
3484
  load_queue_btn = gr.UploadButton("Load Queue", file_types=[".zip"], size="sm")
3485
  clear_queue_btn = gr.Button("Clear Queue", size="sm", variant="stop")
 
3486
  trigger_zip_download_js = """
3487
  (base64String) => {
3488
  if (!base64String) {
@@ -3567,6 +3687,11 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
3567
  inputs=None,
3568
  outputs=[current_gen_column, queue_accordion]
3569
  )
 
 
 
 
 
3570
 
3571
  extra_inputs = prompt_vars + [wizard_prompt, wizard_variables_var, wizard_prompt_activated_var, video_prompt_column, image_prompt_column,
3572
  prompt_column_advanced, prompt_column_wizard_vars, prompt_column_wizard, lset_name, advanced_row] # show_advanced presets_column,
 
31
  import zipfile
32
  import tempfile
33
  import atexit
34
+ import shutil
35
  global_queue_ref = []
36
  AUTOSAVE_FILENAME = "queue.zip"
37
  PROMPT_VARS_MAX = 10
 
365
 
366
  if not queue or len(queue) <=1 :
367
  gr.Info("Queue is empty. Nothing to save.")
368
+ return ""
369
 
370
  zip_buffer = io.BytesIO()
371
 
372
  with tempfile.TemporaryDirectory() as tmpdir:
373
  queue_manifest = []
374
+ file_paths_in_zip = {}
375
 
376
  for task_index, task in enumerate(queue):
377
+ if task is None or not isinstance(task, dict) or task.get('id') is None: continue
378
 
379
  params_copy = task.get('params', {}).copy()
380
  task_id_s = task.get('id', f"task_{task_index}")
381
 
382
  image_keys = ["image_start", "image_end", "image_refs"]
383
+ video_keys = ["video_guide", "video_mask"]
384
+
385
  for key in image_keys:
386
  images_pil = params_copy.get(key)
387
  if images_pil is None:
 
398
  continue
399
 
400
  img_id = id(pil_image)
401
+ if img_id in file_paths_in_zip:
402
+ image_filenames_for_json.append(file_paths_in_zip[img_id])
403
  continue
404
 
405
  img_filename_in_zip = f"task{task_id_s}_{key}_{img_index}.png"
 
408
  try:
409
  pil_image.save(img_save_path, "PNG")
410
  image_filenames_for_json.append(img_filename_in_zip)
411
+ file_paths_in_zip[img_id] = img_filename_in_zip
412
+ print(f"Saved image: {img_filename_in_zip}")
413
  except Exception as e:
414
  print(f"Error saving image {img_filename_in_zip} for task {task_id_s}: {e}")
415
 
 
418
  else:
419
  params_copy.pop(key, None)
420
 
421
+ for key in video_keys:
422
+ video_path_orig = params_copy.get(key)
423
+ if video_path_orig is None or not isinstance(video_path_orig, str):
424
+ continue
425
+
426
+ if video_path_orig in file_paths_in_zip:
427
+ params_copy[key] = file_paths_in_zip[video_path_orig]
428
+ continue
429
+
430
+ if not os.path.isfile(video_path_orig):
431
+ print(f"Warning: Video file not found for key '{key}' in task {task_id_s}: {video_path_orig}. Skipping video.")
432
+ params_copy.pop(key, None)
433
+ continue
434
+
435
+ _, extension = os.path.splitext(video_path_orig)
436
+ vid_filename_in_zip = f"task{task_id_s}_{key}{extension if extension else '.mp4'}"
437
+ vid_save_path = os.path.join(tmpdir, vid_filename_in_zip)
438
+
439
+ try:
440
+ shutil.copy2(video_path_orig, vid_save_path)
441
+ params_copy[key] = vid_filename_in_zip
442
+ file_paths_in_zip[video_path_orig] = vid_filename_in_zip
443
+ print(f"Copied video: {video_path_orig} -> {vid_filename_in_zip}")
444
+ except Exception as e:
445
+ print(f"Error copying video {video_path_orig} to {vid_filename_in_zip} for task {task_id_s}: {e}")
446
+ params_copy.pop(key, None)
447
+
448
 
449
  params_copy.pop('state', None)
450
  params_copy.pop('start_image_data_base64', None)
451
  params_copy.pop('end_image_data_base64', None)
452
  params_copy.pop('start_image_data', None)
453
  params_copy.pop('end_image_data', None)
454
+ task.pop('start_image_data', None)
455
+ task.pop('end_image_data', None)
456
 
457
  manifest_entry = {
458
  "id": task.get('id'),
459
  "params": params_copy,
460
  }
461
+ manifest_entry = {k: v for k, v in manifest_entry.items() if v is not None}
462
  queue_manifest.append(manifest_entry)
463
 
464
  manifest_path = os.path.join(tmpdir, "queue.json")
 
474
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
475
  zf.write(manifest_path, arcname="queue.json")
476
 
477
+ for file_id, saved_file_rel_path in file_paths_in_zip.items():
478
+ saved_file_abs_path = os.path.join(tmpdir, saved_file_rel_path)
479
+ if os.path.exists(saved_file_abs_path):
480
+ zf.write(saved_file_abs_path, arcname=saved_file_rel_path)
481
+ print(f"Adding to zip: {saved_file_rel_path}")
482
  else:
483
+ print(f"Warning: File {saved_file_rel_path} (ID: {file_id}) not found during zipping.")
484
 
485
  zip_buffer.seek(0)
486
  zip_binary_content = zip_buffer.getvalue()
 
499
  global task_id
500
  gen = get_gen_info(state)
501
  original_queue = gen.get("queue", [])
502
+ save_path_base = server_config.get("save_path", "outputs")
503
+ loaded_cache_dir = os.path.join(save_path_base, "_loaded_queue_cache")
504
 
505
  if not filepath or not hasattr(filepath, 'name') or not Path(filepath.name).is_file():
506
  print("[load_queue_action] Warning: No valid file selected or file not found.")
 
513
 
514
  try:
515
  print(f"[load_queue_action] Attempting to load queue from: {filepath.name}")
516
+ os.makedirs(loaded_cache_dir, exist_ok=True)
517
+ print(f"[load_queue_action] Using cache directory: {loaded_cache_dir}")
518
+
519
  with tempfile.TemporaryDirectory() as tmpdir:
520
  with zipfile.ZipFile(filepath.name, 'r') as zf:
521
  if "queue.json" not in zf.namelist(): raise ValueError("queue.json not found in zip file")
 
537
  params = task_data.get('params', {})
538
  task_id_loaded = task_data.get('id', 0)
539
  max_id_in_file = max(max_id_in_file, task_id_loaded)
 
 
540
  params['state'] = state
541
 
542
+ image_keys = ["image_start", "image_end", "image_refs"]
543
+ video_keys = ["video_guide", "video_mask"]
544
+
545
+ loaded_pil_images = {}
546
+ loaded_video_paths = {}
547
+
548
  for key in image_keys:
549
  image_filenames = params.get(key)
550
  if image_filenames is None: continue
551
+
552
  is_list = isinstance(image_filenames, list)
553
  if not is_list: image_filenames = [image_filenames]
554
+
555
  loaded_pils = []
556
  for img_filename_in_zip in image_filenames:
557
+ if not isinstance(img_filename_in_zip, str):
558
+ print(f"[load_queue_action] Warning: Non-string filename found for image key '{key}'. Skipping.")
559
+ continue
560
  img_load_path = os.path.join(tmpdir, img_filename_in_zip)
561
  if not os.path.exists(img_load_path):
562
+ print(f"[load_queue_action] Image file not found in extracted data: {img_load_path}. Skipping.")
563
  continue
564
  try:
565
  pil_image = Image.open(img_load_path)
 
567
  converted_image = convert_image(pil_image)
568
  loaded_pils.append(converted_image)
569
  pil_image.close()
570
+ print(f"Loaded image: {img_filename_in_zip} for key {key}")
571
  except Exception as img_e:
572
  print(f"[load_queue_action] Error loading image {img_filename_in_zip}: {img_e}")
573
  if loaded_pils:
574
  params[key] = loaded_pils if is_list else loaded_pils[0]
575
  loaded_pil_images[key] = params[key]
576
+ else:
577
+ params.pop(key, None)
578
 
579
+ for key in video_keys:
580
+ video_filename_in_zip = params.get(key)
581
+ if video_filename_in_zip is None or not isinstance(video_filename_in_zip, str):
582
+ continue
583
+
584
+ video_load_path = os.path.join(tmpdir, video_filename_in_zip)
585
+ if not os.path.exists(video_load_path):
586
+ print(f"[load_queue_action] Video file not found in extracted data: {video_load_path}. Skipping.")
587
+ params.pop(key, None)
588
+ continue
589
+
590
+ persistent_video_path = os.path.join(loaded_cache_dir, video_filename_in_zip)
591
+ try:
592
+ shutil.copy2(video_load_path, persistent_video_path)
593
+ params[key] = persistent_video_path
594
+ loaded_video_paths[key] = persistent_video_path
595
+ print(f"Loaded video: {video_filename_in_zip} -> {persistent_video_path}")
596
+ except Exception as vid_e:
597
+ print(f"[load_queue_action] Error copying video {video_filename_in_zip} to cache: {vid_e}")
598
+ params.pop(key, None)
599
 
600
+
601
+ primary_preview_pil_list = loaded_pil_images.get("image_start") or loaded_pil_images.get("image_refs")
602
+ secondary_preview_pil_list = loaded_pil_images.get("image_end")
603
+
604
+ primary_preview_pil = None
605
+ if primary_preview_pil_list:
606
+ primary_preview_pil = primary_preview_pil_list[0] if isinstance(primary_preview_pil_list, list) else primary_preview_pil_list
607
+
608
+ secondary_preview_pil = None
609
+ if secondary_preview_pil_list:
610
+ secondary_preview_pil = secondary_preview_pil_list[0] if isinstance(secondary_preview_pil_list, list) else secondary_preview_pil_list
611
 
612
  start_b64 = [pil_to_base64_uri(primary_preview_pil, format="jpeg", quality=70)] if primary_preview_pil else None
613
  end_b64 = [pil_to_base64_uri(secondary_preview_pil, format="jpeg", quality=70)] if secondary_preview_pil else None
614
 
615
+ top_level_start_image = params.get("image_start") or params.get("image_refs")
616
+ top_level_end_image = params.get("image_end")
617
 
618
  runtime_task = {
619
  "id": task_id_loaded,
 
628
  "end_image_data_base64": end_b64,
629
  }
630
  newly_loaded_queue.append(runtime_task)
631
+ print(f"[load_queue_action] Reconstructed task {task_index+1}/{len(loaded_manifest)}, ID: {task_id_loaded}")
632
 
633
  with lock:
634
  print("[load_queue_action] Acquiring lock to update state...")
635
  gen["queue"] = newly_loaded_queue[:]
636
  local_queue_copy_for_global_ref = gen["queue"][:]
 
637
 
638
+ current_max_id_in_new_queue = max([t['id'] for t in newly_loaded_queue if 'id' in t] + [0])
639
+ if current_max_id_in_new_queue >= task_id:
640
+ new_task_id = current_max_id_in_new_queue + 1
641
+ print(f"[load_queue_action] Updating global task_id from {task_id} to {new_task_id}")
642
+ task_id = new_task_id
643
  else:
644
+ print(f"[load_queue_action] Global task_id ({task_id}) is > max in file ({current_max_id_in_new_queue}). Not changing task_id.")
645
 
646
  gen["prompts_max"] = len(newly_loaded_queue)
647
  print("[load_queue_action] State update complete. Releasing lock.")
 
665
  return update_queue_data(original_queue)
666
  finally:
667
  if filepath and hasattr(filepath, 'name') and filepath.name and os.path.exists(filepath.name):
668
+ if tempfile.gettempdir() in os.path.abspath(filepath.name):
669
+ try:
670
+ os.remove(filepath.name)
671
+ print(f"[load_queue_action] Removed temporary upload file: {filepath.name}")
672
+ except OSError as e:
673
+ print(f"[load_queue_action] Info: Could not remove temp file {filepath.name}: {e}")
674
+ else:
675
+ print(f"[load_queue_action] Info: Did not remove non-temporary file: {filepath.name}")
676
 
677
  def clear_queue_action(state):
678
  gen = get_gen_info(state)
 
711
 
712
  return update_queue_data([])
713
 
714
+ def quit_application():
715
+ print("Save and Quit requested...")
716
+ autosave_queue()
717
+ import signal
718
+ os.kill(os.getpid(), signal.SIGINT)
719
+
720
  def autosave_queue():
721
  global global_queue_ref
722
  if not global_queue_ref:
 
730
 
731
  def _save_queue_to_file(queue_to_save, output_filename):
732
  if not queue_to_save: return None
733
+
734
  with tempfile.TemporaryDirectory() as tmpdir:
735
  queue_manifest = []
736
+ file_paths_in_zip = {}
737
+
738
  for task_index, task in enumerate(queue_to_save):
739
+ if task is None or not isinstance(task, dict) or task.get('id') is None: continue
740
+
741
  params_copy = task.get('params', {}).copy()
742
  task_id_s = task.get('id', f"task_{task_index}")
743
+
744
  image_keys = ["image_start", "image_end", "image_refs"]
745
+ video_keys = ["video_guide", "video_mask"]
746
+
747
  for key in image_keys:
748
  images_pil = params_copy.get(key)
749
  if images_pil is None: continue
 
753
  for img_index, pil_image in enumerate(images_pil):
754
  if not isinstance(pil_image, Image.Image): continue
755
  img_id = id(pil_image)
756
+ if img_id in file_paths_in_zip:
757
+ image_filenames_for_json.append(file_paths_in_zip[img_id])
758
  continue
759
  img_filename_in_zip = f"task{task_id_s}_{key}_{img_index}.png"
760
  img_save_path = os.path.join(tmpdir, img_filename_in_zip)
761
  try:
762
  pil_image.save(img_save_path, "PNG")
763
  image_filenames_for_json.append(img_filename_in_zip)
764
+ file_paths_in_zip[img_id] = img_filename_in_zip
765
  except Exception as e:
766
  print(f"Autosave error saving image {img_filename_in_zip}: {e}")
767
  if image_filenames_for_json:
768
  params_copy[key] = image_filenames_for_json if is_list else image_filenames_for_json[0]
769
  else:
770
  params_copy.pop(key, None)
771
+
772
+ for key in video_keys:
773
+ video_path_orig = params_copy.get(key)
774
+ if video_path_orig is None or not isinstance(video_path_orig, str):
775
+ continue
776
+
777
+ if video_path_orig in file_paths_in_zip:
778
+ params_copy[key] = file_paths_in_zip[video_path_orig]
779
+ continue
780
+
781
+ if not os.path.isfile(video_path_orig):
782
+ print(f"Warning (Autosave): Video file not found for key '{key}' in task {task_id_s}: {video_path_orig}. Skipping.")
783
+ params_copy.pop(key, None)
784
+ continue
785
+
786
+ _, extension = os.path.splitext(video_path_orig)
787
+ vid_filename_in_zip = f"task{task_id_s}_{key}{extension if extension else '.mp4'}"
788
+ vid_save_path = os.path.join(tmpdir, vid_filename_in_zip)
789
+
790
+ try:
791
+ shutil.copy2(video_path_orig, vid_save_path)
792
+ params_copy[key] = vid_filename_in_zip
793
+ file_paths_in_zip[video_path_orig] = vid_filename_in_zip
794
+ except Exception as e:
795
+ print(f"Error (Autosave) copying video {video_path_orig} to {vid_filename_in_zip} for task {task_id_s}: {e}")
796
+ params_copy.pop(key, None)
797
  params_copy.pop('state', None)
798
  params_copy.pop('start_image_data_base64', None)
799
  params_copy.pop('end_image_data_base64', None)
800
+ params_copy.pop('start_image_data', None)
801
+ params_copy.pop('end_image_data', None)
802
+
803
  manifest_entry = {
804
+ "id": task.get('id'),
805
+ "params": params_copy,
806
  }
807
+ manifest_entry = {k: v for k, v in manifest_entry.items() if v is not None}
808
  queue_manifest.append(manifest_entry)
809
+
810
  manifest_path = os.path.join(tmpdir, "queue.json")
811
  with open(manifest_path, 'w', encoding='utf-8') as f: json.dump(queue_manifest, f, indent=4)
812
  with zipfile.ZipFile(output_filename, 'w', zipfile.ZIP_DEFLATED) as zf:
813
  zf.write(manifest_path, arcname="queue.json")
814
+ for saved_file_rel_path in file_paths_in_zip.values():
815
+ saved_file_abs_path = os.path.join(tmpdir, saved_file_rel_path)
816
+ if os.path.exists(saved_file_abs_path):
817
+ zf.write(saved_file_abs_path, arcname=saved_file_rel_path)
818
+ else:
819
+ print(f"Warning (Autosave): File {saved_file_rel_path} not found during zipping.")
820
  return output_filename
821
  return None
822
 
 
1281
  server_config_filename = "wgp_config.json"
1282
 
1283
  if not os.path.isfile(server_config_filename) and os.path.isfile("gradio_config.json"):
 
1284
  shutil.move("gradio_config.json", server_config_filename)
1285
 
1286
  if not Path(server_config_filename).is_file():
 
3085
  lora_dir = get_lora_dir(get_model_filename("i2v"), quantizeTransformer)
3086
  log_path = os.path.join(lora_dir, "log.txt")
3087
  if not os.path.isfile(log_path):
 
3088
  tmp_path = os.path.join(lora_dir, "tmp_lora_dowload")
3089
  import glob
3090
  snapshot_download(repo_id="DeepBeepMeep/Wan2.1", allow_patterns="loras_i2v/*", local_dir= tmp_path)
 
3602
  save_queue_btn = gr.DownloadButton("Save Queue", size="sm")
3603
  load_queue_btn = gr.UploadButton("Load Queue", file_types=[".zip"], size="sm")
3604
  clear_queue_btn = gr.Button("Clear Queue", size="sm", variant="stop")
3605
+ quit_button = gr.Button("Save and Quit", size="sm", variant="secondary")
3606
  trigger_zip_download_js = """
3607
  (base64String) => {
3608
  if (!base64String) {
 
3687
  inputs=None,
3688
  outputs=[current_gen_column, queue_accordion]
3689
  )
3690
+ quit_button.click(
3691
+ fn=quit_application,
3692
+ inputs=[],
3693
+ outputs=[]
3694
+ )
3695
 
3696
  extra_inputs = prompt_vars + [wizard_prompt, wizard_variables_var, wizard_prompt_activated_var, video_prompt_column, image_prompt_column,
3697
  prompt_column_advanced, prompt_column_wizard_vars, prompt_column_wizard, lset_name, advanced_row] # show_advanced presets_column,