haepada commited on
Commit
34cd2ff
·
verified ·
1 Parent(s): aa9026f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +98 -44
app.py CHANGED
@@ -575,6 +575,7 @@ def safe_state_update(state, updates):
575
  return state
576
 
577
  def create_interface():
 
578
  import base64
579
 
580
  # initial_state 정의
@@ -617,7 +618,7 @@ def create_interface():
617
  AUDIO_PLAYER_HTML = """
618
  <div class="audio-player-container">
619
  <audio id="mainAudio" preload="auto">
620
- <source src="/assets/main_music.mp3" type="audio/mp3">
621
  Your browser does not support the audio element.
622
  </audio>
623
  <button id="playButton" onclick="togglePlay()" class="custom-audio-button">
@@ -631,6 +632,7 @@ def create_interface():
631
 
632
  function togglePlay() {
633
  if (!isPlaying) {
 
634
  audioElement.play()
635
  .then(() => {
636
  isPlaying = true;
@@ -647,20 +649,17 @@ def create_interface():
647
  }
648
  }
649
 
650
- // 페이지 벗어날 때 오디오 정지
651
- window.addEventListener('beforeunload', function() {
652
- if (audioElement) {
653
- audioElement.pause();
654
- audioElement.currentTime = 0;
655
- }
656
  });
657
 
658
- // 오디오 로딩 에러 처리
659
  audioElement.addEventListener('error', function(e) {
660
  console.error("Audio error:", e);
661
  alert("음악 파일을 불러오는데 실패했습니다. 페이지를 새로고침해주세요.");
662
  });
663
  </script>
 
664
  <style>
665
  .audio-player-container {
666
  margin: 20px 0;
@@ -696,33 +695,33 @@ def create_interface():
696
  """
697
 
698
  css = """
699
- /* 기존 CSS 유지 */
700
  .gradio-container {
701
- max-width: 100% !important;
702
- padding: 0 !important;
 
703
  }
704
-
705
- /* 모바일 최적화 */
706
  @media (max-width: 600px) {
707
- .logo-container {
708
- padding: 20px 10px !important;
709
- width: 100% !important;
710
- }
711
- .desktop-logo { display: none !important; }
712
- .mobile-logo {
713
- width: 100% !important;
714
- height: auto !important;
715
- max-width: 300px !important;
716
- margin: 0 auto !important;
717
- display: block !important;
718
  }
719
- .gradio-button {
 
 
720
  min-height: 44px !important;
721
- margin: 10px 0 !important;
722
  }
723
- input[type="text"], textarea {
724
- font-size: 16px !important;
725
- padding: 12px !important;
 
 
 
 
 
726
  }
727
  }
728
 
@@ -742,12 +741,69 @@ def create_interface():
742
  margin: 0 auto;
743
  display: block;
744
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
745
  }
746
  """
747
 
748
  with gr.Blocks(theme=gr.themes.Soft(), css=css) as app:
749
  state = gr.State(value=initial_state)
750
-
751
  with gr.Column(elem_classes="logo-container"):
