Deepro Bardhan commited on
Commit
2c0a9f6
·
1 Parent(s): 72e0b27

AddedSingleSrcMultiVideo

Browse files
Files changed (2) hide show
  1. .gitignore +1 -0
  2. app.py +127 -0
.gitignore CHANGED
@@ -8,6 +8,7 @@ MultiSrcMultiDst/
8
  SingleSrcMultiDst/
9
  CustomSwap/
10
  CustomVideoSwap/
 
11
  __pycache__/*
12
  .gradio/
13
 
 
8
  SingleSrcMultiDst/
9
  CustomSwap/
10
  CustomVideoSwap/
11
+ SingleSrcMultiVideo/
12
  __pycache__/*
13
  .gradio/
14
 
app.py CHANGED
@@ -693,6 +693,118 @@ def swap_video_custom_mapping(src_imgs, video, mapping_str, delete_frames_dir=Tr
693
  log += f"Elapsed time: {elapsed:.2f} seconds\n"
694
  return final_output_path, log
695
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
696
 
697
  # Gradio UI
698
  with gr.Blocks() as demo:
@@ -810,6 +922,21 @@ with gr.Blocks() as demo:
810
  gr.Textbox(label="Log Output", lines=8, interactive=False)
811
  ],
812
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
813
 
814
 
815
  if __name__ == "__main__":
 
693
  log += f"Elapsed time: {elapsed:.2f} seconds\n"
694
  return final_output_path, log
695
 
696
+ def swap_single_src_multi_video(src_img, dst_videos, dst_indices, delete_frames_dir=True, add_audio=True, progress=gr.Progress(track_tqdm=True)):
697
+ """
698
+ Swaps a single source image onto multiple videos, with a mapping for destination face indices.
699
+ Each video is processed one by one.
700
+ """
701
+ log = ""
702
+ results = []
703
+ start_time = time.time()
704
+ base_dir = "SingleSrcMultiVideo"
705
+ dst_dir = os.path.join(base_dir, "dst")
706
+ frames_dir = os.path.join(base_dir, "video_frames")
707
+ swapped_dir = os.path.join(base_dir, "swap_frames")
708
+ output_dir = os.path.join(base_dir, "output")
709
+ os.makedirs(dst_dir, exist_ok=True)
710
+ os.makedirs(frames_dir, exist_ok=True)
711
+ os.makedirs(swapped_dir, exist_ok=True)
712
+ os.makedirs(output_dir, exist_ok=True)
713
+
714
+ # Parse indices
715
+ if isinstance(dst_indices, str):
716
+ dst_indices_list = [int(idx.strip()) for idx in dst_indices.split(",") if idx.strip().isdigit()]
717
+ else:
718
+ dst_indices_list = [int(idx) for idx in dst_indices]
719
+
720
+ # Save source image
721
+ src_path = os.path.join(base_dir, "data_src.jpg")
722
+ src_img_bgr = cv2.cvtColor(src_img, cv2.COLOR_RGB2BGR)
723
+ cv2.imwrite(src_path, src_img_bgr)
724
+ log += f"Saved source image to {src_path}\n"
725
+
726
+ from VideoSwapping import extract_frames, frames_to_video
727
+
728
+ for i, video in enumerate(dst_videos):
729
+ dst_idx = dst_indices_list[i] if i < len(dst_indices_list) else 1
730
+ video_name = f"video_{i}.mp4"
731
+ dst_video_path = os.path.join(dst_dir, video_name)
732
+ output_video_path = os.path.join(output_dir, f"output_{i}.mp4")
733
+ output_video_with_audio = os.path.join(output_dir, f"output_with_audio_{i}.mp4")
734
+
735
+ # Copy video to dst_dir
736
+ if isinstance(video, str) and os.path.exists(video):
737
+ shutil.copy(video, dst_video_path)
738
+ log += f"Copied video {video} to {dst_video_path}\n"
739
+ else:
740
+ dst_video_path = video
741
+
742
+ # Extract frames
743
+ frame_paths = extract_frames(dst_video_path, frames_dir)
744
+ log += f"Extracted {len(frame_paths)} frames from {dst_video_path} to {frames_dir}\n"
745
+ progress(i / len(dst_videos), desc=f"Processing video {i+1}/{len(dst_videos)}")
746
+
747
+ swapped_files = set(os.listdir(swapped_dir))
748
+ total_frames = len(frame_paths)
749
+ temp_frame_path = os.path.join(swapped_dir, "temp.jpg")
750
+ start_loop_time = time.time()
751
+
752
+ for idx, frame_path in enumerate(frame_paths):
753
+ swapped_name = f"swapped_{idx:05d}.jpg"
754
+ out_path = os.path.join(swapped_dir, swapped_name)
755
+ if swapped_name in swapped_files and os.path.exists(out_path):
756
+ continue
757
+ try:
758
+ shutil.copy(frame_path, temp_frame_path)
759
+ try:
760
+ swapped_img = swapper.swap_faces(src_path, 1, temp_frame_path, int(dst_idx))
761
+ cv2.imwrite(temp_frame_path, swapped_img)
762
+ except Exception as e:
763
+ log += f"Failed to swap face in frame {idx} of video {i}: {e}\n"
764
+ shutil.copy(temp_frame_path, out_path)
765
+ if os.path.exists(temp_frame_path):
766
+ os.remove(temp_frame_path)
767
+ except Exception as e:
768
+ cv2.imwrite(out_path, cv2.imread(frame_path))
769
+ log += f"Failed to swap frame {idx} of video {i}: {e}\n"
770
+
771
+ # Combine frames to video
772
+ cap = cv2.VideoCapture(dst_video_path)
773
+ fps = cap.get(cv2.CAP_PROP_FPS)
774
+ cap.release()
775
+ frames_to_video(swapped_dir, output_video_path, fps)
776
+ log += f"Combined swapped frames into video {output_video_path}\n"
777
+
778
+ # Mux audio if requested
779
+ if add_audio:
780
+ ok, audio_log = add_audio_to_video(dst_video_path, output_video_path, output_video_with_audio)
781
+ if ok:
782
+ log += f"Added audio to {output_video_with_audio}\n"
783
+ results.append(output_video_with_audio)
784
+ else:
785
+ log += f"Audio muxing failed for video {i}: {audio_log}\n"
786
+ results.append(output_video_path)
787
+ else:
788
+ results.append(output_video_path)
789
+ log += f"Audio was not added for video {i} as per user request.\n"
790
+
791
+ # Cleanup frames for next video
792
+ if delete_frames_dir and os.path.exists(frames_dir):
793
+ shutil.rmtree(frames_dir)
794
+ os.makedirs(frames_dir, exist_ok=True)
795
+ log += f"Deleted video_frames directory after video {i}.\n"
796
+ elif not delete_frames_dir:
797
+ log += f"Kept video_frames directory after video {i} as requested.\n"
798
+ if os.path.exists(swapped_dir):
799
+ shutil.rmtree(swapped_dir)
800
+ os.makedirs(swapped_dir, exist_ok=True)
801
+ log += f"Cleared swap_frames directory after video {i}.\n"
802
+
803
+ elapsed = time.time() - start_time
804
+ log += f"Elapsed time: {elapsed:.2f} seconds\n"
805
+ return results, log
806
+
807
+
808
 
809
  # Gradio UI
810
  with gr.Blocks() as demo:
 
922
  gr.Textbox(label="Log Output", lines=8, interactive=False)
923
  ],
924
  )
925
+ with gr.Tab("SingleSrcMultiVideo"):
926
+ gr.Interface(
927
+ fn=swap_single_src_multi_video,
928
+ inputs=[
929
+ gr.Image(label="Source Image"),
930
+ gr.File(label="Target Videos (select multiple)", file_count="multiple", type="filepath"),
931
+ gr.Textbox(label="Destination Face Indices (comma-separated, e.g. 1,2,1)"),
932
+ gr.Checkbox(label="Delete video_frames directory after processing", value=True),
933
+ gr.Checkbox(label="Add audio from original video", value=True)
934
+ ],
935
+ outputs=[
936
+ gr.Gallery(label="Swapped Videos", type="filepath"),
937
+ gr.Textbox(label="Log Output", lines=8, interactive=False)
938
+ ],
939
+ )
940
 
941
 
942
  if __name__ == "__main__":