feat: Hearo 1차 구현 — 프로그램 소리 실시간 번역 자막
프로그램별 오디오를 캡처해 로컬 GPU에서 음성인식→번역하고 화면 위 자막으로 보여주는 데스크톱 앱. 한/영/일/중 4개 언어. 구성 - audio: WASAPI 프로그램별 캡처(C++ 보조 프로그램) + 장치 루프백 폴백, 적응형 VAD 발화 분할 - models: 속도~품질 5단계 티어, faster-whisper + CTranslate2/LLM 2백엔드, 용어집(플레이스홀더 보호 + 프롬프트 주입) - core: Qt 비의존 파이프라인 엔진 (캡처/분할/추론 3스레드, 큐 연결) - ui: 사이드바 5화면 + 무테두리 항상위 자막 오버레이, 자체 다크 테마 모델 선정 근거는 docs/MODELS.md, 추가학습 가능 여부와 방법은 docs/FINETUNING.md 참고. 검증: pytest 39개 통과 (GPU·오디오 장치 없이 실행), ruff clean Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
52
src/hearo/constants.py
Normal file
52
src/hearo/constants.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""전역 상수. 제품명 변경은 이 파일만 고치면 됩니다."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
APP_NAME = "Hearo"
|
||||
APP_NAME_KO = "히어로"
|
||||
APP_SLOGAN = "듣고, 바로 이해하다"
|
||||
APP_VERSION = "0.1.0"
|
||||
ORG_NAME = "tkrmagid"
|
||||
|
||||
# 지원 언어 (1차: 4개)
|
||||
LANGUAGES: dict[str, dict[str, str]] = {
|
||||
"ko": {"label": "한국어", "english": "Korean", "nllb": "kor_Hang", "flag": "KO"},
|
||||
"en": {"label": "English", "english": "English", "nllb": "eng_Latn", "flag": "EN"},
|
||||
"ja": {"label": "日本語", "english": "Japanese", "nllb": "jpn_Jpan", "flag": "JA"},
|
||||
"zh": {"label": "中文", "english": "Chinese", "nllb": "zho_Hans", "flag": "ZH"},
|
||||
}
|
||||
LANGUAGE_CODES = tuple(LANGUAGES.keys())
|
||||
|
||||
# 기본 모델 품질 티어. 실제 티어 정의는 models/tiers.py 에 있지만,
|
||||
# config 가 models 패키지를 import 하면 순환 의존이 생기므로 키만 여기에 둔다.
|
||||
DEFAULT_TIER = "balance"
|
||||
|
||||
# 오디오 파이프라인 규격
|
||||
SAMPLE_RATE = 16_000
|
||||
CHANNELS = 1
|
||||
FRAME_MS = 20
|
||||
FRAME_SAMPLES = SAMPLE_RATE * FRAME_MS // 1000
|
||||
|
||||
|
||||
def user_data_dir() -> Path:
|
||||
"""설정/로그/모델 캐시를 두는 사용자 디렉터리."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
if sys.platform == "win32":
|
||||
base = Path(os.environ.get("APPDATA", Path.home() / "AppData" / "Roaming"))
|
||||
elif sys.platform == "darwin":
|
||||
base = Path.home() / "Library" / "Application Support"
|
||||
else:
|
||||
base = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config"))
|
||||
path = base / APP_NAME
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
def models_dir() -> Path:
|
||||
path = user_data_dir() / "models"
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
return path
|
||||
Reference in New Issue
Block a user