jfforero commited on
Commit
f3b54b2
·
verified ·
1 Parent(s): 9b34f1a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -71
app.py CHANGED
@@ -30,6 +30,8 @@ import base64
30
  from io import BytesIO
31
  import struct
32
  import cv2
 
 
33
 
34
  # Load the emotion prediction model
35
  def load_emotion_model(model_path):
@@ -306,7 +308,7 @@ def upscale_image(image, target_width=4096, target_height=2048):
306
  )
307
  return Image.fromarray(upscaled)
308
 
309
- # ADD THE MISSING generate_image FUNCTION HERE
310
  def generate_image(sentiment_prediction, transcribed_text, chunk_idx, total_chunks):
311
  try:
312
  if not api_key:
@@ -514,14 +516,14 @@ def create_360_viewer_html(image_paths, audio_paths, output_path):
514
  else:
515
  audio_data_list.append(None) # Placeholder for chunks without audio
516
 
517
- # Create the HTML content
518
  html_content = f"""
519
  <!DOCTYPE html>
520
  <html lang="en">
521
  <head>
522
  <meta charset="UTF-8">
523
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
524
- <title>360 Panorama Viewer with Audio</title>
525
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pannellum@2.5.6/build/pannellum.css"/>
526
  <style>
527
  body {{
@@ -676,7 +678,6 @@ def create_360_viewer_html(image_paths, audio_paths, output_path):
676
 
677
  return output_path
678
 
679
-
680
  # Update the process_and_display function
681
  def process_and_display(audio_input, generate_audio, chunk_duration):
682
  # Validate chunk duration
@@ -691,7 +692,7 @@ def process_and_display(audio_input, generate_audio, chunk_duration):
691
  <style>@keyframes spin {{ 0% {{ transform: rotate(0deg); }} 100% {{ transform: rotate(360deg); }} }}</style>
692
  <p style="font-size: 14px; color: #4a4a4a;">This may take several minutes depending on the audio length...</p>
693
  </div>
694
- """)] + [gr.Group(visible=False)] * len(group_components) + [None] * (len(output_containers) * 6) + [None, ""]
695
 
696
  results = get_predictions(audio_input, generate_audio, chunk_duration)
697
 
@@ -729,12 +730,47 @@ def process_and_display(audio_input, generate_audio, chunk_duration):
729
 
730
  # Create 360 viewer HTML if we have 360 images
731
  viewer_html_path = None
 
732
  if all_360_images:
733
- with tempfile.NamedTemporaryFile(suffix=".html", delete=False) as tmp_file:
734
- viewer_html_path = create_360_viewer_html(all_360_images, all_music_paths, tmp_file.name)
735
-
736
- # Hide loading indicator and show results
737
- yield [gr.HTML("")] + group_visibility + outputs + [viewer_html_path, ""]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
738
 
739
  # Update the clear_all function to handle the new outputs
740
  def clear_all():
@@ -745,7 +781,8 @@ def clear_all():
745
  outputs.extend([gr.Group(visible=False)] * len(group_components))
746
 
747
  # For all output containers (set to None)
748
- outputs.extend([None] * (len(output_containers) * 6))
 
749
 
750
  # For loading indicator (empty HTML)
751
  outputs.append(gr.HTML(""))
@@ -759,6 +796,9 @@ def clear_all():
759
  # For viewer (set to None)
760
  outputs.append(None)
761
 
 
 
 
762
  # For JavaScript output (empty)
763
  outputs.append("")
764
 
@@ -771,9 +811,28 @@ def load_example_audio(example_name):
771
  return None
772
 
773
  # Create the Gradio interface with proper output handling
774
-
775
- # Update the Gradio interface with a more prominent download button
776
- with gr.Blocks(title="Affective Virtual Environments - Chunked Processing") as interface:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
777
  gr.Markdown("# Affective Virtual Environments")
778
  gr.Markdown("Create an AVE using your voice. Audio is split into chunks, with separate predictions and generations for each segment.")
779
 
@@ -813,13 +872,7 @@ with gr.Blocks(title="Affective Virtual Environments - Chunked Processing") as i
813
  clear_btn = gr.Button("Clear All", variant="secondary")
814
 
815
  # Add a loading indicator
816
- loading_indicator = gr.HTML("""
817
- <div id="loading" style="display: none; text-align: center; margin: 20px;">
818
- <p style="font-size: 18px; color: #4a4a4a;">Processing audio chunks...</p>
819
- <div style="border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; width: 30px; height: 30px; animation: spin 2s linear infinite; margin: 0 auto;"></div>
820
- <style>@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }</style>
821
- </div>
822
- """)
823
 
824
  # Create output components for each chunk type
825
  output_containers = []
@@ -838,7 +891,7 @@ with gr.Blocks(title="Affective Virtual Environments - Chunked Processing") as i
838
  image_360_output = gr.File(label="Download 360 Image", type="filepath")
839
  with gr.Row():
840
  audio_output = gr.Audio(label="Generated Music")
841
- gr.HTML("<hr style='margin: 20px 0; border: 1px solid #ccc;'>")
842
 
