shaheerawan3 commited on
Commit
643827c
·
verified ·
1 Parent(s): fbd09df

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -98
app.py CHANGED
@@ -796,107 +796,142 @@ class EnhancedVideoGenerator:
796
  return f"{hours:02d}:{minutes:02d}:{secs:02d},{msecs:03d}"
797
 
798
  def create_video(self, script: str, style: str, duration: int, output_path: str, selected_images: List[str]) -> str:
799
- """Create video with selected images and improved error handling"""
800
- try:
801
- # Progress bar
802
- progress_bar = st.progress(0)
803
- status_text = st.empty()
804
-
805
- # Validate inputs
806
- if not selected_images:
807
- raise ValueError("No images selected. Please select at least one image.")
808
-
809
- if not script.strip():
810
- raise ValueError("Script cannot be empty.")
811
-
812
- # Generate voice-over (20%)
813
- status_text.text("Creating voice-over...")
814
- audio = self.generate_voice_over(script)
815
- progress_bar.progress(20)
816
-
817
- # Process selected images (40%)
818
- status_text.text("Processing images...")
819
- processed_images = []
820
-
821
- for img_url in selected_images:
822
- try:
823
- response = requests.get(img_url, timeout=10)
824
- response.raise_for_status() # Raise exception for bad status codes
825
- img = Image.open(BytesIO(response.content))
826
- img = img.convert('RGB') # Ensure RGB format
827
- img = img.resize((1920, 1080), Image.Resampling.LANCZOS)
828
- processed_images.append(np.array(img))
829
- except Exception as e:
830
- print(f"Error processing image {img_url}: {e}")
831
- continue
832
-
833
- if not processed_images:
834
- raise ValueError("Failed to process any of the selected images.")
835
-
836
- progress_bar.progress(40)
837
-
838
- # Create frames with transitions
839
- fps = 30
840
- total_frames = int(duration * fps)
841
- frames = []
842
-
843
- status_text.text("Generating frames...")
844
- frames_per_image = total_frames // len(processed_images)
845
-
846
- for idx, img in enumerate(processed_images):
847
- # Add main frames
848
- for _ in range(frames_per_image):
849
- frames.append(img)
850
-
851
- # Add transition frames to next image
852
- if idx < len(processed_images) - 1:
853
- next_img = processed_images[idx + 1]
854
- for alpha in np.linspace(0, 1, 15):
855
- transition_frame = (1 - alpha) * img + alpha * next_img
856
- frames.append(transition_frame.astype(np.uint8))
857
-
858
- progress_bar.progress(70)
859
-
860
- # Create video clip
861
- status_text.text("Compiling video...")
862
- video = ImageSequenceClip(frames, fps=fps)
863
-
864
- # Ensure audio duration matches video duration
865
- audio_duration = audio.duration
866
- video_duration = len(frames) / fps
867
-
868
- if audio_duration > video_duration:
869
- audio = audio.subclip(0, video_duration)
870
- elif audio_duration < video_duration:
871
- video = video.subclip(0, audio_duration)
872
-
873
- video = video.set_audio(audio)
874
-
875
- progress_bar.progress(90)
876
-
877
- # Write final video with error handling
878
  try:
879
- video.write_videofile(
880
- output_path,
881
- fps=fps,
882
- codec='libx264',
883
- audio_codec='aac',
884
- threads=4,
885
- preset='ultrafast'
886
- )
887
  except Exception as e:
888
- raise RuntimeError(f"Failed to write video file: {str(e)}")
889
-
890
- progress_bar.progress(100)
891
- status_text.text("Video generation complete!")
892
-
893
- return output_path
894
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
895
  except Exception as e:
896
- error_msg = f"Video creation failed: {str(e)}"
897
- self.logger.error(error_msg)
898
- st.error(error_msg)
899
- raise
900
 
901
 
902
 
 
796
  return f"{hours:02d}:{minutes:02d}:{secs:02d},{msecs:03d}"
797
 
798
  def create_video(self, script: str, style: str, duration: int, output_path: str, selected_images: List[str]) -> str:
799
+ """Create video with selected images and improved error handling"""
800
+ try:
801
+ # Initialize progress tracking
802
+ progress_bar = st.progress(0)
803
+ status_text = st.empty()
804
+
805
+ # Validate inputs
806
+ if not selected_images:
807
+ raise ValueError("No images selected. Please select at least one image.")
808
+
809
+ if not script.strip():
810
+ raise ValueError("Script cannot be empty.")
811
+
812
+ # Generate voice-over
813
+ status_text.text("Creating voice-over...")
814
+ audio = self.generate_fallback_audio(script) # Using fallback audio for reliability
815
+ progress_bar.progress(20)
816
+
817
+ # Process images
818
+ status_text.text("Processing images...")
819
+ processed_images = []
820
+
821
+ for img_url in selected_images:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
822
  try:
823
+ response = requests.get(img_url, timeout=10)
824
+ response.raise_for_status()
825
+ img = Image.open(BytesIO(response.content))
826
+ img = img.convert('RGB')
827
+ img = img.resize((1920, 1080), Image.Resampling.LANCZOS)
828
+ processed_images.append(img)
 
 
829
  except Exception as e:
830
+ print(f"Error processing image {img_url}: {e}")
831
+ continue
832
+
833
+ if not processed_images:
834
+ raise ValueError("Failed to process any of the selected images.")
835
+
836
+ progress_bar.progress(40)
837
+
838
+ # Create frames
839
+ status_text.text("Generating frames...")
840
+ frames = []
841
+ fps = 30
842
+ total_frames = int(duration * fps)
843
+ frames_per_image = total_frames // len(processed_images)
844
+
845
+ # Convert images to numpy arrays
846
+ image_arrays = [np.array(img) for img in processed_images]
847
+
848
+ # Generate frames with transitions
849
+ frame_count = 0
850
+ for idx, img_array in enumerate(image_arrays):
851
+ # Calculate how many frames this image should appear
852
+ if idx == len(image_arrays) - 1:
853
+ n_frames = total_frames - frame_count
854
+ else:
855
+ n_frames = min(frames_per_image, total_frames - frame_count)
856
+
857
+ # Add main frames
858
+ for _ in range(n_frames):
859
+ frames.append(img_array)
860
+ frame_count += 1
861
+
862
+ # Add transition frames to next image
863
+ if idx < len(image_arrays) - 1:
864
+ next_img_array = image_arrays[idx + 1]
865
+ transition_frames = 15 # Number of transition frames
866
+ for t in range(transition_frames):
867
+ if frame_count < total_frames:
868
+ alpha = t / transition_frames
869
+ transition_frame = cv2.addWeighted(
870
+ img_array, 1 - alpha,
871
+ next_img_array, alpha, 0
872
+ )
873
+ frames.append(transition_frame)
874
+ frame_count += 1
875
+
876
+ progress_bar.progress(70)
877
+
878
+ # Create video with frames
879
+ status_text.text("Compiling video...")
880
+ clip = ImageSequenceClip(frames, fps=fps)
881
+
882
+ # Add audio
883
+ audio_duration = audio.duration
884
+ video_duration = len(frames) / fps
885
+
886
+ if audio_duration > video_duration:
887
+ audio = audio.subclip(0, video_duration)
888
+ elif audio_duration < video_duration:
889
+ clip = clip.subclip(0, audio_duration)
890
+
891
+ final_clip = clip.set_audio(audio)
892
+
893
+ # Ensure output directory exists
894
+ output_dir = os.path.dirname(output_path)
895
+ if output_dir and not os.path.exists(output_dir):
896
+ os.makedirs(output_dir)
897
+
898
+ progress_bar.progress(90)
899
+
900
+ # Write video file
901
+ status_text.text("Saving video...")
902
+ try:
903
+ final_clip.write_videofile(
904
+ output_path,
905
+ fps=fps,
906
+ codec='libx264',
907
+ audio_codec='aac',
908
+ ffmpeg_params=['-pix_fmt', 'yuv420p'], # Ensure compatibility
909
+ verbose=False,
910
+ logger=None
911
+ )
912
+ except Exception as e:
913
+ raise RuntimeError(f"Failed to write video file: {str(e)}")
914
+
915
+ progress_bar.progress(100)
916
+ status_text.text("Video generation complete!")
917
+
918
+ return output_path
919
+
920
+ except Exception as e:
921
+ error_msg = f"Video creation failed: {str(e)}"
922
+ print(error_msg) # For debugging
923
+ raise RuntimeError(error_msg)
924
+ finally:
925
+ # Cleanup
926
+ try:
927
+ if 'clip' in locals():
928
+ clip.close()
929
+ if 'final_clip' in locals():
930
+ final_clip.close()
931
+ if 'audio' in locals():
932
+ audio.close()
933
  except Exception as e:
934
+ print(f"Cleanup error: {e}")
 
 
 
935
 
936
 
937