haepada commited on
Commit
69feb4b
·
verified ·
1 Parent(s): dddc22b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +165 -71
app.py CHANGED
@@ -53,12 +53,18 @@ def serve_wishes(path):
53
 
54
 
55
  class SimpleDB:
56
- def __init__(self, reflections_path="data/reflections.json", wishes_path="data/wishes.json"):
57
- self.reflections_path = reflections_path
 
 
 
 
 
 
58
  self.wishes_path = wishes_path
59
- os.makedirs('data', exist_ok=True)
60
- self.reflections = self._load_json(reflections_path)
61
  self.wishes = self._load_json(wishes_path)
 
62
 
63
  def _load_json(self, file_path):
64
  if not os.path.exists(file_path):
@@ -71,29 +77,28 @@ class SimpleDB:
71
  print(f"Error loading {file_path}: {e}")
72
  return []
73
 
74
- def save_reflection(self, name, reflection, sentiment, timestamp=None):
75
- if timestamp is None:
76
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
77
-
78
  reflection_data = {
79
- "timestamp": timestamp,
80
  "name": name,
81
  "reflection": reflection,
82
  "sentiment": sentiment
83
  }
84
-
85
- self.reflections.append(reflection_data)
86
- self._save_json(self.reflections_path, self.reflections)
87
  return True
88
 
89
- def save_wish(self, name, wish, emotion_data=None, timestamp=None):
90
- if timestamp is None:
91
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
 
92
  wish_data = {
 
93
  "name": name,
94
  "wish": wish,
95
- "emotion": emotion_data,
96
- "timestamp": timestamp
97
  }
98
  self.wishes.append(wish_data)
99
  self._save_json(self.wishes_path, self.wishes)
@@ -108,11 +113,17 @@ class SimpleDB:
108
  print(f"Error saving to {file_path}: {e}")
109
  return False
110
 
111
- def get_all_reflections(self):
112
- return sorted(self.reflections, key=lambda x: x["timestamp"], reverse=True)
 
113
 
114
  def get_all_wishes(self):
115
- return self.wishes
 
 
 
 
 
116
 
117
  # API 설정
118
  HF_API_TOKEN = os.getenv("roots", "")
@@ -646,59 +657,142 @@ def create_interface():
646
  with blessing_section:
647
  gr.Markdown("### 축원의식을 시작하겠습니다")
648
  gr.Markdown("'명짐 복짐 짊어지고 안가태평하시기를 비도발원 축원 드립니다'")
649
- baseline_audio = gr.Audio(
650
- label="축원 문장 녹음하기",
651
- sources=["microphone"],
652
- type="numpy",
653
- streaming=False
654
- )
655
- set_baseline_btn = gr.Button("축원 마치기", variant="primary")
656
- baseline_status = gr.Markdown("")
657
-
658
- # 4단계: 굿판 입장 안내
659
- entry_guide_section = gr.Column(visible=False)
660
- with entry_guide_section:
661
- gr.Markdown("## 굿판으로 입장하기")
662
- gr.Markdown("""
663
- * 청신 탭으로 이동해 주세요.
664
- * 부산광역시 동래구 온천장역에서 시작하면 더욱 깊은 경험을 시작할 수 있습니다.
665
- * (본격적인 경험을 시작하기에 앞서 이동을 권장드립니다)
666
- """)
667
- enter_btn = gr.Button("청신 의식 시작하기", variant="primary")
668
-
669
- with gr.TabItem("청신") as tab_listen:
670
- gr.Markdown("## 청신 - 소리로 정화하기")
671
- gr.Markdown("""
672
- 온천천의 소리를 들으며 마음을 정화해보세요.
673
-
674
- 💫 이 앱은 온천천의 사운드스케이프를 녹음하여 제작되었으며,
675
- 온천천 온천장역에서 장전역까지 걸으며 더 깊은 체험이 가능합니다.
676
- """)
677
- play_music_btn = gr.Button("온천천의 ���리 듣기", variant="secondary")
678
- with gr.Row():
679
- audio = gr.Audio(
680
- value="assets/main_music.mp3",
681
- type="filepath",
682
- label="온천천의 소리",
683
- interactive=False,
684
- show_download_button=True,
685
- visible=True
686
- )
687
- with gr.Column():
688
- reflection_input = gr.Textbox(
689
- label="지금 이 순간의 감상을 자유롭게 적어보세요",
690
- lines=3,
691
- max_lines=5
692
  )