843
  group_components.append(chunk_group)
844
  output_containers.append({
@@ -850,47 +903,16 @@ with gr.Blocks(title="Affective Virtual Environments - Chunked Processing") as i
850
  'music': audio_output
851
  })
852
 
853
- # Add component for 360 viewer with a more prominent download button
854
- with gr.Group(visible=False) as viewer_group:
855
- gr.Markdown("### 🎯 360 Viewer Results")
856
- gr.Markdown("Your interactive 360 viewer is ready! Download the HTML file to view your generated environments in a web browser.")
857
-
858
- # Create a row with a prominent download button
859
- with gr.Row():
860
- viewer_html_output = gr.File(
861
- label="360 Viewer HTML File",
862
- type="filepath",
863
- interactive=False,
864
- elem_classes=["prominent-download"]
865
- )
866
-
867
- # Add a custom CSS class to make the download button more prominent
868
- gr.HTML("""
869
- <style>
870
- .prominent-download .gr-button {
871
- background: linear-gradient(45deg, #FF3366, #FF9933) !important;
872
- color: white !important;
873
- font-size: 18px !important;
874
- font-weight: bold !important;
875
- padding: 15px 25px !important;
876
- border-radius: 8px !important;
877
- border: none !important;
878
- box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;
879
- transition: all 0.3s ease !important;
880
- }
881
- .prominent-download .gr-button:hover {
882
- transform: scale(1.05) !important;
883
- box-shadow: 0 6px 12px rgba(0,0,0,0.3) !important;
884
- }
885
- .prominent-download .gr-button:before {
886
- content: "⬇️ " !important;
887
- margin-right: 8px !important;
888
- }
889
- </style>
890
- """)
891
-
892
- # Add the viewer group to the group components
893
- group_components.append(viewer_group)
894
 
895
  # Add a hidden HTML component for JavaScript execution
896
  js_output = gr.HTML(visible=False)
@@ -917,7 +939,7 @@ with gr.Blocks(title="Affective Virtual Environments - Chunked Processing") as i
917
  container['image'],
918
  container['image_360'],
919
  container['music']
920
- ]] + [viewer_html_output, js_output]
921
  )
922
 
923
  clear_btn.click(
@@ -930,7 +952,7 @@ with gr.Blocks(title="Affective Virtual Environments - Chunked Processing") as i
930
  container['image'],
931
  container['image_360'],
932
  container['music']
933
- ]] + [loading_indicator, chunk_duration_input, example_selector, viewer_html_output, js_output]
934
  )
935
 
936
  load_example_btn.click(
@@ -938,10 +960,7 @@ with gr.Blocks(title="Affective Virtual Environments - Chunked Processing") as i
938
  inputs=[example_selector],
939
  outputs=[audio_input, example_selector]
940
  )
941
-
942
- # Check if we're running on Hugging Face Spaces
943
- is_spaces = os.getenv('SPACE_ID') is not None
944
-
945
- # Launch with appropriate settings
946
- interface.launch(share=True) # Only share when not on Spaces
947
 
 
30
  from io import BytesIO
31
  import struct
32
  import cv2
33
+ import shutil
34
+ from datetime import datetime
35
 
36
  # Load the emotion prediction model
37
  def load_emotion_model(model_path):
 
308
  )
309
  return Image.fromarray(upscaled)
310
 
311
+ # Function to generate image using DeepAI API
312
  def generate_image(sentiment_prediction, transcribed_text, chunk_idx, total_chunks):
313
  try:
314
  if not api_key:
 
516
  else:
517
  audio_data_list.append(None) # Placeholder for chunks without audio
518
 
519
+ # Create the HTML content
520
  html_content = f"""
521
  <!DOCTYPE html>
522
  <html lang="en">
523
  <head>
524
  <meta charset="UTF-8">
525
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
526
+ <title>My AVE - 360 Panorama Viewer with Audio</title>
527
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pannellum@2.5.6/build/pannellum.css"/>
528
  <style>
529
  body {{
 
678
 
679
  return output_path
680
 
 
681
  # Update the process_and_display function
682
  def process_and_display(audio_input, generate_audio, chunk_duration):
683
  # Validate chunk duration
 
692
  <style>@keyframes spin {{ 0% {{ transform: rotate(0deg); }} 100% {{ transform: rotate(360deg); }} }}</style>
693
  <p style="font-size: 14px; color: #4a4a4a;">This may take several minutes depending on the audio length...</p>
694
  </div>
695
+ """)] + [gr.Group(visible=False)] * len(group_components) + [None] * (len(output_containers) * 6) + [None, None, ""]
696
 
697
  results = get_predictions(audio_input, generate_audio, chunk_duration)
698
 
 
730
 
731
  # Create 360 viewer HTML if we have 360 images
732
  viewer_html_path = None
733
+ download_button_html = ""
734
  if all_360_images:
