haepada commited on
Commit
e006b08
·
verified ·
1 Parent(s): 8e216d6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -112
app.py CHANGED
@@ -4,11 +4,19 @@ import librosa
4
  from transformers import pipeline
5
  from datetime import datetime
6
  import os
 
 
 
 
 
 
 
 
7
 
8
  # AI 모델 초기화
9
  speech_recognizer = pipeline(
10
  "automatic-speech-recognition",
11
- model="kresnik/wav2vec2-large-xlsr-korean" # 한국어 음성인식 모델
12
  )
13
  emotion_classifier = pipeline(
14
  "audio-classification",
@@ -21,13 +29,12 @@ text_analyzer = pipeline(
21
 
22
  def create_interface():
23
  with gr.Blocks(theme=gr.themes.Soft()) as app:
24
- # 상태 관리
25
  state = gr.State({
26
  "user_name": "",
27
  "reflections": [],
28
  "voice_analysis": None,
29
  "final_prompt": "",
30
- "generated_images": [] # 생성된 이미지 저장
31
  })
32
 
33
  # 헤더
@@ -44,10 +51,14 @@ def create_interface():
44
  # 청신
45
  with gr.Tab("청신"):
46
  with gr.Row():
 
 
47
  audio = gr.Audio(
48
- value="assets/main_music.mp3",
49
  type="filepath",
50
- label="온천천의 소리"
 
 
51
  )
52
  with gr.Column():
53
  reflection_input = gr.Textbox(
@@ -64,14 +75,16 @@ def create_interface():
64
  with gr.Tab("기원"):
65
  gr.Markdown("## 기원 - 목소리로 전하기")
66
  with gr.Row():
67
- # 음성 입력
68
- voice_input = gr.Audio(
69
- label="나누고 싶은 이야기를 들려주세요",
70
- sources=["microphone"],
71
- type="filepath"
72
- )
 
 
 
73
 
74
- # 분석 결과
75
  with gr.Column():
76
  transcribed_text = gr.Textbox(
77
  label="인식된 텍스트",
@@ -85,9 +98,7 @@ def create_interface():
85
  label="텍스트 감정 분석",
86
  interactive=False
87
  )
88
- analysis_details = gr.JSON(
89
- label="상세 분석 결과"
90
- )
91
 
92
  # 송신
93
  with gr.Tab("송신"):
@@ -97,135 +108,91 @@ def create_interface():
97
  label="생성된 프롬프트",
98
  interactive=False
99
  )
 
100
  gallery = gr.Gallery(
101
  label="시각화 결과",
102
- columns=2
 
 
103
  )
104
- share_btn = gr.Button("결과 공유하기")
105
 
106
- def analyze_voice_comprehensive(audio_path, state):
107
- """종합적인 음성 분석"""
108
- try:
109
- if audio_path is None:
110
- return state, "음성 입력이 필요합니다.", "", "", {}
111
 
 
 
 
 
 
 
112
  # 오디오 로드
113
  y, sr = librosa.load(audio_path, sr=16000)
114
-
115
- # 1. 음성-텍스트 변환
116
  transcription = speech_recognizer(y)
117
- spoken_text = transcription["text"]
118
-
119
- # 2. 음향학적 특성 분석
120
- features = {
121
- "energy": float(np.mean(librosa.feature.rms(y=y))),
122
- "pitch": float(np.mean(librosa.piptrack(y=y, sr=sr)[1])),
123
- "tempo": float(librosa.beat.tempo(y)[0]),
124
- "zero_crossing_rate": float(np.mean(librosa.feature.zero_crossing_rate(y)))
125
- }
126
-
127
- # 3. 음성 감정 분석
128
  voice_emotions = emotion_classifier(y)
129
- primary_emotion = voice_emotions[0]
130
-
131
- # 4. 텍스트 감정 분석
132
- text_sentiment = text_analyzer(spoken_text)[0]
133
-
134
- # 결과 종합
135
- analysis_result = {
136
- "acoustic_features": features,
137
- "voice_emotion": primary_emotion,
138
- "text_sentiment": text_sentiment
139
- }
140
-
141
- # 프롬프트 생성
142
- prompt = generate_art_prompt(spoken_text, analysis_result, state["reflections"])
143
- state["final_prompt"] = prompt
144
-
145
  return (
146
  state,
147
- spoken_text,
148
- f"음성 감정: {primary_emotion['label']} ({primary_emotion['score']:.2f})",
149
  f"텍스트 감정: {text_sentiment['label']} ({text_sentiment['score']:.2f})",
150
- analysis_result
151
  )
152
-
153
  except Exception as e:
154
- return state, f"오류 발생: {str(e)}", "", "", {}
155
-
156
- def generate_art_prompt(text, analysis, reflections):
157
- """예술적 프롬프트 생성"""
158
- # 음성 감정
159
- voice_emotion = analysis["voice_emotion"]["label"]
160
- # 텍스트 감정
161
- text_sentiment = analysis["text_sentiment"]["label"]
162
- # 에너지 레벨
163
- energy = analysis["acoustic_features"]["energy"]
164
-
165
- # 감정에 따른 색상 매핑
166
- emotion_colors = {
167
- "happy": "따뜻한 노란색과 주황색",
168
- "sad": "깊은 파랑색과 보라색",
169
- "angry": "강렬한 빨강색과 검정색",
170
- "neutral": "부드러운 회색과 베이지색"
171
- }
172
-
173
- # 기본 프롬프트 구성
174
- prompt = f"한국 전통 민화 스타일의 추상화, {emotion_colors.get(voice_emotion, '자연스러운 색상')} 사용. "
175
- prompt += f"음성의 감정({voice_emotion})과 텍스트의 감정({text_sentiment})이 조화를 이루며, "
176
- prompt += f"에너지 레벨({energy:.2f})을 통해 화면의 동적인 느낌을 표현. "
177
-
178
- # 이전 감상들 반영
179
- if reflections:
180
- prompt += "이전 감상들의 정서를 배경에 은은하게 담아내기. "
181
-
182
- return prompt
183
-
184
- def save_reflection(text, state):
185
- """감상 저장 및 감정 분석"""
186
- if not text.strip():
187
- return state, state["reflections"]
188
-
189
- current_time = datetime.now().strftime("%H:%M:%S")
190
- sentiment = text_analyzer(text)[0]
191
- new_reflection = [current_time, text, f"{sentiment['label']} ({sentiment['score']:.2f})"]
192
-
193
- state["reflections"].append(new_reflection)
194
- return state, state["reflections"]
195
 
196
- def start_journey(name):
197
- """여정 시작"""
198
- welcome_text = f"# 환영합니다, {name}님의 디지털 굿판"
199
- return welcome_text, gr.update(selected="청신")
 
 
 
 
 
 
 
 
200
 
201
  # 이벤트 연결
202
  start_btn.click(
203
- fn=start_journey,
204
  inputs=[name_input],
205
  outputs=[user_display, tabs]
206
  )
207
 
208
  save_btn.click(
209
- fn=save_reflection,
210
  inputs=[reflection_input, state],
211
  outputs=[state, reflections_display]
212
  )
213
 
214
- voice_input.change(
215
- fn=analyze_voice_comprehensive,
 
 
 
 
 
 
216
  inputs=[voice_input, state],
217
- outputs=[
218
- state,
219
- transcribed_text,
220
- voice_emotion,
221
- text_emotion,
222
- analysis_details
223
- ]
224
  )
225
 
226
  return app
227
 
228
- # 앱 실행
229
  if __name__ == "__main__":
230
  demo = create_interface()
231
  demo.launch()
 
4
  from transformers import pipeline
5
  from datetime import datetime
6
  import os
7
+ from diffusers import StableDiffusionPipeline
8
+ import torch
9
+
10
+ # 스테이블 디퓨전 초기화
11
+ model_id = "runwayml/stable-diffusion-v1-5"
12
+ pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)
13
+ if torch.cuda.is_available():
14
+ pipe = pipe.to("cuda")
15
 
16
  # AI 모델 초기화
17
  speech_recognizer = pipeline(
18
  "automatic-speech-recognition",
19
+ model="kresnik/wav2vec2-large-xlsr-korean"
20
  )
21
  emotion_classifier = pipeline(
22
  "audio-classification",
 
29
 
30
  def create_interface():
31
  with gr.Blocks(theme=gr.themes.Soft()) as app:
 
32
  state = gr.State({
33
  "user_name": "",
34
  "reflections": [],
35
  "voice_analysis": None,
36
  "final_prompt": "",
37
+ "generated_images": []
38
  })
39
 
40
  # 헤더
 
51
  # 청신
52
  with gr.Tab("청신"):
53
  with gr.Row():
54
+ # 절대 경로로 변경
55
+ audio_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "assets", "main_music.mp3"))
56
  audio = gr.Audio(
57
+ value=audio_path,
58
  type="filepath",
59
+ label="온천천의 소리",
60
+ interactive=False,
61
+ autoplay=True
62
  )