693
- save_btn = gr.Button("감상 저장하기", variant="secondary")
694
- reflections_display = gr.Dataframe(
695
- headers=["시간", "감상", "감정 분석"],
696
- label="기록된 감상들",
697
- value=[], # 초기값은 빈 리스트
698
- interactive=False,
699
- wrap=True,
700
- row_count=(5, "dynamic") # 동적으로 행 수 조정
701
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
 
703
  # 기원 탭
704
  with gr.TabItem("기원") as tab_wish:
 
53
 
54
 
55
  class SimpleDB:
56
+ """데이터 저장 및 관리 클래스"""
57
+
58
+ def __init__(self, wishes_path="data/wishes.json"):
59
+ """
60
+ 영구 저장이 필요한 소원 데이터만 파일로 관리
61
+ Args:
62
+ wishes_path: 소원 데이터 저장 경로
63
+ """
64
  self.wishes_path = wishes_path
65
+ os.makedirs(os.path.dirname(wishes_path), exist_ok=True)
 
66
  self.wishes = self._load_json(wishes_path)
67
+ self.session_reflections = [] # 임시 메모리에만 저장되는 감상
68
 
69
  def _load_json(self, file_path):
70
  if not os.path.exists(file_path):
 
77
  print(f"Error loading {file_path}: {e}")
78
  return []
79
 
80
+ def save_reflection(self, name, reflection, sentiment):
81
+ """
82
+ 감상은 세션 메모리에만 저장
83
+ """
84
  reflection_data = {
85
+ "timestamp": datetime.now().strftime("%H:%M:%S"),
86
  "name": name,
87
  "reflection": reflection,
88
  "sentiment": sentiment
89
  }
90
+ self.session_reflections.append(reflection_data)
 
 
91
  return True
92
 
93
+ def save_wish(self, name, wish, emotion_data=None):
94
+ """
95
+ 소원은 영구 저장
96
+ """
97
  wish_data = {
98
+ "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
99
  "name": name,
100
  "wish": wish,
101
+ "emotion": emotion_data
 
102
  }
103
  self.wishes.append(wish_data)
104
  self._save_json(self.wishes_path, self.wishes)
 
113
  print(f"Error saving to {file_path}: {e}")
114
  return False
115
 
116
+ def get_session_reflections(self):
117
+ """현재 세션의 감상만 반환"""
118
+ return self.session_reflections
119
 
120
  def get_all_wishes(self):
121
+ """저장된 모든 소원 반환"""
122
+ return sorted(self.wishes, key=lambda x: x["timestamp"], reverse=True)
123
+
124
+ def clear_session_data(self):
125
+ """세션 데이터 초기화"""
126
+ self.session_reflections = []
127
 
128
  # API 설정
129
  HF_API_TOKEN = os.getenv("roots", "")
 
657
  with blessing_section:
658
  gr.Markdown("### 축원의식을 시작하겠습니다")
659
  gr.Markdown("'명짐 복짐 짊어지고 안가태평하시기를 비도발원 축원 드립니다'")
660
+ with gr.Column() as recording_section:
661
+ baseline_audio = gr.Audio(
662
+ label="축원 문장 녹음하기",
663
+ sources=["microphone"],
664
+ type="numpy",
665
+ streaming=False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
666
  )
667
+ analysis_status = gr.Markdown(
668
+ "축원 문장을 녹음해주세요.",
669
+ visible=True
 
 
 
 
 
670
  )
671
+
672
+ with gr.Column(visible=False) as analysis_results:
673
+ voice_analysis = gr.Markdown("")
674
+ set_baseline_btn = gr.Button(
675
+ "축원 마치기",
676
+ variant="primary",
677
+ visible=False
678
+ )
679
+
680
+ def handle_baseline_recording(audio, state):
681
+ """기준 음성 분석"""
682
+ if audio is None:
683
+ return {
684
+ "state": state,
685
+ "status": "축원 문장을 녹음해주세요.",
686
+ "analysis_visible": False,
687
+ "button_visible": False,
688
+ "analysis_text": ""
689
+ }
690
+
691
+ try:
692
+ # 분석 중임을 표시
693
+ yield {
694
+ "state": state,
695
+ "status": "음성을 분석하고 있습니다...",
696
+ "analysis_visible": False,
697
+ "button_visible": False,
698
+ "analysis_text": ""
699
+ }
700
+
701
+ # 음성 분석
702
+ features = calculate_baseline_features(audio)
703
+ if features is None:
704
+ return {
705
+ "state": state,
706
+ "status": "음성 분석에 실패했습니다. 다시 시도해주세요.",
707
+ "analysis_visible": False,
708
+ "button_visible": False,
709
+ "analysis_text": ""
710
+ }
711
+
712
+ # 감정 분석
713
+ baseline_emotion = map_acoustic_to_emotion(features)
714
+
715
+ # 분석 결과 생성
716
+ analysis_text = (
717
+ f"기준 음성 분석 결과:\n"
718
+ f"- 감정: {baseline_emotion['primary']}\n"
719
+ f"- 에너지 레벨: {baseline_emotion['details']['energy_level']}\n"
720
+ f"- 말하기 속도: {baseline_emotion['details']['speech_rate']}\n"
721
+ f"- 음높이: {baseline_emotion['details']['pitch_variation']}\n"
722
+ f"이 음성을 기준으로 이후 소원을 비교 분석합니다."
723
+ )
724
+
725
+ # 상태 업데이트
726
+ new_state = {**state, "baseline_features": features, "analysis_complete": True}
727
+
728
+ return {
729
+ "state": new_state,
730
+ "status": "",
731
+ "analysis_visible": True,
732
+ "button_visible": True,
733
+ "analysis_text": analysis_text
734
+ }
735
+
736
+ except Exception as e:
737
+ return {
738
+ "state": state,
739
+ "status": f"오류가 발생했습니다: {str(e)}",
740
+ "analysis_visible": False,
741
+ "button_visible": False,
742
+ "analysis_text": ""
743
+ }
744
+
745
+ def handle_blessing_complete(state):
746
+ """축원 완료 처리"""
747
+ if not state.get("analysis_complete"):
748
+ return state, "음성 분석이 완료되지 않았습니다.", gr.update(visible=True), gr.update(visible=False)
749
+
750
+ return state, "", gr.update(visible=False), gr.update(visible=True)
751
+
752
+ # 4단계: 굿판 입장 안내
753
+ entry_guide_section = gr.Column(visible=False)
754
+ with entry_guide_section:
755
+ gr.Markdown("## 굿판으로 입장하기")
756
+ gr.Markdown("""
757
+ * 청신 탭으로 이동해 주세요.
758
+ * 부산광역시 동래구 온천장역에서 시작하면 더욱 깊은 경험을 시작할 수 있습니다.
759
+ * (본격적인 경험을 시작하기에 앞서 이동을 권장드립니다)
760
+ """)
761
+ enter_btn = gr.Button("청신 의식 시작하기", variant="primary")
762
+
763
+ with gr.TabItem("청신") as tab_listen:
764
+ gr.Markdown("## 청신 - 소리로 정화하기")
765
+ gr.Markdown("""
766
+ 온천천의 소리를 들으며 마음을 정화해보세요.
767
+
768
+ 💫 이 앱은 온천천의 사운드스케이프를 녹음하여 제작되었으며,
769
+ 온천천 온천장역에서 장전역까지 걸으며 더 깊은 체험이 가능합니다.
770
+ """)
771
+ play_music_btn = gr.Button("온천천의 소리 듣기", variant="secondary")
772
+ with gr.Row():
773
+ audio = gr.Audio(
774
+ value="assets/main_music.mp3",
775
+ type="filepath",
776
+ label="온천천의 소리",
777
+ interactive=False,
778
+ show_download_button=True,
779
+ visible=True
780
+ )
781
+ with gr.Column():
782
+ reflection_input = gr.Textbox(
783
+ label="지금 이 순간의 감상을 자유롭게 적어보세요",
784
+ lines=3,
785
+ max_lines=5
786
+ )
787
+ save_btn = gr.Button("감상 저장하기", variant="secondary")
788
+ reflections_display = gr.Dataframe(
789
+ headers=["시간", "감상", "감정 분석"],
790
+ label="기록된 감상들",
791
+ value=[], # 초기값은 빈 리스트
792
+ interactive=False,
793
+ wrap=True,
794
+ row_count=(5, "dynamic") # 동적으로 행 수 조정
795
+ )
796
 
797
  # 기원 탭
798
  with gr.TabItem("기원") as tab_wish: