mirror of
https://github.com/nad4-su/meeting-minutes.git
synced 2026-10-11 15:50:13 +09:00
46분 대면 회의 실측에서 Web Speech 포착률이 7~10%에 그쳤다(489어절 / 분당 10.6어절, 30초 이상 공백 26곳 26분 29초). 빈 텍스트 청크 19개는 Chrome이 `isFinal: true`에 `transcript: ""`를 준 것으로, 소리는 감지했으나 인식에 실패했다는 신호다. 지금까지는 오디오를 어디에도 남기지 않아 놓친 발화를 복구할 수도, 얼마나 놓쳤는지 잴 수도 없었다. 전사와 독립적으로 원음을 파일로 남긴다. ## 유실 방지 설계 메모리에 모았다가 종료 시 한 번에 쓰지 않는다. 그러면 탭이나 서버가 죽는 순간 회의 전체가 사라진다. 15초 조각마다 디스크에 append 하므로 어느 시점에 중단되든 그때까지의 오디오는 남는다. - 서버 업로드가 실패해도 녹음을 멈추지 않고 브라우저 사본으로 회수한다 - 조각이 3회 재시도 후에도 실패하면 뒤를 이어 붙이지 않고 멈춘다. 중간이 빈 파일은 짧은 파일보다 나쁘다 — 재생도 전사도 안 된다 - 한 조각도 못 받았으면 "보관됨"이라고 하지 않고 오류를 띄운다 - 서버 사본이 로컬보다 짧으면 경고한다 ## 캡처 제약 변경 `noiseSuppression: false, echoCancellation: false, autoGainControl: true`. 브라우저 기본값은 전화 통화용 튜닝이라 멀리 앉은 화자를 노이즈로 지운다. AGC는 조용한 화자를 끌어올려 주므로 남긴다. 실측으로 검증할 가설이며 회귀 방지 테스트를 걸어 뒀다. ## 검증 - 서버 파이프라인: 184조각 755KB 업로드 → 다운로드 SHA256 바이트 일치 - 클라이언트 전 경로: 합성 스트림으로 48초 녹음 → 로컬·서버 크기 일치, 서버 파일이 decodeAudioData로 48.12초 실제 오디오로 디코딩됨 - 경로 조작 400 / 없는 세션 404 / 빈 조각 400 / 미허용 mimeType 400 - 테스트 162 → 206 통과, 신규 타입 에러 0, 린트 baseline과 동일 실제 마이크 경로는 테스트하지 못했다. Web Speech와 getUserMedia가 같은 마이크를 두고 경합하는지 실사용 확인이 필요하다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzAH7GPWSYTe2AoBV6CZDP
64 lines
3.3 KiB
Bash
64 lines
3.3 KiB
Bash
# =============================================================================
|
|
# Meeting Minutes — 환경 변수
|
|
#
|
|
# 사용법:
|
|
# 1. 이 파일을 .env로 복사: cp .env.example .env
|
|
# 2. 아래 값들을 직접 채워주세요. 빈 값으로 두면 docker compose가 실패합니다.
|
|
#
|
|
# 강력한 비밀번호 생성 (macOS / Linux):
|
|
# openssl rand -base64 24
|
|
# =============================================================================
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 필수 — PostgreSQL
|
|
# -----------------------------------------------------------------------------
|
|
POSTGRES_USER=meetinguser
|
|
POSTGRES_DB=meetingminutes
|
|
|
|
# ⚠️ 강력한 임의 값으로 채우세요 (예: openssl rand -base64 24)
|
|
# 이 비밀번호는 docker compose가 첫 기동 시 사용하며, 이후 변경하려면
|
|
# `docker compose down -v`로 볼륨을 삭제하거나 ALTER USER로 갱신해야 합니다.
|
|
POSTGRES_PASSWORD=
|
|
|
|
# 위 USER/PASSWORD/DB와 일치해야 합니다.
|
|
# 로컬 개발(npm run dev) 시에는 host=localhost, Docker에서는 host=db.
|
|
DATABASE_URL=
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 선택 — AI 프로바이더
|
|
# -----------------------------------------------------------------------------
|
|
# AI 요약 기능을 쓰려면 프로바이더 설정이 필요합니다. 두 가지 방법 중 선택:
|
|
# (A) 웹 UI 방식 — 앱 기동 후 /settings에서 선택·입력 (브라우저 LocalStorage, 추천)
|
|
# (B) 환경변수 방식 — 아래 값을 채우면 모든 사용자가 공통으로 사용
|
|
#
|
|
# 설정이 없어도 "단순 변환" 모드는 정상 동작합니다.
|
|
|
|
# --- (기본) Google Gemini 직접 호출 ---
|
|
# 무료 발급: https://aistudio.google.com/apikey
|
|
GEMINI_API_KEY=
|
|
|
|
# --- (선택) OpenAI 호환 엔드포인트 ---
|
|
# OrcaRouter · OpenAI · Ollama · LM Studio · vLLM 등 OpenAI Chat Completions
|
|
# 형식을 따르는 엔드포인트라면 무엇이든 연결됩니다.
|
|
#
|
|
# LLM_PROVIDER=openai-compatible 로 두었을 때만 아래 값들이 사용됩니다.
|
|
# OpenAI : LLM_BASE_URL=https://api.openai.com/v1 LLM_MODEL=gpt-4o-mini
|
|
# OrcaRouter : LLM_BASE_URL=https://api.orcarouter.ai/v1 LLM_MODEL=google/gemini-3.5-flash-lite
|
|
# Ollama : LLM_BASE_URL=http://localhost:11434/v1 LLM_MODEL=llama3.1 (키 불필요)
|
|
#
|
|
# ⚠️ 중계 서비스를 쓰면 회의 전문이 그 회사 서버를 거칩니다. SECURITY.md 참고.
|
|
# LLM_PROVIDER=
|
|
# LLM_BASE_URL=
|
|
# LLM_MODEL=
|
|
# LLM_API_KEY=
|
|
|
|
# ─────────────────────────────────────────────────────────────
|
|
# 회의 오디오 녹음 저장 위치 (선택)
|
|
# ─────────────────────────────────────────────────────────────
|
|
# 기본값은 <프로젝트>/uploads/recordings 입니다.
|
|
# Docker Compose에서는 uploads 볼륨에 저장되어 컨테이너를 재시작해도 남습니다.
|
|
#
|
|
# ⚠️ 녹음 파일에는 회의 원음이 그대로 들어 있습니다. 디스크 암호화된 위치에
|
|
# 두고, 필요 없어진 녹음은 직접 삭제하세요. SECURITY.md 참고.
|
|
# RECORDINGS_DIR=
|