Files
stt/README.md
dosangyoon 9ec998e1f1 fix(deps): pin numpy<2.2 for CPUs without x86_64_v2; docs Apache+503
- Avoid NumPy wheel baseline X86_V2 import crash on older VMs
- README: NumPy error remediation, Apache ProxyPass example, web UI note

Made-with: Cursor
2026-03-23 15:31:40 +09:00

14 KiB

Web STT (mp3/m4a 업로드 → 텍스트 변환)

구성

  • 백엔드: FastAPI (업로드/검증/STT 수행)
  • STT 엔진: faster-whisper (Whisper 모델)
  • 화자 분리(웹 기본 켜짐): pyannotewhisper_stt.py와 동일하게 로컬 ./models/pyannote-diarization-3.1 + HF 토큰·게이트 동의 필요. UI/API에서 끌 수 있음(diarize=false).
  • 프론트: 단일 HTML (파일 선택 → 전사 → 결과 표시/다운로드)
  • 선택 CLI: whisper_stt.py — OpenAI Whisper 기반 로컬 전사(기본: 화자 구분, 동일 pyannote 스냅샷)

동작 개요 (pseudocode)

UI:
  onSelect(file):
    validate client-side (extension)
    enable "전사" 버튼

  onClickTranscribe():
    POST /api/transcribe (multipart/form-data, file, options)
    show progress (업로드 중 / 처리 중)
    render returned text + segments
    allow download as .txt

API:
  POST /api/transcribe:
    if no file -> 400
    validate mime/ext in allowed audio types -> 415 if not
    save to temp file
    run STT(model, language, vad_filter, beam_size, ...)
    return { text, segments[], detected_language, duration_sec }
    cleanup temp file

사전 요구 사항

Ubuntu (22.04 / 24.04 등)

오디오 디코딩과 일부 Python 패키지 빌드에 쓰입니다.

sudo apt update
sudo apt install -y ffmpeg build-essential
  • ffmpeg: faster-whisper·Whisper가 mp3/m4a 등을 읽을 때 필요합니다. (apt로 설치하는 편이 가장 단순합니다.)
  • build-essential: 소스/휠 빌드가 필요한 의존성이 있을 때 도움이 됩니다.

선택(GPU로 faster-whisper 등을 쓸 때):

  • NVIDIA 드라이버 및 CUDA는 NVIDIA 문서에 맞게 설치합니다.
  • 이 저장소 기본값은 CPU입니다. GPU 사용 시 APP_WHISPER_DEVICE·APP_WHISPER_COMPUTE_TYPE 등을 환경에 맞게 조정하세요.

macOS

brew install ffmpeg

pipimageio-ffmpeg만으로도 CLI 쪽 보조는 가능하지만, 서버·도구 공통으로 시스템 ffmpeg 설치를 권장합니다.


Python 환경 (Conda 권장)

이 프로젝트는 conda 환경 stt (Python 3.11) 사용을 권장합니다. (Cursor/VS Code는 .vscode/settings.json에 인터프리터 경로가 있습니다.)

1) stt 생성 및 웹 서버 의존성

conda create -n stt python=3.11 -y
conda activate stt
pip install -r requirements.txt

2) (선택) 로컬 전사 CLI — whisper_stt.py

conda activate stt
pip install -r requirements-whisper-stt.txt

Ubuntu에서 pip install -r requirements-whisper-stt.txt 가 torch 관련 OSError / ATen.h 없음 등으로 실패할 때
기존 torch 설치가 깨졌거나 pip가 교체 도중 멈춘 경우가 많습니다.

conda activate stt   # 또는 사용 중인 env (예: ncue)
pip uninstall -y torch torchvision torchaudio functorch
pip uninstall -y torch torchvision torchaudio functorch   # Skipping만 나올 때까지 반복
pip cache purge
pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install -r requirements-whisper-stt.txt

