shaheerawan3 commited on
Commit
8817c98
·
verified ·
1 Parent(s): 79fef09

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -105
app.py CHANGED
@@ -889,123 +889,86 @@ class EnhancedVideoGenerator:
889
  msecs = int((seconds - int(seconds)) * 1000)
890
  return f"{hours:02d}:{minutes:02d}:{secs:02d},{msecs:03d}"
891
 
892
- def create_video(self, script: str, style: str, duration: int, output_path: str, selected_images: List[str],
893
- video_effects: dict = None, progress_callback: Callable[[float], None] = None) -> str:
894
- """Create video with selected images and effects"""
 
895
  try:
896
- # Initialize default effects if none provided
897
- if video_effects is None:
898
- video_effects = {
899
- 'zoom': 1.0,
900
- 'brightness': 1.0,
901
- 'contrast': 1.0,
902
- 'blur': False
903
- }
904
 
905
- # Process images with error handling
906
  processed_images = []
907
- total_images = len(selected_images)
908
-
909
  for idx, img_url in enumerate(selected_images):
910
  try:
911
  response = requests.get(img_url, timeout=10)
912
- response.raise_for_status()
913
  img = Image.open(BytesIO(response.content))
914
- img = img.convert('RGB')
915
- img = img.resize((1920, 1080), Image.LANCZOS)
916
- processed_images.append(img)
917
 
918
- # Update progress (20% of total progress is for image processing)
919
  if progress_callback:
920
- progress = (idx + 1) / total_images * 20
921
- progress_callback(progress)
922
-
923
  except Exception as e:
924
- self.logger.error(f"Error processing image {img_url}: {e}")
925
  continue
926
-
927
  if not processed_images:
928
- raise ValueError("No valid images to process")
929
-
930
- # Generate voice-over
931
- audio = self.generate_fallback_audio(script)
932
  if progress_callback:
933
- progress_callback(30) # 30% progress after audio generation
934
-
935
- # Calculate frames
 
936
  fps = 30
937
- total_frames = int(duration * fps)
938
- frames_per_image = total_frames // len(processed_images)
939
-
940
- # Create frames with effects
941
- frames = []
942
- frame_count = 0
943
 
944
- # Apply zoom effect over time
945
- zoom_range = np.linspace(1.0, video_effects['zoom'], frames_per_image)
946
-
947
- for idx, img in enumerate(processed_images):
948
- img_array = np.array(img)
949
-
950
- # Calculate frames for this image
951
- if idx == len(processed_images) - 1:
952
- n_frames = total_frames - frame_count
953
- else:
954
- n_frames = min(frames_per_image, total_frames - frame_count)
955
-
956
- # Generate frames with effects
957
- for frame_idx in range(n_frames):
958
- current_effects = video_effects.copy()
959
-
960
- # Update zoom factor
961
- if video_effects['zoom'] != 1.0:
962
- current_effects['zoom'] = zoom_range[min(frame_idx, len(zoom_range)-1)]
963
-
964
- # Apply effects to frame
965
- frame = self.apply_video_effects(img_array.copy(), current_effects)
966
- frames.append(frame)
967
- frame_count += 1
968
-
969
- # Update progress (30% to 70% is for frame generation)
970
- if progress_callback and frame_count % 30 == 0:
971
- progress = 30 + (frame_count / total_frames * 40)
972
- progress_callback(progress)
973
-
974
- # Add transition to next image if enabled
975
- if idx < len(processed_images) - 1 and video_effects.get('transition_style') != 'None':
976
- next_img_array = np.array(processed_images[idx + 1])
977
- transition_frames = 15
978
-
979
- for t in range(transition_frames):
980
- if frame_count < total_frames:
981
- alpha = t / transition_frames
982
- transition_frame = cv2.addWeighted(
983
- img_array, 1 - alpha,
984
- next_img_array, alpha, 0
985
- )
986
- frames.append(transition_frame)
987
- frame_count += 1
988
-
989
- # Create video clip
990
- clip = ImageSequenceClip(frames, fps=fps)
991
  if progress_callback:
992
- progress_callback(80) # 80% progress after creating clip
993
-
994
- # Adjust audio duration
995
- if audio.duration > clip.duration:
996
- audio = audio.subclip(0, clip.duration)
997
- elif audio.duration < clip.duration:
998
- clip = clip.subclip(0, audio.duration)
999
-
 
 
 
1000
  # Combine video and audio
1001
- final_clip = clip.set_audio(audio)
 
1002
  if progress_callback:
1003
- progress_callback(90) # 90% progress after combining audio
1004
-
1005
  # Ensure output directory exists
1006
  os.makedirs(os.path.dirname(output_path), exist_ok=True)
1007
-
1008
- # Write video file
1009
  final_clip.write_videofile(
1010
  output_path,
1011
  fps=fps,
@@ -1015,26 +978,26 @@ class EnhancedVideoGenerator:
1015
  verbose=False,
1016
  logger=None
1017
  )
