shaheerawan3 commited on
Commit
cd00544
·
verified ·
1 Parent(s): 9854831

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +162 -126
app.py CHANGED
@@ -25,6 +25,7 @@ import docx
25
  import PyPDF2
26
  import pptx
27
  import cv2
 
28
 
29
  class FileProcessor:
30
  @staticmethod
@@ -831,143 +832,178 @@ class EnhancedVideoGenerator:
831
  msecs = int((seconds - int(seconds)) * 1000)
832
  return f"{hours:02d}:{minutes:02d}:{secs:02d},{msecs:03d}"
833
 
834
- def create_video(self, script: str, style: str, duration: int, output_path: str, selected_images: List[str]) -> str:
835
- """Create video with selected images and improved error handling"""
836
- try:
837
- # Initialize progress tracking
838
- progress_bar = st.progress(0)
839
- status_text = st.empty()
840
-
841
- # Validate inputs
842
- if not selected_images:
843
- raise ValueError("No images selected. Please select at least one image.")
844
-
845
- if not script.strip():
846
- raise ValueError("Script cannot be empty.")
847
-
848
- # Generate voice-over
849
- status_text.text("Creating voice-over...")
850
- audio = self.generate_fallback_audio(script) # Using fallback audio for reliability
851
- progress_bar.progress(20)
852
-
853
- # Process images
854
- status_text.text("Processing images...")
855
- processed_images = []
856
-
857
- for img_url in selected_images:
858
- try:
859
- response = requests.get(img_url, timeout=10)
860
- response.raise_for_status()
861
- img = Image.open(BytesIO(response.content))
862
- img = img.convert('RGB')
863
- img = img.resize((1920, 1080), Image.Resampling.LANCZOS)
864
- processed_images.append(img)
865
- except Exception as e:
866
- print(f"Error processing image {img_url}: {e}")
867
- continue
868
-
869
- if not processed_images:
870
- raise ValueError("Failed to process any of the selected images.")
871
-
872
- progress_bar.progress(40)
873
-
874
- # Create frames
875
- status_text.text("Generating frames...")
876
- frames = []
877
- fps = 30
878
- total_frames = int(duration * fps)
879
- frames_per_image = total_frames // len(processed_images)
880
-
881
- # Convert images to numpy arrays
882
- image_arrays = [np.array(img) for img in processed_images]
883
-
884
- # Generate frames with transitions
885
- frame_count = 0
886
- for idx, img_array in enumerate(image_arrays):
887
- # Calculate how many frames this image should appear
888
- if idx == len(image_arrays) - 1:
889
- n_frames = total_frames - frame_count
890
- else:
891
- n_frames = min(frames_per_image, total_frames - frame_count)
892
 
893
- # Add main frames
894
- for _ in range(n_frames):
895
- frames.append(img_array)
896
- frame_count += 1
 
 
 
 
 
 
 
897
 
