From 9f15f4f6e526ed4ce0e4f3e5e15af3768183b0e4 Mon Sep 17 00:00:00 2001 From: Minseo-Jo Date: Wed, 22 Oct 2025 15:24:08 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B3=91=ED=95=A9=20=EC=99=84=EB=A3=8C:=20?= =?UTF-8?q?=EC=9B=90=EA=B2=A9=20=EC=A0=80=EC=9E=A5=EC=86=8C=20=EC=B5=9C?= =?UTF-8?q?=EC=8B=A0=20=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 회의시작및실시간회의록작성.puml 병합 완료 - .gitignore 업데이트 - stt-ai 디렉토리 추가 - requirements.txt, .env.example 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .claude/settings.local.json | 5 +- .env.example | 12 ++ .gitignore | 1 + .../outer/회의시작및실시간회의록작성.puml | 97 +++---------- requirements.txt | 5 + stt-ai/tests/stt_test.py | 136 ++++++++++++++++++ 6 files changed, 176 insertions(+), 80 deletions(-) create mode 100644 .env.example create mode 100644 requirements.txt create mode 100644 stt-ai/tests/stt_test.py diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 20bae11..20b958c 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -35,9 +35,10 @@ "Bash(./tools/check-mermaid.sh:*)", "Bash(mv:*)", "Bash(cp:*)", - "mcp__sequential-thinking__sequentialthinking" + "mcp__sequential-thinking__sequentialthinking", + "Bash(git checkout:*)" ], "deny": [], "ask": [] } -} \ No newline at end of file +} diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d6b39f0 --- /dev/null +++ b/.env.example @@ -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 + + diff --git a/.gitignore b/.gitignore index 5f8b57a..a887e50 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .playwright-mcp/ .DS_Store **/.DS_Store +.env diff --git a/design/backend/sequence/outer/회의시작및실시간회의록작성.puml b/design/backend/sequence/outer/회의시작및실시간회의록작성.puml index a413089..d4bcbf2 100644 --- a/design/backend/sequence/outer/회의시작및실시간회의록작성.puml +++ b/design/backend/sequence/outer/회의시작및실시간회의록작성.puml @@ -1,4 +1,4 @@ -@startuml 회의시작및실시간회의록작성 +@startuml !theme mono title 회의시작및실시간회의록작성 외부 시퀀스 @@ -23,33 +23,18 @@ activate Gateway Gateway -> Meeting: POST /meetings/{meetingId}/start activate Meeting -' 회의 세션 생성 -Meeting -> Meeting: 회의 세션 생성\n- 회의 상태 업데이트 (시작중)\n- 시작 시간 기록\n- 회의 통계 초기화 +Meeting -> Meeting: 회의 세션 생성 -' MeetingStarted 이벤트 발행 Meeting -> EventHub: MeetingStarted 이벤트 발행 activate EventHub -note right - 이벤트 데이터: - - meetingId - - title - - startTime - - participants -end note Meeting --> Gateway: 201 Created -note right - 응답 데이터: - - meetingId - - sessionId - - status: IN_PROGRESS -end note deactivate Meeting -Gateway --> Frontend: 201 Created (회의 세션 정보) +Gateway --> Frontend: 201 Created deactivate Gateway -Frontend -> Frontend: 회의 화면으로 전환\n- 음성 녹음 UI 표시\n- 참석자 목록 표시\n- 회의록 편집 영역 활성화 +Frontend -> Frontend: 회의 화면으로 전환 Frontend --> User: 회의 진행 화면 표시 deactivate Frontend @@ -59,7 +44,7 @@ deactivate Frontend EventHub -> STT: MeetingStarted 이벤트 구독 activate STT -STT -> STT: 음성 녹음 준비\n- 녹음 세션 생성\n- 오디오 스트림 초기화\n- Azure Speech 연동 준비 +STT -> STT: 음성 녹음 준비 STT --> EventHub: 녹음 준비 완료 deactivate STT @@ -75,21 +60,10 @@ activate Frontend Frontend -> STT: 음성 데이터 스트리밍 activate STT -' 음성-텍스트 변환 -STT -> STT: 음성 인식 처리\n- 화자 식별\n- Azure Speech API 호출\n- 텍스트 변환\n- 타임스탬프 기록 +STT -> STT: 음성 인식 처리 -' TranscriptReady 이벤트 발행 (5초 배치) -STT -> EventHub: TranscriptReady 이벤트 발행 (5초 배치) +STT -> EventHub: TranscriptReady 이벤트 발행 activate EventHub -note right - 이벤트 데이터: - - meetingId - - segments: - * speaker - * text - * timestamp - * confidence -end note STT --> Frontend: 음성 처리 중 표시 deactivate STT @@ -100,64 +74,37 @@ deactivate Frontend EventHub -> AI: TranscriptReady 이벤트 구독 activate AI -par AI 병렬 처리 - AI -> AI: [1] 회의록 내용 정리 (LLM)\n- 구어체 → 문어체 변환\n- 주제별 분류\n- 핵심 내용 요약\n- 문장 다듬기 -and - AI -> AI: [2] 전문용어 추출 (RAG)\n- 전문용어 자동 감지\n- 벡터 임베딩\n- 유사도 검색\n- 맥락 기반 설명 생성 -and - AI -> AI: [3] 관련 자료 검색\n- 과거 회의록 검색\n- 사내 문서 검색\n- 관련도 계산\n- 상위 5개 선정 -end +AI -> AI: [1] 회의록 내용 정리 (LLM) +AI -> AI: [2] 전문용어 추출 (RAG) +AI -> AI: [3] 관련 자료 검색 -' AI 분석 결과 저장 -AI -> AI: AI 분석 결과 저장\n- TranscriptSummary 생성\n- TermExplanation 저장\n- 관련 문서 링크 저장 +AI -> AI: AI 분석 결과 저장 -' TranscriptSummaryCreated 이벤트 발행 -AI -> EventHub: TranscriptSummaryCreated 이벤트 발행 -note right - 이벤트 데이터: - - meetingId - - summary - - terms - - relatedDocs - - timestamp -end note +AI -> EventHub: TranscriptSummaryCreated 발행 AI --> EventHub: AI 분석 완료 deactivate AI -deactivate EventHub == 회의록 저장 및 실시간 동기화 == -EventHub -> Meeting: TranscriptSummaryCreated 이벤트 구독 -activate EventHub +EventHub -> Meeting: TranscriptSummaryCreated 구독 activate Meeting -' 회의록 데이터 저장 -Meeting -> Meeting: 회의록 데이터 저장\n- Transcript 엔티티 업데이트\n- 버전 증가\n- 수정 이력 기록 +Meeting -> Meeting: 회의록 데이터 저장 -' 캐시 무효화 -Meeting --> Cache: DEL meeting:info:{meetingId} +Meeting -> Cache: 캐시 무효화 activate Cache Cache --> Meeting: 캐시 삭제 완료 deactivate Cache -' 실시간 동기화 (WebSocket) Meeting -> Frontend: WebSocket 메시지 전송 activate Frontend -note right - 메시지 데이터: - - type: TRANSCRIPT_UPDATE - - summary - - terms - - relatedDocs - - delta -end note Meeting --> EventHub: 동기화 완료 deactivate Meeting deactivate EventHub -Frontend -> Frontend: 회의록 화면 업데이트\n- 정리된 회의록 표시\n- 전문용어 하이라이트\n- 관련 자료 링크 표시\n- 수정자 표시 (3초간) +Frontend -> Frontend: 회의록 화면 업데이트 Frontend --> User: 실시간 회의록 표시 deactivate Frontend @@ -165,16 +112,10 @@ deactivate Frontend end note over User, EventHub -**처리 시간**: +처리 시간: - STT 변환: 1-3초 - AI 병렬 처리: 5-8초 -- 회의록 저장 및 동기화: 1-2초 -- 총 처리 시간: 7-13초 (5초 배치 기준) - -**차별화 포인트**: -- AI 병렬 처리로 회의록 정리, 전문용어 설명, 관련 자료 검색을 동시에 수행 -- 정리된 회의록과 맥락 기반 용어 설명을 통합 제공 -- WebSocket 델타 전송으로 네트워크 효율성 향상 +- 회의록 저장: 1-2초 +- 총 처리 시간: 7-13초 end note - @enduml diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b18bd09 --- /dev/null +++ b/requirements.txt @@ -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 + + + diff --git a/stt-ai/tests/stt_test.py b/stt-ai/tests/stt_test.py new file mode 100644 index 0000000..b249aa6 --- /dev/null +++ b/stt-ai/tests/stt_test.py @@ -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) \ No newline at end of file