같은 오류(ATen.h 없음 등)가 torch 재설치 시에도 반복되면
pip uninstall만으로는 깨진 site-packages/torch 폴더가 남는 경우가 있습니다. 아래로 잔여 디렉터리를 직접 삭제한 뒤 다시 설치하세요. (python3.11python -c "import sys; print(sys.version_info[:2])"로 맞춤.)

conda activate ncue   # 문제 나는 env
pip uninstall -y torch torchvision torchaudio functorch 2>/dev/null || true
rm -rf "$CONDA_PREFIX/lib/python3.11/site-packages/torch" \
       "$CONDA_PREFIX/lib/python3.11/site-packages/torch-"*.dist-info \
       "$CONDA_PREFIX/lib/python3.11/site-packages/torchaudio" \
       "$CONDA_PREFIX/lib/python3.11/site-packages/torchaudio-"*.dist-info \
       "$CONDA_PREFIX/lib/python3.11/site-packages/torchgen" \
       "$CONDA_PREFIX/lib/python3.11/site-packages/functorch"
pip cache purge
pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install -r requirements-whisper-stt.txt

그래도 실패하면 새 conda 환경(conda create -n stt-whisper python=3.11 -y)을 만들고, 위 README의 conda로 PyTorch 먼저 절차만 그 env에서 진행하는 것이 가장 확실합니다.

애초에 꼬이지 않게 하려면 PyTorch를 conda로 먼저 깐 뒤 위 requirements만 pip로 설치하는 것을 권장합니다.

conda activate stt
conda install pytorch torchaudio cpuonly -c pytorch -y
pip install -r requirements-whisper-stt.txt
  • Hugging Face hf CLI: pip install huggingface_hubhf auth login, hf download … (화자 구분용 pyannote 모델 등).
    • $ hf auth login
    • $ hf download pyannote/speaker-diarization-3.1 --local-dir ./models/pyannote-diarization-3.1
  • 화자 구분(기본 켜짐): ./models/pyannote-diarization-3.1 에 pyannote 스냅샷이 있어야 합니다. 없으면 스크립트가 hf download 안내 후 종료합니다. 모델 받기: pyannote/speaker-diarization-3.1 약관 동의 후 hf auth login, hf download … --local-dir ./models/pyannote-diarization-3.1. 다른 경로는 --diarize-model-dir 또는 WHISPER_DIARIZE_MODEL_DIR 로 지정.
  • 하위 gated 모델(403 시): speaker-diarization-3.1만 동의했다고 끝나지 않습니다. 실행 시 최소한 아래 각각 Hugging Face에서 로그인 후 약관·양식을 제출해야 합니다: speaker-diarization-3.1, segmentation-3.0, speaker-diarization-community-1 (xvec_transform.npz 등). 오류에 다른 pyannote/… 가 나오면 그 저장소도 동일합니다. 403 / «not in the authorized list» 이면 (1) 빠진 저장소 동의 (2) 토큰이 동의한 같은 계정의 것인지 (hf auth whoami) (3) 동의 후 새로 발급한 Read 토큰 사용을 확인하세요. 실행 전 hf auth login 또는 HF_TOKEN. whisper_stt.py는 로컬 config.yaml 로드 후에도 이 토큰으로 허브에서 하위 파일을 받습니다.
  • 화자 구분 끄기: python whisper_stt.py 입력.m4a 출력.txt --no-diarize (Whisper 통문만 저장)
python whisper_stt.py 입력.m4a 출력.txt
python whisper_stt.py 입력.m4a 출력.txt --no-diarize
python whisper_stt.py 입력.m4a 출력.txt --diarize-model-dir /다른/경로/pyannote-diarization-3.1

대안: environment.yml (환경 이름 ncue, conda에 ffmpeg 포함)

conda env create -f environment.yml
conda activate ncue

pip 의존성은 requirements.txt를 통해 설치됩니다. 팀에서 이미 ncue를 쓰는 경우에만 사용해도 됩니다.