63
  with gr.Column():
64
  reflection_input = gr.Textbox(
 
75
  with gr.Tab("기원"):
76
  gr.Markdown("## 기원 - 목소리로 전하기")
77
  with gr.Row():
78
+ with gr.Column():
79
+ record_btn = gr.Button("🎤 녹음 시작/중지")
80
+ voice_input = gr.Audio(
81
+ label="나누고 싶은 이야기를 들려주세요",
82
+ sources=["microphone"],
83
+ type="filepath",
84
+ interactive=True
85
+ )
86
+ clear_btn = gr.Button("녹음 지우기")
87
 
 
88
  with gr.Column():
89
  transcribed_text = gr.Textbox(
90
  label="인식된 텍스트",
 
98
  label="텍스트 감정 분석",
99
  interactive=False
100
  )
101
+ analyze_btn = gr.Button("분석하기")
 
 
102
 
103
  # 송신
104
  with gr.Tab("송신"):
 
108
  label="생성된 프롬프트",
109
  interactive=False
110
  )
111
+ generate_btn = gr.Button("이미지 생성하기")
112
  gallery = gr.Gallery(
113
  label="시각화 결과",
114
+ columns=2,
115
+ show_label=True,
116
+ elem_id="gallery"
117
  )
 
118
 
119
+ def clear_voice_input():
120
+ """음성 입력 초기화"""
121
+ return None
 
 
122
 