735
+ # Create a timestamp for unique filenames
736
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
737
+ html_filename = f"MyAVE_{timestamp}.html"
738
+
739
+ # Create a temporary directory for our output
740
+ output_dir = tempfile.mkdtemp()
741
+ viewer_html_path = os.path.join(output_dir, html_filename)
742
+
743
+ # Create the HTML file
744
+ create_360_viewer_html(all_360_images, all_music_paths, viewer_html_path)
745
+
746
+ # Create a beautiful download button for the Gradio interface
747
+ download_button_html = f"""
748
+ <div style="text-align: center; margin: 20px;">
749
+ <a href="/file={viewer_html_path}" download="MyAVE.html">
750
+ <button style="
751
+ background: linear-gradient(to bottom, #4CAF50, #45a049);
752
+ color: white;
753
+ border: none;
754
+ padding: 15px 30px;
755
+ text-align: center;
756
+ text-decoration: none;
757
+ display: inline-block;
758
+ font-size: 18px;
759
+ margin: 10px 2px;
760
+ cursor: pointer;
761
+ border-radius: 25px;
762
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
763
+ transition: all 0.3s ease;
764
+ ">
765
+ 📥 Download Complete AVE Experience
766
+ </button>
767
+ </a>
768
+ <p style="font-size: 14px; color: #4a4a4a;">Download the complete 360° experience with all chunks</p>
769
+ </div>
770
+ """
771
+
772
+ # After processing, return the results along with other outputs
773
+ yield [gr.HTML("")] + group_visibility + outputs + [viewer_html_path, gr.HTML(download_button_html), js_output]
774
 
775
  # Update the clear_all function to handle the new outputs
776
  def clear_all():
 
781
  outputs.extend([gr.Group(visible=False)] * len(group_components))
782
 
783
  # For all output containers (set to None)
784
+ for _ in output_containers:
785
+ outputs.extend([None, None, None, None, None, None]) # emotion, transcription, sentiment, image, image_360, music
786
 
787
  # For loading indicator (empty HTML)
788
  outputs.append(gr.HTML(""))
 
796
  # For viewer (set to None)
797
  outputs.append(None)
798
 
799
+ # For download button (empty HTML)
800
+ outputs.append(gr.HTML(""))
801
+
802
  # For JavaScript output (empty)
803
  outputs.append("")
804
 
 
811
  return None
812
 
813
  # Create the Gradio interface with proper output handling
814
+ with gr.Blocks(title="Affective Virtual Environments - Chunked Processing", css="""
815
+ .download-button {
816
+ background: linear-gradient(to bottom, #4CAF50, #45a049) !important;
817
+ color: white !important;
818
+ border: none !important;
819
+ padding: 15px 30px !important;
820
+ text-align: center !important;
821
+ text-decoration: none !important;
822
+ display: inline-block !important;
823
+ font-size: 18px !important;
824
+ margin: 10px 2px !important;
825
+ cursor: pointer !important;
826
+ border-radius: 25px !important;
827
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;
828
+ transition: all 0.3s ease !important;
829
+ }
830
+ .download-button:hover {
831
+ background: linear-gradient(to bottom, #45a049, #4CAF50) !important;
832
+ box-shadow: 0 6px 12px rgba(0,0,0,0.3) !important;
833
+ transform: translateY(-2px) !important;
834
+ }
835
+ """) as interface:
836
  gr.Markdown("# Affective Virtual Environments")
837
  gr.Markdown("Create an AVE using your voice. Audio is split into chunks, with separate predictions and generations for each segment.")
838
 
 
872
  clear_btn = gr.Button("Clear All", variant="secondary")
873
 
874
  # Add a loading indicator
875
+ loading_indicator = gr.HTML("")
 
 
 
 
 
 
876
 
877
  # Create output components for each chunk type
878
  output_containers = []
 
891
  image_360_output = gr.File(label="Download 360 Image", type="filepath")
892
  with gr.Row():
893
  audio_output = gr.Audio(label="Generated Music")
894
+ gr.Markdown("---") # Horizontal line using Markdown
895
 
896
  group_components.append(chunk_group)
897
  output_containers.append({
 
903
  'music': audio_output
904
  })
905
 
906
+ # Add component for 360 viewer
907
+ viewer_html_output = gr.File(
908
+ label="Complete AVE Experience (HTML)",
909
+ type="filepath",
910
+ interactive=False,
911
+ visible=False
912
+ )
913
+
914
+ # Add a beautiful download button component
915
+ download_button = gr.HTML("")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
916
 
917
  # Add a hidden HTML component for JavaScript execution
918
  js_output = gr.HTML(visible=False)
 
939
  container['image'],
940
  container['image_360'],
941
  container['music']
942
+ ]] + [viewer_html_output, download_button, js_output]
943
  )
944
 
945
  clear_btn.click(
 
952
  container['image'],
953
  container['image_360'],
954
  container['music']
955
+ ]] + [loading_indicator, chunk_duration_input, example_selector, viewer_html_output, download_button, js_output]
956
  )
957
 
958
  load_example_btn.click(
 
960
  inputs=[example_selector],
961
  outputs=[audio_input, example_selector]
962
  )
963
+
964
+ # Launch the interface
965
+ interface.launch()
 
 
 
966