서버 실행

conda activate stt   # 또는 ncue
uvicorn app.main:app --reload --host 127.0.0.1 --port 8025

또는 저장소 루트에서 ./run.sh (백그라운드 + server.log, 기본 포트 8025, PORT·CONDA_ENV 등으로 조정).

브라우저에서 http://127.0.0.1:8025 접속.

웹 UI는 faster-whisper 전사와(옵션) pyannote 화자 분리를 지원합니다. OpenAI Whisper 기반 CLI는 whisper_stt.py 를 사용하세요.

HTTPS 도메인(https://ncue.net/stt/…)에서 503 (Service Unavailable)

브라우저가 503을 보여 줄 때, 대부분 리버스 프록시(nginx·Apache 등)가 백엔드(uvicorn)에 붙지 못했다는 뜻입니다. 이 저장소의 앱은 일반적으로 503을 직접 내지 않습니다.

흔한 원인

  1. run.sh를 다른 머신에서만 실행한 경우
    run.sh는 uvicorn을 **127.0.0.1:8025**에만 띄웁니다. 웹 서버(프록시)가 돌아가는 서버와 같은 호스트에서 프로세스가 떠 있어야 https://도메인/stt/ 프록시가 연결됩니다. 노트북에서만 ./run.sh를 켜 두면 공개 도메인 쪽 업스트림은 비어 있어 503이 납니다.

  2. 프로세스가 곧바로 종료된 경우
    DB 설정 오류, import 실패(NumPy·torch 등) 로 uvicorn이 뜨자마자 죽으면 프록시도 503을 냅니다. 서버에서 tail -n 100 server.log 로 스택 트레이스를 확인하세요.

  3. 포트·프록시 설정 불일치
    프록시가 가리키는 포트가 실제 uvicorn 포트(PORT, 기본 8025)와 같아야 합니다.

구형 CPU / NumPy X86_V2 오류 (server.log)

다음처럼 앱이 시작조차 못 하고 죽는 경우가 있습니다.

RuntimeError: NumPy was built with baseline optimizations: (X86_V2) but your machine doesn't support: (X86_V2).

의미: 설치된 NumPy 바이너리가 x86_64_v2(AVX2 등)를 요구하는데, 서버 CPU가 이를 지원하지 않습니다. (가상머신·오래된 Xeon 등에서 흔합니다.)

조치 (웹 서버에서, 사용 중인 conda env — 예: ncue):

conda activate ncue
pip install "numpy>=1.26,<2.2" --force-reinstall
pip install -r requirements.txt   # 나머지 의존성 유지
./run.sh

pip만으로 안 되면 conda-forge NumPy가 해당 CPU에 맞는 빌드를 주는 경우가 많습니다.

conda install -n ncue "numpy<2.2" -c conda-forge

이 저장소 requirements.txt에는 위와 같이 numpy<2.2 를 명시해 두었습니다. 이미 깨진 환경은 위처럼 한 번 재설치하면 됩니다.

같은 서버에서 빠른 점검

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8025/healthz
# 200 이어야 정상
ss -lntp | grep 8025
# 또는: lsof -iTCP:8025 -sTCP:LISTEN

nginx 예시 (/stt/ 아래로 서비스할 때, 접두사를 벗겨 uvicorn의 /·/api/…에 넘깁니다)

location /stt/ {
    proxy_pass http://127.0.0.1:8025/;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

proxy_pass에 **끝 슬래시(/)**가 있어야 location /stt/와 짝이 맞아 경로가 올바르게 넘어갑니다. 설정을 고친 뒤 nginx -t 후 reload 하세요.

Apache (httpd) 예시 (mod_proxy, mod_proxy_http 필요)

ProxyPass        "/stt/" "http://127.0.0.1:8025/"
ProxyPassReverse "/stt/" "http://127.0.0.1:8025/"

설정 반영 후 apachectl configtest 및 재시작(또는 reload) 하세요.

공개 URL은 가능하면 https://예시/stt/ 처럼 슬래시까지 포함해 두면, UI의 상대 경로(healthz, api/…)가 같은 접두사 아래로 잘 붙습니다.


옵션·환경 변수

  • 모델: 기본 small (정확도/속도 균형). APP_WHISPER_MODEL=base|small|medium|large-v3 등으로 변경 가능.
  • 디바이스: 기본 CPU. Apple Silicon에서 Metal은 faster-whisper 단독으로는 제한이 있어 CPU 기본값을 권장.
  • 화자 분리: pip install -r requirements.txtpyannote.audio가 포함됩니다. 모델 폴더는 WHISPER_DIARIZE_MODEL_DIR / PYANNOTE_MODEL_DIR 또는 기본 ./models/pyannote-diarization-3.1. 다른 경로는 APP_PYANNOTE_MODEL_DIR로 지정 가능. HF 토큰(HF_TOKEN 등)과 gated 저장소 동의는 whisper_stt.py 절·requirements-whisper-stt.txt 주석과 동일합니다.
  • 기타: APP_WHISPER_DEVICE, APP_WHISPER_COMPUTE_TYPE, 업로드 크기 등은 app/main.py.env 예시를 참고.

Linux + Conda: libtinfo.so.6 / vi·bash 경고

(ncue) 등 conda 환경을 켠 뒤 LD_LIBRARY_PATH${CONDA_PREFIX}/lib가 들어가면, 터미널에서 돌아가는 시스템 프로그램(vi, bash, less 등) 이 conda에 들어 있는 libtinfo.so.6을 먼저 물 수 있습니다. 그 라이브러리에 ELF 버전 태그가 맞지 않을 때 «no version information available» 가 납니다. (run.sh는 스크립트 안에서 이를 피하도록 처리해 두었습니다.)

conda deactivate 해도 경고가 남는 경우

  • deactivate만으로 LD_LIBRARY_PATH가 비워지지 않을 수 있습니다 (이전 셸 값 복원 실패, .bashrc에서 직접 export, 다른 툴이 덧붙임).
  • vi가 conda·vim 빌드일 수 있습니다. type -a vi, which -a vi 로 확인하고, 가능하면 /usr/bin/vi 또는 /usr/bin/vim 을 쓰세요.

당장 편집·실행

unset LD_LIBRARY_PATH
vi run.sh

또는 한 줄로:

env -u LD_LIBRARY_PATH /usr/bin/vi run.sh
LD_LIBRARY_PATH= /usr/bin/vi run.sh

저장소 헬퍼 (chmod +x scripts/env-no-ld.sh 후):

./scripts/env-no-ld.sh vi run.sh
./scripts/env-no-ld.sh /usr/bin/vi run.sh

원인 확인

echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH-<비어 있음>}"
type -a vi
conda deactivate
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH-<비어 있음>}"   # 여전히 miniconda 경로면 .bashrc 등 확인
grep -n LD_LIBRARY_PATH ~/.bashrc ~/.profile ~/.bash_profile 2>/dev/null

장기적으로

  1. grep -r LD_LIBRARY_PATH "$HOME/workspace/miniconda3/envs/ncue/etc/conda/activate.d/" 등으로 어떤 패키지가 넣는지 확인합니다.
  2. GPU/torch가 꼭 필요한 터미널과 편집·git용 터미널을 나누거나, 편집 전에 unset LD_LIBRARY_PATH 를 습관화합니다.
  3. conda install -c conda-forge ncurses 로 env 안 ncurses를 맞추면 완화되는 경우가 있습니다(환경마다 다름).

플랫폼 요약

항목 Ubuntu macOS
ffmpeg sudo apt install ffmpeg brew install ffmpeg
Python Conda stt 권장 동일
웹 STT pip install -r requirements.txt 동일
whisper_stt.py pip install -r requirements-whisper-stt.txt 동일