123
+ def analyze_voice(audio_path, state):
124
+ """음성 분석"""
125
+ if audio_path is None:
126
+ return state, "음성을 먼저 녹음해주세요.", "", "", ""
127
+
128
+ try:
129
  # 오디오 로드
130
  y, sr = librosa.load(audio_path, sr=16000)
131
+
132
+ # 음성 인식
133
  transcription = speech_recognizer(y)
134
+ text = transcription["text"]
135
+
136
+ # 감정 분석
 
 
 
 
 
 
 
 
137
  voice_emotions = emotion_classifier(y)
138
+ text_sentiment = text_analyzer(text)[0]
139
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  return (
141
  state,
142
+ text,
143
+ f"음성 감정: {voice_emotions[0]['label']} ({voice_emotions[0]['score']:.2f})",
144
  f"텍스트 감정: {text_sentiment['label']} ({text_sentiment['score']:.2f})",
145
+ "분석이 완료되었습니다."
146
  )
 
147
  except Exception as e:
148
+ return state, f"오류 발생: {str(e)}", "", "", ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
+ def generate_image(prompt, state):
151
+ """이미지 생성"""
152
+ try:
153
+ images = pipe(prompt).images
154
+ image_paths = []
155
+ for i, image in enumerate(images):
156
+ path = f"output_{i}.png"
157
+ image.save(path)
158
+ image_paths.append(path)
159
+ return image_paths
160
+ except Exception as e:
161
+ return []
162
 
163
  # 이벤트 연결
164
  start_btn.click(
165
+ fn=lambda name: (f"# 환영합니다, {name}님의 디지털 굿판", gr.update(selected="청신")),
166
  inputs=[name_input],
167
  outputs=[user_display, tabs]
168
  )
169
 
170
  save_btn.click(
171
+ fn=lambda text, state: save_reflection(text, state),
172
  inputs=[reflection_input, state],
173
  outputs=[state, reflections_display]
174
  )
175
 
176
+ clear_btn.click(
177
+ fn=clear_voice_input,
178
+ inputs=[],
179
+ outputs=[voice_input]
180
+ )
181
+
182
+ analyze_btn.click(
183
+ fn=analyze_voice,
184
  inputs=[voice_input, state],
185
+ outputs=[state, transcribed_text, voice_emotion, text_emotion, final_prompt]
186
+ )
187
+
188
+ generate_btn.click(
189
+ fn=generate_image,
190
+ inputs=[final_prompt, state],
191
+ outputs=[gallery]
192
  )
193
 
194
  return app
195
 
 
196
  if __name__ == "__main__":
197
  demo = create_interface()
198
  demo.launch()