898
- # Add transition frames to next image
899
- if idx < len(image_arrays) - 1:
900
- next_img_array = image_arrays[idx + 1]
901
- transition_frames = 15 # Number of transition frames
902
- for t in range(transition_frames):
903
- if frame_count < total_frames:
904
- alpha = t / transition_frames
905
- transition_frame = cv2.addWeighted(
906
- img_array, 1 - alpha,
907
- next_img_array, alpha, 0
908
- )
909
- frames.append(transition_frame)
910
- frame_count += 1
911
-
912
- progress_bar.progress(70)
913
-
914
- # Create video with frames
915
- status_text.text("Compiling video...")
916
- clip = ImageSequenceClip(frames, fps=fps)
917
-
918
- # Add audio
919
- audio_duration = audio.duration
920
- video_duration = len(frames) / fps
921
-
922
- if audio_duration > video_duration:
923
- audio = audio.subclip(0, video_duration)
924
- elif audio_duration < video_duration:
925
- clip = clip.subclip(0, audio_duration)
926
-
927
- final_clip = clip.set_audio(audio)
928
-
929
- # Ensure output directory exists
930
- output_dir = os.path.dirname(output_path)
931
- if output_dir and not os.path.exists(output_dir):
932
- os.makedirs(output_dir)
933
-
934
- progress_bar.progress(90)
935
-
936
- # Write video file
937
- status_text.text("Saving video...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
938
  try:
 
939
  final_clip.write_videofile(
940
  output_path,
941
  fps=fps,
942
  codec='libx264',
943
- audio_codec='aac',
944
- ffmpeg_params=['-pix_fmt', 'yuv420p'], # Ensure compatibility
945
  verbose=False,
946
  logger=None
947
  )
948
- except Exception as e:
949
- raise RuntimeError(f"Failed to write video file: {str(e)}")
950
-
951
- progress_bar.progress(100)
952
- status_text.text("Video generation complete!")
953
-
954
- return output_path
955
-
 
 
 
 
 
 
 
 
 
 
 
 
 
956
  except Exception as e:
957
- error_msg = f"Video creation failed: {str(e)}"
958
- print(error_msg) # For debugging
959
- raise RuntimeError(error_msg)
960
- finally:
961
- # Cleanup
962
- try:
963
- if 'clip' in locals():
964
- clip.close()
965
- if 'final_clip' in locals():
966
- final_clip.close()
967
- if 'audio' in locals():
968
- audio.close()
969
- except Exception as e:
970
- print(f"Cleanup error: {e}")
971
 
972
 
973
 
 
25
  import PyPDF2
26
  import pptx
27
  import cv2
28
+ from PIL import ImageEnhance
29
 
30
  class FileProcessor:
31
  @staticmethod
 
832
  msecs = int((seconds - int(seconds)) * 1000)
833
  return f"{hours:02d}:{minutes:02d}:{secs:02d},{msecs:03d}"
834
 
835
+ def create_video(self, script: str, style: str, duration: int, output_path: str, selected_images: List[str]) -> str:
836
+ """Create video with enhanced features and proper error handling"""
837
+ try:
838
+ # Initialize progress tracking
839
+ progress_bar = st.progress(0)
840
+ status_text = st.empty()
841
+
842
+ # Create output directory if it doesn't exist
843
+ os.makedirs(os.path.dirname(output_path), exist_ok=True)
844
+
845
+ # Validate inputs and paths
846
+ if not output_path:
847
+ raise ValueError("Output path cannot be empty")
848
+ if not selected_images:
849
+ raise ValueError("No images selected")
850
+
851
+ # Generate voice-over with progress tracking
852
+ status_text.text("Creating voice-over...")
853
+ audio = self.generate_voice_over(script)
854
+ progress_bar.progress(20)
855
+
856
+ # Process images with effects
857
+ status_text.text("Processing images with effects...")
858
+ processed_images = []
859
+
860
+ for img_url in selected_images:
861
+ try:
862
+ response = requests.get(img_url, timeout=10)
863
+ response.raise_for_status()
864
+ img = Image.open(BytesIO(response.content))
865
+ img = img.convert('RGB')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
866
 
867
+ # Apply image effects based on style
868
+ if style == "Creative":
869
+ # Add creative effects
870
+ enhancer = ImageEnhance.Contrast(img)
871
+ img = enhancer.enhance(1.2)
872
+ enhancer = ImageEnhance.Brightness(img)
873
+ img = enhancer.enhance(1.1)
874
+ elif style == "Professional":
875
+ # Add professional effects
876
+ enhancer = ImageEnhance.Sharpness(img)
877
+ img = enhancer.enhance(1.3)
878
 
879
+ img = img.resize((1920, 1080), Image.Resampling.LANCZOS)
880
+ processed_images.append(img)
881
+
882
+ except Exception as e:
883
+ print(f"Error processing image {img_url}: {e}")
884
+ continue
885
+
886
+ progress_bar.progress(40)
887
+
888
+ # Generate frames with transitions
889
+ status_text.text("Creating frames with transitions...")
890
+ frames = []
891
+ fps = 30
892
+ total_frames = int(duration * fps)
893
+ frames_per_image = total_frames // len(processed_images)
894
+
895
+ # Convert images to numpy arrays
896
+ image_arrays = [np.array(img) for img in processed_images]
897
+
898
+ # Add transition effects
899
+ frame_count = 0
900
+ for idx, img_array in enumerate(image_arrays):
901
+ # Calculate frames for this image
902
+ if idx == len(image_arrays) - 1:
903
+ n_frames = total_frames - frame_count
904
+ else:
905
+ n_frames = min(frames_per_image, total_frames - frame_count)
906
+
907
+ # Add effects and transitions
908
+ for frame_idx in range(n_frames):
909
+ # Apply fade in/out effect
910
+ alpha = 1.0
911
+ if frame_idx < 15: # Fade in
912
+ alpha = frame_idx / 15
913
+ elif frame_idx > n_frames - 15: # Fade out
914
+ alpha = (n_frames - frame_idx) / 15
915
+
916
+ frame = img_array * alpha
917
+ frames.append(frame.astype(np.uint8))
918
+ frame_count += 1
919
+
920
+ # Update progress
921
+ progress = int(40 + (frame_count / total_frames * 30))
922
+ progress_bar.progress(progress)
923
+
924
+ # Add transition to next image
925
+ if idx < len(image_arrays) - 1:
926
+ next_img_array = image_arrays[idx + 1]
927
+ transition_frames = 15
928
+ for t in range(transition_frames):
929
+ if frame_count < total_frames:
930
+ alpha = t / transition_frames
931
+ transition_frame = cv2.addWeighted(
932
+ img_array, 1 - alpha,
933
+ next_img_array, alpha, 0
934
+ )
935
+ frames.append(transition_frame)
936
+ frame_count += 1
937
+
938
+ progress_bar.progress(70)
939
+
940
+ # Create video with frames
941
+ status_text.text("Compiling video...")
942
+ clip = ImageSequenceClip(frames, fps=fps)
943
+
944
+ # Add audio with proper synchronization
945
+ audio_duration = audio.duration
946
+ video_duration = len(frames) / fps
947
+
948
+ if audio_duration > video_duration:
949
+ audio = audio.subclip(0, video_duration)
950
+ elif audio_duration < video_duration:
951
+ clip = clip.subclip(0, audio_duration)
952
+
953
+ final_clip = clip.set_audio(audio)
954
+
955
+ # Write video with progress caching
956
+ status_text.text("Saving video...")
957
+ cache_dir = os.path.join(os.path.dirname(output_path), ".cache")
958
+ os.makedirs(cache_dir, exist_ok=True)
959
+
960
+ try:
961
+ final_clip.write_videofile(
962
+ output_path,
963
+ fps=fps,
964
+ codec='libx264',
965
+ audio_codec='aac',
966
+ ffmpeg_params=['-pix_fmt', 'yuv420p'],
967
+ temp_audiofile=os.path.join(cache_dir, "temp-audio.m4a"),
968
+ verbose=False,
969
+ logger=None
970
+ )
971
+ except Exception as e:
972
+ # Attempt error recovery
973
+ status_text.text("Attempting error recovery...")
974
  try:
975
+ # Try alternative codec settings
976
  final_clip.write_videofile(
977
  output_path,
978
  fps=fps,
979
  codec='libx264',
980
+ audio_codec='mp3',
 
981
  verbose=False,
982
  logger=None
983
  )
984
+ except Exception as recovery_e:
985
+ raise RuntimeError(f"Video creation failed even with recovery attempt: {str(recovery_e)}")
986
+
987
+ progress_bar.progress(100)
988
+ status_text.text("Video generation complete!")
989
+
990
+ return output_path
991
+
992
+ except Exception as e:
993
+ error_msg = f"Video creation failed: {str(e)}"
994
+ print(error_msg)
995
+ raise RuntimeError(error_msg)
996
+ finally:
997
+ # Cleanup
998
+ try:
999
+ if 'clip' in locals():
1000
+ clip.close()
1001
+ if 'final_clip' in locals():
1002
+ final_clip.close()
1003
+ if 'audio' in locals():
1004
+ audio.close()
1005
  except Exception as e:
1006
+ print(f"Cleanup error: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
1007
 
1008
 
1009