awacke1 commited on
Commit
06a02a3
1 Parent(s): b0d4a94

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +100 -160
app.py CHANGED
@@ -811,21 +811,28 @@ def get_video_html(video_path, width="100%"):
811
 
812
 
813
  # *********
814
-
815
- def validate_and_preprocess_image(image_data, target_size=(576, 1024)):
816
- """Validate and preprocess image for video generation with detailed logging"""
817
  try:
818
  st.write("Starting image preprocessing...")
819
 
820
- # Convert bytes to PIL Image if needed
821
- if isinstance(image_data, bytes):
822
- img = Image.open(io.BytesIO(image_data))
823
- elif isinstance(image_data, Image.Image):
824
- img = image_data
 
 
 
 
 
 
 
 
825
  else:
826
- raise ValueError(f"Unsupported image data type: {type(image_data)}")
827
 
828
- st.write(f"Original image size: {img.size}, mode: {img.mode}")
829
 
830
  # Convert to RGB if necessary
831
  if img.mode != 'RGB':
@@ -864,118 +871,20 @@ def validate_and_preprocess_image(image_data, target_size=(576, 1024)):
864
  final_img.paste(resized_img, (paste_x, paste_y))
865
 
866
  st.write(f"Final image size: {final_img.size}")
867
-
868
- # Validate final image
869
- if final_img.size != target_size:
870
- raise ValueError(f"Final image size {final_img.size} doesn't match target size {target_size}")
871
-
872
  return final_img
873
 
874
  except Exception as e:
875
- st.error(f"Error in image preprocessing: {str(e)}")
876
  return None
877
 
878
- def generate_video_from_image(image_data, seed=None, motion_bucket_id=127, fps_id=6, max_retries=3):
879
- """Generate video from image with improved preprocessing and error handling"""
880
- temp_files = []
881
- try:
882
- # Set up progress tracking
883
- progress_bar = st.progress(0)
884
- status_text = st.empty()
885
-
886
- # Preprocess image
887
- status_text.text("Preprocessing image...")
888
- progress_bar.progress(10)
889
-
890
- processed_img = validate_and_preprocess_image(image_data)
891
- if processed_img is None:
892
- st.error("Image preprocessing failed")
893
- return None, None
894
-
895
- # Show preprocessed image
896
- st.write("Preprocessed image preview:")
897
- st.image(processed_img, caption="Preprocessed image", use_column_width=True)
898
-
899
- # Save processed image
900
- with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as temp_img:
901
- temp_files.append(temp_img.name)
902
- processed_img.save(temp_img.name, format='PNG', optimize=True)
903
- st.write(f"Saved preprocessed image to: {temp_img.name}")
904
-
905
- # Verify file size
906
- file_size = os.path.getsize(temp_img.name)
907
- st.write(f"Preprocessed image file size: {file_size/1024:.2f}KB")
908
-
909
- status_text.text("Connecting to video generation service...")
910
- progress_bar.progress(30)
911
-
912
- # Initialize client with debug flags
913
- client = Client(
914
- "awacke1/stable-video-diffusion",
915
- hf_token=os.environ.get("HUGGINGFACE_TOKEN"),
916
- )
917
-
918
- if seed is None:
919
- seed = int(time.time() * 1000) # Use millisecond timestamp as seed
920
-
921
- status_text.text("Starting video generation...")
922
- progress_bar.progress(40)
923
-
924
- for attempt in range(max_retries):
925
- try:
926
- status_text.text(f"Generating video (attempt {attempt + 1}/{max_retries})...")
927
- progress_bar.progress(40 + (attempt * 20))
928
-
929
- # Call video generation API
930
- result = client.predict(
931
- image=temp_img.name,
932
- seed=seed,
933
- randomize_seed=False, # Set to False for reproducibility
934
- motion_bucket_id=motion_bucket_id,
935
- fps_id=fps_id,
936
- api_name="/video"
937
- )
938
-
939
- # Validate result
940
- if result and isinstance(result, tuple) and len(result) >= 1:
941
- if isinstance(result[0], dict) and 'video' in result[0]:
942
- video_path = result[0]['video']
943
- if os.path.exists(video_path):
944
- status_text.text("Video generated successfully!")
945
- progress_bar.progress(100)
946
- return video_path, seed
947
-
948
- st.warning(f"Invalid result format on attempt {attempt + 1}: {result}")
949
- time.sleep(2 ** attempt) # Exponential backoff
950
-
951
- except Exception as e:
952
- st.warning(f"Attempt {attempt + 1} failed: {str(e)}")
953
- time.sleep(2 ** attempt)
954
-
955
- raise Exception(f"Failed to generate video after {max_retries} attempts")
956
-
957
- except Exception as e:
958
- st.error(f"Error in video generation: {str(e)}")
959
- return None, None
960
-
961
- finally:
962
- # Cleanup
963
- for temp_file in temp_files:
964
- try:
965
- if os.path.exists(temp_file):
966
- os.unlink(temp_file)
967
- st.write(f"Cleaned up temporary file: {temp_file}")
968
- except Exception as e:
969
- st.warning(f"Error cleaning up {temp_file}: {str(e)}")
970
-
971
  def add_video_generation_ui(container):
972
- """Enhanced video generation UI with better error handling and feedback"""
973
  st.markdown("### 🎥 Video Generation")
974
 
975
  col1, col2 = st.columns([2, 1])
976
 
977
  with col1:
978
- uploaded_image = st.file_uploader(
979
  "Upload Image for Video Generation 🖼️",
980
  type=['png', 'jpg', 'jpeg'],
981
  help="Upload a clear, well-lit image. Recommended size: 576x1024 pixels."
@@ -998,7 +907,6 @@ def add_video_generation_ui(container):
998
  help="Higher values create smoother but potentially less stable videos"
999
  )
1000
 
1001
- # Add advanced options in an expander
1002
  with st.expander("Advanced Options"):
1003
  use_custom_seed = st.checkbox("Use Custom Seed")
1004
  if use_custom_seed:
@@ -1006,71 +914,103 @@ def add_video_generation_ui(container):
1006
  else:
1007
  seed = None
1008
 
1009
- if uploaded_image:
1010
  try:
 
 
 
1011
  # Preview original image
1012
  preview_col1, preview_col2 = st.columns(2)
1013
  with preview_col1:
1014
  st.write("Original Image:")
1015
- st.image(uploaded_image, caption="Original", use_column_width=True)
 
1016
 
1017
  # Preview preprocessed image
1018
  with preview_col2:
1019
- preprocessed = validate_and_preprocess_image(uploaded_image.read())
 
1020
  if preprocessed:
1021
  st.write("Preprocessed Image:")
1022
  st.image(preprocessed, caption="Preprocessed", use_column_width=True)
1023
- except Exception as e:
1024
- st.error(f"Error previewing image: {str(e)}")
1025
-
1026
- if st.button("🎥 Generate Video", help="Start video generation process"):
1027
- try:
1028
  with st.spinner("Processing your video... This may take a few minutes 🎬"):
1029
- video_path, used_seed = generate_video_from_image(
1030
- uploaded_image.read(),
1031
- seed=seed,
1032
- motion_bucket_id=motion_bucket_id,
1033
- fps_id=fps_id
1034
- )
1035
-
1036
- if video_path and os.path.exists(video_path):
1037
- # Save video locally
1038
- video_filename = f"generated_video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
1039
  try:
1040
- shutil.copy(video_path, video_filename)
1041
-
1042
- # Display success and video
1043
- st.success(f"""
1044
- Video generated successfully! 🎉
1045
- - Seed: {used_seed}
1046
- - Motion Intensity: {motion_bucket_id}
1047
- - FPS: {fps_id}
1048
- """)
1049
 
1050
- st.video(video_filename)
 
 
 
 
 
 
 
 
1051
 