1018
-
1019
  if progress_callback:
1020
- progress_callback(100) # 100% progress after writing file
1021
-
1022
  return output_path
1023
-
1024
  except Exception as e:
1025
- self.logger.error(f"Video creation failed: {str(e)}")
1026
  raise
1027
  finally:
1028
  # Cleanup
1029
  try:
1030
- if 'clip' in locals():
1031
- clip.close()
1032
  if 'final_clip' in locals():
1033
  final_clip.close()
1034
  if 'audio' in locals():
1035
  audio.close()
1036
  except Exception as e:
1037
- self.logger.error(f"Cleanup error: {e}")
1038
 
1039
 
1040
 
 
889
  msecs = int((seconds - int(seconds)) * 1000)
890
  return f"{hours:02d}:{minutes:02d}:{secs:02d},{msecs:03d}"
891
 
892
+ def create_video(self, script: str, style: str, duration: int, output_path: str,
893
+ selected_images: List[str], video_effects: dict = None,
894
+ progress_callback: Callable[[float], None] = None) -> str:
895
+ """Create video with enhanced error handling and progress tracking"""
896
  try:
897
+ if not selected_images:
898
+ raise ValueError("No images provided for video generation")
899
+
900
+ # Initialize moviepy
901
+ import moviepy.editor as mpy
902
+ from moviepy.editor import ImageSequenceClip, AudioFileClip
 
 
903
 
904
+ # Process images
905
  processed_images = []
 
 
906
  for idx, img_url in enumerate(selected_images):
907
  try:
908
  response = requests.get(img_url, timeout=10)
 
909
  img = Image.open(BytesIO(response.content))
910
+ img = img.convert('RGB').resize((1920, 1080), Image.LANCZOS)
911
+ processed_images.append(np.array(img))
 
912
 
 
913
  if progress_callback:
914
+ progress_callback((idx + 1) / len(selected_images) * 20)
 
 
915
  except Exception as e:
916
+ logging.error(f"Error processing image {img_url}: {e}")
917
  continue
918
+
919
  if not processed_images:
920
+ raise ValueError("Failed to process any images")
921
+
922
+ # Generate audio
 
923
  if progress_callback:
924
+ progress_callback(25)
925
+ audio = self.generate_voice_over(script)
926
+
927
+ # Calculate video parameters
928
  fps = 30
929
+ total_duration = duration
930
+ frames_per_image = int(fps * total_duration / len(processed_images))
 
 
 
 
931
 
932
+ # Generate frames with effects
933
+ frames = []
934
+ for img_array in processed_images:
935
+ for _ in range(frames_per_image):
936
+ if video_effects and video_effects.get('zoom'):
937
+ # Apply zoom effect
938
+ zoom = video_effects['zoom']
939
+ h, w = img_array.shape[:2]
940
+ scaled_h, scaled_w = int(h * zoom), int(w * zoom)
941
+ img = Image.fromarray(img_array).resize((scaled_w, scaled_h), Image.LANCZOS)
942
+ # Crop to original size from center
943
+ left = (scaled_w - w) // 2
944
+ top = (scaled_h - h) // 2
945
+ img = img.crop((left, top, left + w, top + h))
946
+ frames.append(np.array(img))
947
+ else:
948
+ frames.append(img_array)
949
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
950
  if progress_callback:
951
+ progress_callback(60)
952
+
953
+ # Create video clip
954
+ video_clip = ImageSequenceClip(frames, fps=fps)
955
+
956
+ # Adjust audio duration if needed
957
+ if audio.duration > video_clip.duration:
958
+ audio = audio.subclip(0, video_clip.duration)
959
+ elif audio.duration < video_clip.duration:
960
+ video_clip = video_clip.subclip(0, audio.duration)
961
+
962
  # Combine video and audio
963
+ final_clip = video_clip.set_audio(audio)
964
+
965
  if progress_callback:
966
+ progress_callback(80)
967
+
968
  # Ensure output directory exists
969
  os.makedirs(os.path.dirname(output_path), exist_ok=True)
970
+
971
+ # Write final video
972
  final_clip.write_videofile(
973
  output_path,
974
  fps=fps,
 
978
  verbose=False,
979
  logger=None
980
  )
981
+
982
  if progress_callback:
983
+ progress_callback(100)
984
+
985
  return output_path
986
+
987
  except Exception as e:
988
+ logging.error(f"Video creation failed: {str(e)}")
989
  raise
990
  finally:
991
  # Cleanup
992
  try:
993
+ if 'video_clip' in locals():
994
+ video_clip.close()
995
  if 'final_clip' in locals():
996
  final_clip.close()
997
  if 'audio' in locals():
998
  audio.close()
999
  except Exception as e:
1000
+ logging.error(f"Cleanup error: {e}")
1001
 
1002
 
1003