mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 07:56:24 +00:00
병합 완료: 원격 저장소 최신 변경사항 반영
- 회의시작및실시간회의록작성.puml 병합 완료 - .gitignore 업데이트 - stt-ai 디렉토리 추가 - requirements.txt, .env.example 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b05f7b2f22
commit
9f15f4f6e5
@ -35,9 +35,10 @@
|
|||||||
"Bash(./tools/check-mermaid.sh:*)",
|
"Bash(./tools/check-mermaid.sh:*)",
|
||||||
"Bash(mv:*)",
|
"Bash(mv:*)",
|
||||||
"Bash(cp:*)",
|
"Bash(cp:*)",
|
||||||
"mcp__sequential-thinking__sequentialthinking"
|
"mcp__sequential-thinking__sequentialthinking",
|
||||||
|
"Bash(git checkout:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
.env.example
Normal file
12
.env.example
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Azure Speech Service 설정
|
||||||
|
AZURE_SPEECH_KEY=your_azure_speech_key_here
|
||||||
|
AZURE_SPEECH_REGION=region_here
|
||||||
|
|
||||||
|
# OpenAI API (회의록 생성용)
|
||||||
|
OPENAI_API_KEY=your_openai_api_key_here
|
||||||
|
|
||||||
|
# 개발 환경 설정
|
||||||
|
ENVIRONMENT=development
|
||||||
|
DEBUG=true
|
||||||
|
|
||||||
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
.playwright-mcp/
|
.playwright-mcp/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
|
.env
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
@startuml 회의시작및실시간회의록작성
|
@startuml
|
||||||
!theme mono
|
!theme mono
|
||||||
|
|
||||||
title 회의시작및실시간회의록작성 외부 시퀀스
|
title 회의시작및실시간회의록작성 외부 시퀀스
|
||||||
@ -23,33 +23,18 @@ activate Gateway
|
|||||||
Gateway -> Meeting: POST /meetings/{meetingId}/start
|
Gateway -> Meeting: POST /meetings/{meetingId}/start
|
||||||
activate Meeting
|
activate Meeting
|
||||||
|
|
||||||
' 회의 세션 생성
|
Meeting -> Meeting: 회의 세션 생성
|
||||||
Meeting -> Meeting: 회의 세션 생성\n- 회의 상태 업데이트 (시작중)\n- 시작 시간 기록\n- 회의 통계 초기화
|
|
||||||
|
|
||||||
' MeetingStarted 이벤트 발행
|
|
||||||
Meeting -> EventHub: MeetingStarted 이벤트 발행
|
Meeting -> EventHub: MeetingStarted 이벤트 발행
|
||||||
activate EventHub
|
activate EventHub
|
||||||
note right
|
|
||||||
이벤트 데이터:
|
|
||||||
- meetingId
|
|
||||||
- title
|
|
||||||
- startTime
|
|
||||||
- participants
|
|
||||||
end note
|
|
||||||
|
|
||||||
Meeting --> Gateway: 201 Created
|
Meeting --> Gateway: 201 Created
|
||||||
note right
|
|
||||||
응답 데이터:
|
|
||||||
- meetingId
|
|
||||||
- sessionId
|
|
||||||
- status: IN_PROGRESS
|
|
||||||
end note
|
|
||||||
deactivate Meeting
|
deactivate Meeting
|
||||||
|
|
||||||
Gateway --> Frontend: 201 Created (회의 세션 정보)
|
Gateway --> Frontend: 201 Created
|
||||||
deactivate Gateway
|
deactivate Gateway
|
||||||
|
|
||||||
Frontend -> Frontend: 회의 화면으로 전환\n- 음성 녹음 UI 표시\n- 참석자 목록 표시\n- 회의록 편집 영역 활성화
|
Frontend -> Frontend: 회의 화면으로 전환
|
||||||
|
|
||||||
Frontend --> User: 회의 진행 화면 표시
|
Frontend --> User: 회의 진행 화면 표시
|
||||||
deactivate Frontend
|
deactivate Frontend
|
||||||
@ -59,7 +44,7 @@ deactivate Frontend
|
|||||||
EventHub -> STT: MeetingStarted 이벤트 구독
|
EventHub -> STT: MeetingStarted 이벤트 구독
|
||||||
activate STT
|
activate STT
|
||||||
|
|
||||||
STT -> STT: 음성 녹음 준비\n- 녹음 세션 생성\n- 오디오 스트림 초기화\n- Azure Speech 연동 준비
|
STT -> STT: 음성 녹음 준비
|
||||||
|
|
||||||
STT --> EventHub: 녹음 준비 완료
|
STT --> EventHub: 녹음 준비 완료
|
||||||
deactivate STT
|
deactivate STT
|
||||||
@ -75,21 +60,10 @@ activate Frontend
|
|||||||
Frontend -> STT: 음성 데이터 스트리밍
|
Frontend -> STT: 음성 데이터 스트리밍
|
||||||
activate STT
|
activate STT
|
||||||
|
|
||||||
' 음성-텍스트 변환
|
STT -> STT: 음성 인식 처리
|
||||||
STT -> STT: 음성 인식 처리\n- 화자 식별\n- Azure Speech API 호출\n- 텍스트 변환\n- 타임스탬프 기록
|
|
||||||
|
|
||||||
' TranscriptReady 이벤트 발행 (5초 배치)
|
STT -> EventHub: TranscriptReady 이벤트 발행
|
||||||
STT -> EventHub: TranscriptReady 이벤트 발행 (5초 배치)
|
|
||||||
activate EventHub
|
activate EventHub
|
||||||
note right
|
|
||||||
이벤트 데이터:
|
|
||||||
- meetingId
|
|
||||||
- segments:
|
|
||||||
* speaker
|
|
||||||
* text
|
|
||||||
* timestamp
|
|
||||||
* confidence
|
|
||||||
end note
|
|
||||||
|
|
||||||
STT --> Frontend: 음성 처리 중 표시
|
STT --> Frontend: 음성 처리 중 표시
|
||||||
deactivate STT
|
deactivate STT
|
||||||
@ -100,64 +74,37 @@ deactivate Frontend
|
|||||||
EventHub -> AI: TranscriptReady 이벤트 구독
|
EventHub -> AI: TranscriptReady 이벤트 구독
|
||||||
activate AI
|
activate AI
|
||||||
|
|
||||||
par AI 병렬 처리
|
AI -> AI: [1] 회의록 내용 정리 (LLM)
|
||||||
AI -> AI: [1] 회의록 내용 정리 (LLM)\n- 구어체 → 문어체 변환\n- 주제별 분류\n- 핵심 내용 요약\n- 문장 다듬기
|
AI -> AI: [2] 전문용어 추출 (RAG)
|
||||||
and
|
AI -> AI: [3] 관련 자료 검색
|
||||||
AI -> AI: [2] 전문용어 추출 (RAG)\n- 전문용어 자동 감지\n- 벡터 임베딩\n- 유사도 검색\n- 맥락 기반 설명 생성
|
|
||||||
and
|
|
||||||
AI -> AI: [3] 관련 자료 검색\n- 과거 회의록 검색\n- 사내 문서 검색\n- 관련도 계산\n- 상위 5개 선정
|
|
||||||
end
|
|
||||||
|
|
||||||
' AI 분석 결과 저장
|
AI -> AI: AI 분석 결과 저장
|
||||||
AI -> AI: AI 분석 결과 저장\n- TranscriptSummary 생성\n- TermExplanation 저장\n- 관련 문서 링크 저장
|
|
||||||
|
|
||||||
' TranscriptSummaryCreated 이벤트 발행
|
AI -> EventHub: TranscriptSummaryCreated 발행
|
||||||
AI -> EventHub: TranscriptSummaryCreated 이벤트 발행
|
|
||||||
note right
|
|
||||||
이벤트 데이터:
|
|
||||||
- meetingId
|
|
||||||
- summary
|
|
||||||
- terms
|
|
||||||
- relatedDocs
|
|
||||||
- timestamp
|
|
||||||
end note
|
|
||||||
|
|
||||||
AI --> EventHub: AI 분석 완료
|
AI --> EventHub: AI 분석 완료
|
||||||
deactivate AI
|
deactivate AI
|
||||||
deactivate EventHub
|
|
||||||
|
|
||||||
== 회의록 저장 및 실시간 동기화 ==
|
== 회의록 저장 및 실시간 동기화 ==
|
||||||
|
|
||||||
EventHub -> Meeting: TranscriptSummaryCreated 이벤트 구독
|
EventHub -> Meeting: TranscriptSummaryCreated 구독
|
||||||
activate EventHub
|
|
||||||
activate Meeting
|
activate Meeting
|
||||||
|
|
||||||
' 회의록 데이터 저장
|
Meeting -> Meeting: 회의록 데이터 저장
|
||||||
Meeting -> Meeting: 회의록 데이터 저장\n- Transcript 엔티티 업데이트\n- 버전 증가\n- 수정 이력 기록
|
|
||||||
|
|
||||||
' 캐시 무효화
|
Meeting -> Cache: 캐시 무효화
|
||||||
Meeting --> Cache: DEL meeting:info:{meetingId}
|
|
||||||
activate Cache
|
activate Cache
|
||||||
Cache --> Meeting: 캐시 삭제 완료
|
Cache --> Meeting: 캐시 삭제 완료
|
||||||
deactivate Cache
|
deactivate Cache
|
||||||
|
|
||||||
' 실시간 동기화 (WebSocket)
|
|
||||||
Meeting -> Frontend: WebSocket 메시지 전송
|
Meeting -> Frontend: WebSocket 메시지 전송
|
||||||
activate Frontend
|
activate Frontend
|
||||||
note right
|
|
||||||
메시지 데이터:
|
|
||||||
- type: TRANSCRIPT_UPDATE
|
|
||||||
- summary
|
|
||||||
- terms
|
|
||||||
- relatedDocs
|
|
||||||
- delta
|
|
||||||
end note
|
|
||||||
|
|
||||||
Meeting --> EventHub: 동기화 완료
|
Meeting --> EventHub: 동기화 완료
|
||||||
deactivate Meeting
|
deactivate Meeting
|
||||||
deactivate EventHub
|
deactivate EventHub
|
||||||
|
|
||||||
Frontend -> Frontend: 회의록 화면 업데이트\n- 정리된 회의록 표시\n- 전문용어 하이라이트\n- 관련 자료 링크 표시\n- 수정자 표시 (3초간)
|
Frontend -> Frontend: 회의록 화면 업데이트
|
||||||
|
|
||||||
Frontend --> User: 실시간 회의록 표시
|
Frontend --> User: 실시간 회의록 표시
|
||||||
deactivate Frontend
|
deactivate Frontend
|
||||||
@ -165,16 +112,10 @@ deactivate Frontend
|
|||||||
end
|
end
|
||||||
|
|
||||||
note over User, EventHub
|
note over User, EventHub
|
||||||
**처리 시간**:
|
처리 시간:
|
||||||
- STT 변환: 1-3초
|
- STT 변환: 1-3초
|
||||||
- AI 병렬 처리: 5-8초
|
- AI 병렬 처리: 5-8초
|
||||||
- 회의록 저장 및 동기화: 1-2초
|
- 회의록 저장: 1-2초
|
||||||
- 총 처리 시간: 7-13초 (5초 배치 기준)
|
- 총 처리 시간: 7-13초
|
||||||
|
|
||||||
**차별화 포인트**:
|
|
||||||
- AI 병렬 처리로 회의록 정리, 전문용어 설명, 관련 자료 검색을 동시에 수행
|
|
||||||
- 정리된 회의록과 맥락 기반 용어 설명을 통합 제공
|
|
||||||
- WebSocket 델타 전송으로 네트워크 효율성 향상
|
|
||||||
end note
|
end note
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|||||||
5
requirements.txt
Normal file
5
requirements.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
azure-cognitiveservices-speech==1.34.0 # Azure Speech SDK for Python
|
||||||
|
python-dotenv==1.0.0 # For loading environment variables from .env file
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
136
stt-ai/tests/stt_test.py
Normal file
136
stt-ai/tests/stt_test.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
"""
|
||||||
|
Azure Speech SDK 연결 테스트
|
||||||
|
- 마이크 입력을 받아 실시간 STT 수행
|
||||||
|
- 화자 식별 기능 테스트
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import azure.cognitiveservices.speech as speechsdk
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# .env 파일 로드
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
def test_azure_speech_connection():
|
||||||
|
"""Azure Speech 서비스 연결 테스트"""
|
||||||
|
|
||||||
|
# 환경변수에서 키 읽기
|
||||||
|
speech_key = os.getenv("AZURE_SPEECH_KEY")
|
||||||
|
speech_region = os.getenv("AZURE_SPEECH_REGION")
|
||||||
|
|
||||||
|
if not speech_key or not speech_region:
|
||||||
|
print("❌ 환경변수가 설정되지 않았습니다!")
|
||||||
|
print(" .env 파일에 AZURE_SPEECH_KEY와 AZURE_SPEECH_REGION을 설정하세요.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print(f"🔑 Azure Speech Key: {speech_key[:10]}...")
|
||||||
|
print(f"🌍 Region: {speech_region}")
|
||||||
|
|
||||||
|
# Speech Config 생성
|
||||||
|
speech_config = speechsdk.SpeechConfig(
|
||||||
|
subscription=speech_key,
|
||||||
|
region=speech_region
|
||||||
|
)
|
||||||
|
speech_config.speech_recognition_language = "ko-KR"
|
||||||
|
|
||||||
|
# 오디오 설정 (마이크)
|
||||||
|
audio_config = speechsdk.audio.AudioConfig(use_default_microphone=True)
|
||||||
|
|
||||||
|
# Recognizer 생성
|
||||||
|
recognizer = speechsdk.SpeechRecognizer(
|
||||||
|
speech_config=speech_config,
|
||||||
|
audio_config=audio_config
|
||||||
|
)
|
||||||
|
|
||||||
|
print("\n🎤 마이크에 대고 말씀하세요 (한국어)...")
|
||||||
|
print(" (음성 인식이 시작됩니다)\n")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 한 번의 음성 인식 수행
|
||||||
|
result = recognizer.recognize_once()
|
||||||
|
|
||||||
|
if result.reason == speechsdk.ResultReason.RecognizedSpeech:
|
||||||
|
print(f"✅ 인식 성공!")
|
||||||
|
print(f"📝 텍스트: {result.text}")
|
||||||
|
return True
|
||||||
|
elif result.reason == speechsdk.ResultReason.NoMatch:
|
||||||
|
print(f"⚠️ 음성을 인식하지 못했습니다.")
|
||||||
|
print(f" 세부정보: {result.no_match_details}")
|
||||||
|
return False
|
||||||
|
elif result.reason == speechsdk.ResultReason.Canceled:
|
||||||
|
cancellation = result.cancellation_details
|
||||||
|
print(f"❌ 인식 취소됨: {cancellation.reason}")
|
||||||
|
if cancellation.reason == speechsdk.CancellationReason.Error:
|
||||||
|
print(f" 에러 코드: {cancellation.error_code}")
|
||||||
|
print(f" 에러 메시지: {cancellation.error_details}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 예외 발생: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def test_continuous_recognition():
|
||||||
|
"""연속 음성 인식 테스트 (실시간 스트리밍)"""
|
||||||
|
|
||||||
|
speech_key = os.getenv("AZURE_SPEECH_KEY")
|
||||||
|
speech_region = os.getenv("AZURE_SPEECH_REGION")
|
||||||
|
|
||||||
|
speech_config = speechsdk.SpeechConfig(
|
||||||
|
subscription=speech_key,
|
||||||
|
region=speech_region
|
||||||
|
)
|
||||||
|
speech_config.speech_recognition_language = "ko-KR"
|
||||||
|
|
||||||
|
audio_config = speechsdk.audio.AudioConfig(use_default_microphone=True)
|
||||||
|
recognizer = speechsdk.SpeechRecognizer(
|
||||||
|
speech_config=speech_config,
|
||||||
|
audio_config=audio_config
|
||||||
|
)
|
||||||
|
|
||||||
|
print("\n🔄 연속 음성 인식 테스트 시작...")
|
||||||
|
print(" (Ctrl+C로 종료하세요)\n")
|
||||||
|
|
||||||
|
# 이벤트 핸들러
|
||||||
|
def recognized_handler(evt):
|
||||||
|
if evt.result.reason == speechsdk.ResultReason.RecognizedSpeech:
|
||||||
|
print(f"✅ [{evt.result.offset/10000000:.1f}s] {evt.result.text}")
|
||||||
|
|
||||||
|
def canceled_handler(evt):
|
||||||
|
print(f"❌ 취소됨: {evt}")
|
||||||
|
|
||||||
|
# 이벤트 연결
|
||||||
|
recognizer.recognized.connect(recognized_handler)
|
||||||
|
recognizer.canceled.connect(canceled_handler)
|
||||||
|
|
||||||
|
# 연속 인식 시작
|
||||||
|
recognizer.start_continuous_recognition()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 사용자가 종료할 때까지 대기
|
||||||
|
input("Press Enter to stop...\n")
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n⏹️ 인식 중지 중...")
|
||||||
|
finally:
|
||||||
|
recognizer.stop_continuous_recognition()
|
||||||
|
print("✅ 연속 인식 종료")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("=" * 60)
|
||||||
|
print("🎤 Azure Speech SDK 연결 테스트")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# 1. 기본 연결 테스트
|
||||||
|
print("\n[테스트 1] 기본 음성 인식")
|
||||||
|
success = test_azure_speech_connection()
|
||||||
|
|
||||||
|
if success:
|
||||||
|
# 2. 연속 인식 테스트
|
||||||
|
response = input("\n연속 인식 테스트를 진행하시겠습니까? (y/n): ")
|
||||||
|
if response.lower() == 'y':
|
||||||
|
test_continuous_recognition()
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("테스트 완료!")
|
||||||
|
print("=" * 60)
|
||||||
Loading…
x
Reference in New Issue
Block a user