752
  gr.HTML(f"""
753
  <img class="mobile-logo" src="data:image/png;base64,{mobile_logo}" alt="디지털 굿판 로고 모바일">
@@ -835,9 +891,7 @@ def create_interface():
835
  # 기원 탭
836
  with gr.TabItem("기원") as tab_wish:
837
  gr.Markdown("## 기원 - 소원을 전해보세요")
838
-
839
- # 상태 표시 추가
840
- processing_status = gr.Markdown("", visible=False)
841
 
842
  with gr.Row():
843
  with gr.Column():
@@ -845,12 +899,13 @@ def create_interface():
845
  label="소원을 나누고 싶은 마음을 말해주세요",
846
  sources=["microphone"],
847
  type="numpy",
848
- streaming=False
 
849
  )
850
  with gr.Row():
851
  clear_btn = gr.Button("녹음 지우기", variant="secondary")
852
  analyze_btn = gr.Button("소원 분석하기", variant="primary")
853
-
854
  with gr.Column():
855
  transcribed_text = gr.Textbox(
856
  label="인식된 텍스트",
@@ -1043,25 +1098,24 @@ def create_interface():
1043
  print(f"Error saving wish: {e}")
1044
  return "오류가 발생했습니다.", []
1045
 
1046
- def safe_analyze_voice(audio_data, state):
1047
- """음성 분석 함수에 안전장치 추가"""
1048
  if audio_data is None:
1049
- return state, "음성을 먼저 녹음해주세요.", "", "", "", gr.update(visible=False)
1050
 
1051
  try:
1052
- processing_status.update(value="분석 중입니다...", visible=True)
1053
- result = analyze_voice(audio_data, state)
1054
- processing_status.update(value="", visible=False)
1055
  return (*result, gr.update(visible=False))
1056
  except Exception as e:
1057
  print(f"Voice analysis error: {str(e)}")
1058
  return (
1059
- state,
1060
  "음성 분석 중 오류가 발생했습니다. 다시 시도해주세요.",
1061
  "",
1062
  "",
1063
  "",
1064
- gr.update(visible=False)
1065
  )
1066
 
1067
 
@@ -1102,7 +1156,7 @@ def create_interface():
1102
  analyze_btn.click(
1103
  fn=safe_analyze_voice,
1104
  inputs=[voice_input, state],
1105
- outputs=[state, transcribed_text, voice_emotion, text_emotion, final_prompt, processing_status]
1106
  )
1107
 
1108
  generate_btn.click(
 
575
  return state
576
 
577
  def create_interface():
578
+ db = SimpleDB() # DB 객체 초기화 추가
579
  import base64
580
 
581
  # initial_state 정의
 
618
  AUDIO_PLAYER_HTML = """
619
  <div class="audio-player-container">
620
  <audio id="mainAudio" preload="auto">
621
+ <source src="assets/main_music.mp3" type="audio/mp3">
622
  Your browser does not support the audio element.
623
  </audio>
624
  <button id="playButton" onclick="togglePlay()" class="custom-audio-button">
 
632
 
633
  function togglePlay() {
634
  if (!isPlaying) {
635
+ audioElement.load(); // 재생 전 로드 추가
636
  audioElement.play()
637
  .then(() => {
638
  isPlaying = true;
 
649
  }
650
  }
651
 
652
+ audioElement.addEventListener('ended', function() {
653
+ isPlaying = false;
654
+ playButtonText.textContent = '재생';
 
 
 
655
  });
656
 
 
657
  audioElement.addEventListener('error', function(e) {
658
  console.error("Audio error:", e);
659
  alert("음악 파일을 불러오는데 실패했습니다. 페이지를 새로고침해주세요.");
660
  });
661
  </script>
662
+
663
  <style>
664
  .audio-player-container {
665
  margin: 20px 0;
 
695
  """
696
 
697
  css = """
698
+ /* 전체 컨테이너 width 제한 */
699
  .gradio-container {
700
+ margin: 0 auto !important;
701
+ max-width: 800px !important;
702
+ padding: 1rem !important;
703
  }
704
+
705
+ /* 모바일 */
706
  @media (max-width: 600px) {
707
+ .container { padding: 10px !important; }
708
+ .gradio-row {
709
+ flex-direction: column !important;
710
+ gap: 10px !important;
 
 
 
 
 
 
 
711
  }
712
+ .gradio-button {
713
+ width: 100% !important;
714
+ margin: 5px 0 !important;
715
  min-height: 44px !important;
 
716
  }
717
+ .gradio-textbox { width: 100% !important; }
718
+ .gradio-audio { width: 100% !important; }
719
+ .gradio-image { width: 100% !important; }
720
+ #audio-recorder { width: 100% !important; }
721
+ #result-image { width: 100% !important; }
722
+ .gradio-dataframe {
723
+ overflow-x: auto !important;
724
+ max-width: 100% !important;
725
  }
726
  }
727
 
 
741
  margin: 0 auto;
742
  display: block;
743
  }
744
+ /* 데스크탑에서 2단 컬럼 레이아웃 보완 */
745
+ .gradio-row {
746
+ gap: 20px !important;
747
+ }
748
+ .gradio-row > .gradio-column {
749
+ flex: 1 !important;
750
+ min-width: 0 !important;
751
+ }
752
+ }
753
+
754
+ /* 전반적인 UI 개선 */
755
+ .gradio-button {
756
+ transition: all 0.3s ease;
757
+ border-radius: 8px !important;
758
+ }
759
+ .gradio-button:active {
760
+ transform: scale(0.98);
761
+ }
762
+
763
+ /* 컴포넌트 간격 조정 */
764
+ .gradio-column > *:not(:last-child) {
765
+ margin-bottom: 1rem !important;
766
+ }
767
+
768
+ /* 데이터프레임 스타일링 */
769
+ .gradio-dataframe {
770
+ border: 1px solid #e0e0e0;
771
+ border-radius: 8px;
772
+ overflow: hidden;
773
+ }
774
+
775
+ /* 오디오 플레이어 컨테이너 */
776
+ .audio-player-container {
777
+ max-width: 800px;
778
+ margin: 20px auto;
779
+ padding: 0 1rem;
780
+ }
781
+
782
+ /* 탭 스타일링 */
783
+ .tabs {
784
+ max-width: 800px;
785
+ margin: 0 auto;
786
+ }
787
+
788
+ /* 마크다운 컨텐츠 */
789
+ .markdown-content {
790
+ max-width: 800px;
791
+ margin: 0 auto;
792
+ padding: 0 1rem;
793
+ }
794
+
795
+ /* 이미지 컨테이너 */
796
+ .gradio-image {
797
+ border-radius: 8px;
798
+ overflow: hidden;
799
+ max-width: 800px;
800
+ margin: 0 auto;
801
  }
802
  """
803
 
804
  with gr.Blocks(theme=gr.themes.Soft(), css=css) as app:
805
  state = gr.State(value=initial_state)
806
+ processing_status = gr.State("")
807
  with gr.Column(elem_classes="logo-container"):
808
  gr.HTML(f"""
809
  <img class="mobile-logo" src="data:image/png;base64,{mobile_logo}" alt="디지털 굿판 로고 모바일">
 
891
  # 기원 탭
892
  with gr.TabItem("기원") as tab_wish:
893
  gr.Markdown("## 기원 - 소원을 전해보세요")
894
+ status_display = gr.Markdown("", visible=False) # 상태 표시용 컴포넌트
 
 
895
 
896
  with gr.Row():
897
  with gr.Column():
 
899
  label="소원을 나누고 싶은 마음을 말해주세요",
900
  sources=["microphone"],
901
  type="numpy",
902
+ streaming=False,
903
+ elem_id="voice-input" # elem_id 추가
904
  )
905
  with gr.Row():
906
  clear_btn = gr.Button("녹음 지우기", variant="secondary")
907
  analyze_btn = gr.Button("소원 분석하기", variant="primary")
908
+
909
  with gr.Column():
910
  transcribed_text = gr.Textbox(
911
  label="인식된 텍스트",
 
1098
  print(f"Error saving wish: {e}")
1099
  return "오류가 발생했습니다.", []
1100
 
1101
+ def safe_analyze_voice(audio_data, current_state):
 
1102
  if audio_data is None:
1103
+ return current_state, "음성을 먼저 녹음해주세요.", "", "", "", gr.update(visible=True)
1104
 
1105
  try:
1106
+ status_display.update(value="분석 중입니다...", visible=True)
1107
+ result = analyze_voice(audio_data, current_state)
1108
+ status_display.update(value="", visible=False)
1109
  return (*result, gr.update(visible=False))
1110
  except Exception as e:
1111
  print(f"Voice analysis error: {str(e)}")
1112
  return (
1113
+ current_state,
1114
  "음성 분석 중 오류가 발생했습니다. 다시 시도해주세요.",
1115
  "",
1116
  "",
1117
  "",
1118
+ gr.update(visible=True)
1119
  )
1120
 
1121
 
 
1156
  analyze_btn.click(
1157
  fn=safe_analyze_voice,
1158
  inputs=[voice_input, state],
1159
+ outputs=[state, transcribed_text, voice_emotion, text_emotion, final_prompt, status_display]
1160
  )
1161
 
1162
  generate_btn.click(