Update app.py
Browse files
app.py
CHANGED
@@ -250,59 +250,63 @@ def analyze_voice(audio_data, state):
|
|
250 |
return state, "음성을 먼저 녹음해주세요.", "", "", ""
|
251 |
|
252 |
try:
|
253 |
-
|
254 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
return state, "음성 분석에 실패했습니다.", "", "", ""
|
256 |
|
257 |
-
#
|
258 |
-
voice_emotion = map_acoustic_to_emotion(
|
259 |
-
features,
|
260 |
-
state.get("baseline_features") # 기준점 전달
|
261 |
-
)
|
262 |
-
|
263 |
-
# 음성 인식 (필요한 경우)
|
264 |
-
text = "음성이 인식되었습니다."
|
265 |
if speech_recognizer:
|
266 |
try:
|
267 |
-
sr, y = audio_data
|
268 |
transcription = speech_recognizer({"sampling_rate": sr, "raw": y.astype(np.float32)})
|
269 |
text = transcription["text"]
|
270 |
except Exception as e:
|
271 |
print(f"Speech recognition error: {e}")
|
272 |
-
text = "음성
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
296 |
|
297 |
# 프롬프트 생성
|
298 |
-
prompt = generate_detailed_prompt(text, voice_emotion,
|
299 |
state = {**state, "final_prompt": prompt}
|
300 |
|
301 |
-
return state, text, voice_result,
|
302 |
|
303 |
except Exception as e:
|
304 |
print(f"Error in analyze_voice: {str(e)}")
|
305 |
-
return state, f"
|
306 |
|
307 |
|
308 |
def generate_detailed_prompt(text, emotions, text_sentiment):
|
@@ -649,77 +653,14 @@ def create_interface():
|
|
649 |
with blessing_section:
|
650 |
gr.Markdown("### 축원의식을 시작하겠습니다")
|
651 |
gr.Markdown("'명짐 복짐 짊어지고 안가태평하시기를 비도발원 축원 드립니다'")
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
set_baseline_btn = gr.Button("축원 마치기", variant="primary")
|
661 |
-
|
662 |
-
# 분석 결과 표시 영역
|
663 |
-
baseline_status = gr.Markdown("") # 상태 메시지
|
664 |
-
analysis_results = gr.Markdown(visible=False) # 분석 결과
|
665 |
-
|
666 |
-
def handle_blessing_complete(audio, state):
|
667 |
-
"""축원 완료 및 기준점 설정 핸들러"""
|
668 |
-
if audio is None:
|
669 |
-
return (
|
670 |
-
state,
|
671 |
-
"음성을 먼저 녹음해주세요.",
|
672 |
-
gr.update(visible=True),
|
673 |
-
gr.update(visible=False)
|
674 |
-
)
|
675 |
-
|
676 |
-
try:
|
677 |
-
# 기준점 설정을 위한 음성 분석
|
678 |
-
features = calculate_baseline_features(audio)
|
679 |
-
if features is None:
|
680 |
-
return (
|
681 |
-
state,
|
682 |
-
"음성 분석에 실패했습니다. 다시 시도해주세요.",
|
683 |
-
gr.update(visible=True),
|
684 |
-
gr.update(visible=False)
|
685 |
-
)
|
686 |
-
|
687 |
-
# 기본 감정 상태 분석
|
688 |
-
baseline_emotion = map_acoustic_to_emotion(features)
|
689 |
-
|
690 |
-
# 상태 업데이트
|
691 |
-
new_state = safe_state_update(state, {
|
692 |
-
"baseline_features": features,
|
693 |
-
"baseline_emotion": baseline_emotion
|
694 |
-
})
|
695 |
-
|
696 |
-
# 분석 결과 표시
|
697 |
-
result_text = f"""
|
698 |
-
✨ 축원이 완료되었습니다.
|
699 |
-
|
700 |
-
🎭 기본 감정 상태:
|
701 |
-
• 주요 감정: {baseline_emotion['primary']}
|
702 |
-
• 감정 강도: {baseline_emotion['intensity']:.1f}%
|
703 |
-
• 특징: {', '.join(baseline_emotion['characteristics'])}
|
704 |
-
|
705 |
-
다음 단계로 진행해주세요.
|
706 |
-
"""
|
707 |
-
|
708 |
-
return (
|
709 |
-
new_state,
|
710 |
-
result_text,
|
711 |
-
gr.update(visible=False),
|
712 |
-
gr.update(visible=True)
|
713 |
-
)
|
714 |
-
|
715 |
-
except Exception as e:
|
716 |
-
print(f"Error in handle_blessing_complete: {str(e)}")
|
717 |
-
return (
|
718 |
-
state,
|
719 |
-
f"오류가 발생했습니다. 다시 시도해주세요.",
|
720 |
-
gr.update(visible=True),
|
721 |
-
gr.update(visible=False)
|
722 |
-
)
|
723 |
|
724 |
# 4단계: 굿판 입장 안내
|
725 |
entry_guide_section = gr.Column(visible=False)
|
|
|
250 |
return state, "음성을 먼저 녹음해주세요.", "", "", ""
|
251 |
|
252 |
try:
|
253 |
+
sr, y = audio_data
|
254 |
+
y = y.astype(np.float32)
|
255 |
+
|
256 |
+
if len(y) == 0:
|
257 |
+
return state, "음성이 감지되지 않았습니다.", "", "", ""
|
258 |
+
|
259 |
+
acoustic_features = calculate_baseline_features((sr, y))
|
260 |
+
if acoustic_features is None:
|
261 |
return state, "음성 분석에 실패했습니다.", "", "", ""
|
262 |
|
263 |
+
# 음성 인식
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
if speech_recognizer:
|
265 |
try:
|
|
|
266 |
transcription = speech_recognizer({"sampling_rate": sr, "raw": y.astype(np.float32)})
|
267 |
text = transcription["text"]
|
268 |
except Exception as e:
|
269 |
print(f"Speech recognition error: {e}")
|
270 |
+
text = "음성 인식 실패"
|
271 |
+
else:
|
272 |
+
text = "음성 인식 모델을 불러올 수 없습니다."
|
273 |
+
|
274 |
+
# 음성 감정 분석
|
275 |
+
voice_emotion = map_acoustic_to_emotion(acoustic_features, state.get("baseline_features"))
|
276 |
+
|
277 |
+
# 텍스트 감정 분석
|
278 |
+
if text_analyzer and text:
|
279 |
+
try:
|
280 |
+
text_sentiment = text_analyzer(text)[0]
|
281 |
+
text_result = f"텍스트 감정 분석: {text_sentiment['label']} (점수: {text_sentiment['score']:.2f})"
|
282 |
+
except Exception as e:
|
283 |
+
print(f"Text analysis error: {e}")
|
284 |
+
text_sentiment = {"label": "unknown", "score": 0.0}
|
285 |
+
text_result = "텍스트 감정 분석 실패"
|
286 |
+
else:
|
287 |
+
text_sentiment = {"label": "unknown", "score": 0.0}
|
288 |
+
text_result = "텍스트 감정 분석을 수행할 수 없습니다."
|
289 |
+
|
290 |
+
voice_result = (
|
291 |
+
f"음성 감정: {voice_emotion['primary']} "
|
292 |
+
f"(강도: {voice_emotion['intensity']:.1f}%, 신뢰도: {voice_emotion['confidence']:.2f})\n"
|
293 |
+
f"특징: {', '.join(voice_emotion['characteristics'])}\n"
|
294 |
+
f"상세 분석:\n"
|
295 |
+
f"- 에너지 레벨: {voice_emotion['details']['energy_level']}\n"
|
296 |
+
f"- 말하기 속도: {voice_emotion['details']['speech_rate']}\n"
|
297 |
+
f"- 음높이 변화: {voice_emotion['details']['pitch_variation']}\n"
|
298 |
+
f"- 음성 크기: {voice_emotion['details']['voice_volume']}"
|
299 |
+
)
|
300 |
|
301 |
# 프롬프트 생성
|
302 |
+
prompt = generate_detailed_prompt(text, voice_emotion, text_sentiment)
|
303 |
state = {**state, "final_prompt": prompt}
|
304 |
|
305 |
+
return state, text, voice_result, text_result, prompt
|
306 |
|
307 |
except Exception as e:
|
308 |
print(f"Error in analyze_voice: {str(e)}")
|
309 |
+
return state, f"오류 발생: {str(e)}", "", "", ""
|
310 |
|
311 |
|
312 |
def generate_detailed_prompt(text, emotions, text_sentiment):
|
|
|
653 |
with blessing_section:
|
654 |
gr.Markdown("### 축원의식을 시작하겠습니다")
|
655 |
gr.Markdown("'명짐 복짐 짊어지고 안가태평하시기를 비도발원 축원 드립니다'")
|
656 |
+
baseline_audio = gr.Audio(
|
657 |
+
label="축원 문장 녹음하기",
|
658 |
+
sources=["microphone"],
|
659 |
+
type="numpy",
|
660 |
+
streaming=False
|
661 |
+
)
|
662 |
+
set_baseline_btn = gr.Button("축원 마치기", variant="primary")
|
663 |
+
baseline_status = gr.Markdown("")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
664 |
|
665 |
# 4단계: 굿판 입장 안내
|
666 |
entry_guide_section = gr.Column(visible=False)
|