lukehemmin be5f505410 fix: normalize faster-whisper TranscriptionInfo to dict
Colab run 4 (A100): same namedtuple bug as segments — faster-whisper
returns TranscriptionInfo (namedtuple) but batch.py reads
outcome['info'].get('language') -> AttributeError 'TranscriptionInfo'
object has no attribute 'get' on every real transcription, failing the
CLI, API auto-worker job, worker drain, and bench clip alike.

FasterWhisperEngine now normalizes info to a dict at the boundary
(_to_dict_info: _asdict -> dataclasses.asdict -> known-field fallback).

+ 2 unit tests (namedtuple/dict info); 138 tests pass, ruff clean.
2026-08-12 17:39:15 +09:00

luke_scribe

내부용 로컬 STT 전사 API — faster-whisper(CTranslate2) 기반, 하드웨어 적응형, privacy-first.

한국어 + 영문 기술용어(KO+EN code-switching)를 외부 STT API에 보내지 않고 통제된 환경에서 전사한다. 단일 Job 추상화로 배치(파일)와 실시간(WebSocket)을 처리한다.

설계 단일 진실원본(SoT): .omc/plans/consensus-luke-scribe-stt-api.md, .omc/specs/deep-interview-luke-scribe-stt-api.md

상태

  • 설계 완료(모호도 ~5%) · 구현 완료(v0.1 전체 플랫폼, mock 검증)feat/full-platform
  • 이 저장소 환경은 CPU-only이고 ffmpeg/모델 다운로드가 없으므로 단위/통합 테스트는 mock 기반으로 검증한다. 실제 GPU/모델 스모크는 GPU가 있는 환경에서 수행한다.

빠른 시작 (개발)

# 1) 의존성 (Python 3.11+)
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[engine,api]"   # 또는: uv sync --extra engine --extra api

# 2) 환경 설정
cp .env.example .env

# 3) 하드웨어 감지 → 능력 등급/정밀도/워커수
luke-scribe detect

# 4) 단일 파일 전사 (CPU에서도 동작)
luke-scribe transcribe samples/hello-ko-en.wav --language ko --device cpu

# 5) API 서버 (개발 기본: in-proc 큐, Redis 불필요)
luke-scribe serve

# 6) API 키 생성 (1회만 출력, 다이제스트만 저장)
luke-scribe key --create --scopes transcribe,admin

5분 스모크 (mock 환경에서도 CLI 동작 확인)

./run.sh test          # 단위/통합 테스트
luke-scribe detect     # JSON 프로필

CLI

명령 설명 상태
detect 하드웨어 감지 · 능력 등급(T0~T3) · 정밀도 · 워커수
transcribe <file> 단발 파일 전사 (faster-whisper, CPU/GPU)
bench <manifest> turbo vs large-v3 도메인 벤치 · 모델 결정 게이트
serve FastAPI 서버 (in-proc 또는 Redis 큐)
key --create API 키 생성 (1회 출력 + 다이제스트 저장)

Exit codes: 0 성공 · 2 입력 오류 · 3 모델/장치 오류 · 4 추론 오류 · 5 결과 쓰기 오류 · 130 인터럽트

REST API (배치)

메서드 경로 설명
POST /v1/jobs multipart 업로드 (file + options JSON) → 202 {job_id}
GET /v1/jobs/{id} 상태 · queue_position · progress
GET /v1/jobs/{id}/result?format=json|txt|srt|vtt 결과
DELETE /v1/jobs/{id} 협조적 취소
GET /v1/jobs 내 job 목록
GET /health 헬스체크 (공개)
GET /v1/system · /v1/models admin 전용

인증: X-API-Key 헤더 (또는 Authorization: Bearer). 스코프 + Job 소유권 강제.

KEY=$(luke-scribe key --create --scopes transcribe | python -c "import sys,json;print(json.load(sys.stdin)['key'])")
curl -X POST localhost:8000/v1/jobs \
  -H "X-API-Key: $KEY" \
  -F file=@samples/hello-ko-en.wav \
  -F 'options={"language":"ko","formats":["json","srt"]}'

WebSocket (실시간)

WS /v1/stream — 첫 메시지는 init 프레임(인증 + 오디오 협상):

{"type":"init","api_key":"...","audio":{"codec":"pcm_s16le","sample_rate":16000,"channels":1},"options":{"language":"ko"}}

응답: partial(가설) / final(확정, LocalAgreement) / status.

벤치마크

luke-scribe bench benchmarks/manifest.yaml --output benchmarks/report.json --decision benchmarks/decisions/default-model-v1.json

절대 기준: entity 보존 ≥95% · K-CER ≤15% · 실패율 0%. 게이트는 turbo 우선, 미달 시 large-v3 채택. 단일 모델 run은 decision artifact를 생성하지 않는다.

Docker (프로덕션)

# CPU 프로파일
docker compose --profile cpu up -d
# GPU 프로파일 (NVIDIA Container Toolkit 필요)
docker compose --profile gpu up -d

API + Redis + 워커, 공유 스토어 볼륨. LUKESCRIBE_API_KEYS 필수.

Colab 실전 테스트 (GPU)

이 저장소의 CI/개발 환경은 CPU-only라 모델·ffmpeg는 mock으로만 검증했다. GPU + 실제 faster-whisper 모델로 실전 검증하려면 Colab 노트북을 사용한다 (Colab Pro T4 GPU 권장 — 터미널에서도 동일 명령 실행 가능):

  • notebooks/luke-scribe-colab.ipynb — 클론 → 설치 → detect(GPU 감지) → 테스트 → 샘플 TTS 생성 → 실제 한국어 전사 → hotword/후처리 → API 스모크 → 벤치마크
  • 노트북은 scripts/build_colab_notebook.py로 생성/재생성한다
  • private 저장소이면 1번 셀의 GITEA_TOKEN에 토큰을 넣는다

알려진 제한 (v0.1)

  • 실시간 decode는 EngineOwner 스텁 (실제 WS decode는 GPU 환경에서 활성화).
  • Redis/RQ 브로커는 Redis 설치 시에만 동작 (기본 in-proc).
  • 화자 분리(pyannote) / 외부 LLM 보정은 [diarize]/[llm] extra + allowlist 필요.
  • 이 저장소 환경(CPU-only, ffmpeg 없음)에서는 모델·ffmpeg 호출을 mock으로 검증.
S
Description
No description provided
Readme
1.2 MiB
Languages
Markdown 100%