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)
|