1052
- # Save to Cosmos DB
1053
- if container:
1054
- video_record = {
1055
- "id": generate_unique_id(),
1056
- "type": "generated_video",
1057
- "filename": video_filename,
1058
- "seed": used_seed,
1059
- "motion_bucket_id": motion_bucket_id,
1060
- "fps_id": fps_id,
1061
- "timestamp": datetime.now().isoformat()
1062
- }
1063
- success, message = insert_record(container, video_record)
1064
- if success:
1065
- st.success("Video record saved to database!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1066
  else:
1067
- st.error(f"Error saving video record: {message}")
 
 
 
1068
  except Exception as e:
1069
- st.error(f"Error saving video: {str(e)}")
1070
- else:
1071
- st.error("Video generation failed. Please try again with different parameters.")
1072
- except Exception as e:
1073
- st.error(f"Error during video generation process: {str(e)}")
 
 
 
 
 
 
 
1074
 
1075
  # ******************************************
1076
 
 
811
 
812
 
813
  # *********
814
+ def validate_and_preprocess_image(file_data, target_size=(576, 1024)):
815
+ """Validate and preprocess image for video generation with improved BytesIO handling"""
 
816
  try:
817
  st.write("Starting image preprocessing...")
818
 
819
+ # Handle different input types
820
+ if isinstance(file_data, bytes):
821
+ st.write("Processing bytes input")
822
+ img = Image.open(io.BytesIO(file_data))
823
+ elif hasattr(file_data, 'read'):
824
+ st.write("Processing file-like object")
825
+ # Reset file pointer if possible
826
+ if hasattr(file_data, 'seek'):
827
+ file_data.seek(0)
828
+ img = Image.open(file_data)
829
+ elif isinstance(file_data, Image.Image):
830
+ st.write("Processing PIL Image input")
831
+ img = file_data
832
  else:
833
+ raise ValueError(f"Unsupported input type: {type(file_data)}")
834
 
835
+ st.write(f"Successfully loaded image: {img.format}, size={img.size}, mode={img.mode}")
836
 
837
  # Convert to RGB if necessary
838
  if img.mode != 'RGB':
 
871
  final_img.paste(resized_img, (paste_x, paste_y))
872
 
873
  st.write(f"Final image size: {final_img.size}")
 
 
 
 
 
874
  return final_img
875
 
876
  except Exception as e:
877
+ st.error(f"Error in image preprocessing: {str(e)}\nType of input: {type(file_data)}")
878
  return None
879
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
880
  def add_video_generation_ui(container):
881
+ """Enhanced video generation UI with improved file handling"""
882
  st.markdown("### 🎥 Video Generation")
883
 
884
  col1, col2 = st.columns([2, 1])
885
 
886
  with col1:
887
+ uploaded_file = st.file_uploader(
888
  "Upload Image for Video Generation 🖼️",
889
  type=['png', 'jpg', 'jpeg'],
890
  help="Upload a clear, well-lit image. Recommended size: 576x1024 pixels."
 
907
  help="Higher values create smoother but potentially less stable videos"
908
  )
909
 
 
910
  with st.expander("Advanced Options"):
911
  use_custom_seed = st.checkbox("Use Custom Seed")
912
  if use_custom_seed:
 
914
  else:
915
  seed = None
916
 
917
+ if uploaded_file is not None:
918
  try:
919
+ # Read file data
920
+ file_data = uploaded_file.read()
921
+
922
  # Preview original image
923
  preview_col1, preview_col2 = st.columns(2)
924
  with preview_col1:
925
  st.write("Original Image:")
926
+ original_img = Image.open(io.BytesIO(file_data))
927
+ st.image(original_img, caption="Original", use_column_width=True)
928
 
929
  # Preview preprocessed image
930
  with preview_col2:
931
+ # Create a new BytesIO object with the file data
932
+ preprocessed = validate_and_preprocess_image(io.BytesIO(file_data))
933
  if preprocessed:
934
  st.write("Preprocessed Image:")
935
  st.image(preprocessed, caption="Preprocessed", use_column_width=True)
936
+ else:
937
+ st.error("Failed to preprocess image")
938
+ return
939
+
940
+ if st.button("🎥 Generate Video", help="Start video generation process"):
941
  with st.spinner("Processing your video... This may take a few minutes 🎬"):
942
+ # Save preprocessed image to temporary file
943
+ with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as temp_file:
944
+ preprocessed.save(temp_file.name, format='PNG')
945
+ st.write(f"Saved preprocessed image to temporary file: {temp_file.name}")
946
+
 
 
 
 
 
947
  try:
948
+ # Initialize the Gradio client
949
+ client = Client(
950
+ "awacke1/stable-video-diffusion",
951
+ hf_token=os.environ.get("HUGGINGFACE_TOKEN")
952
+ )
 
 
 
 
953
 
954
+ # Generate video
955
+ result = client.predict(
956
+ image=temp_file.name,
957
+ seed=seed if seed is not None else int(time.time() * 1000),
958
+ randomize_seed=seed is None,
959
+ motion_bucket_id=motion_bucket_id,
960
+ fps_id=fps_id,
961
+ api_name="/video"
962
+ )
963
 
964
+ if result and isinstance(result, tuple) and len(result) >= 1:
965
+ video_path = result[0].get('video') if isinstance(result[0], dict) else None
966
+ if video_path and os.path.exists(video_path):
967
+ # Save video locally
968
+ video_filename = f"generated_video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
969
+ shutil.copy(video_path, video_filename)
970
+
971
+ st.success(f"""
972
+ Video generated successfully! 🎉
973
+ - Seed: {seed if seed is not None else 'Random'}
974
+ - Motion Intensity: {motion_bucket_id}
975
+ - FPS: {fps_id}
976
+ """)
977
+
978
+ st.video(video_filename)
979
+
980
+ # Save to Cosmos DB
981
+ if container:
982
+ video_record = {
983
+ "id": generate_unique_id(),
984
+ "type": "generated_video",
985
+ "filename": video_filename,
986
+ "seed": seed if seed is not None else "random",
987
+ "motion_bucket_id": motion_bucket_id,
988
+ "fps_id": fps_id,
989
+ "timestamp": datetime.now().isoformat()
990
+ }
991
+ success, message = insert_record(container, video_record)
992
+ if success:
993
+ st.success("Video record saved to database!")
994
+ else:
995
+ st.error(f"Error saving video record: {message}")
996
  else:
997
+ st.error("Failed to generate video: Invalid result format")
998
+ else:
999
+ st.error("Failed to generate video: No result returned")
1000
+
1001
  except Exception as e:
1002
+ st.error(f"Error generating video: {str(e)}")
1003
+ finally:
1004
+ # Cleanup temporary file
1005
+ try:
1006
+ os.unlink(temp_file.name)
1007
+ st.write("Cleaned up temporary file")
1008
+ except Exception as e:
1009
+ st.warning(f"Error cleaning up temporary file: {str(e)}")
1010
+
1011
+ except Exception as e:
1012
+ st.error(f"Error processing uploaded file: {str(e)}")
1013
+
1014
 
1015
  # ******************************************
1016