EFaligner는 HTK(Hidden Markov Model Toolkit) 기반의 영어 강제 정렬(Forced Alignment) 시스템입니다. P2FA(Penn Forced Aligner)를 기반으로 하여 음성 파일과 전사 텍스트를 입력받아 음소(phoneme) 및 단어(word) 단위의 정확한 시간 정렬 정보를 Praat TextGrid 형식으로 출력합니다.
- 자동 음소 정렬: 영어 음성과 텍스트를 음소 단위로 정확하게 정렬
- 다중 샘플레이트 지원: 8kHz, 11.025kHz, 16kHz 음성 파일 처리
- 자동 리샘플링: sox를 이용한 자동 변환
- TextGrid 출력: Praat에서 바로 사용 가능한 표준 형식
- 웹 인터페이스: Flask 기반 웹 애플리케이션 제공
- Short Pause (sp) 처리: 단어 사이의 휴지를 별도 구간으로 분리
- P2FA 호환: Penn Forced Aligner와 호환되는 모델 사용
- Python: 3.6 이상
- HTK: 3.4.1 (Hidden Markov Model Toolkit)
- sox: 음성 리샘플링용
- OS: Linux (Ubuntu 20.04+ 권장)
flask>=2.0.0
gunicorn>=20.0.0
numpycd /var/www/html/efalignerHTK는 라이선스 제약으로 직접 다운로드가 필요합니다:
- HTK 공식 사이트에서 HTK-3.4.1 다운로드
- 압축 해제 및 컴파일:
tar -xvf HTK-3.4.1.tar.gz
cd htk
./configure --prefix=/usr/local
make all
sudo make installsudo apt-get update
sudo apt-get install sox libsox-fmt-all# 가상환경 생성 (권장)
python3 -m venv venv
source venv/bin/activate
# 패키지 설치
pip install flask gunicorn numpyP2FA 모델이 model/ 디렉토리에 있는지 확인:
ls -la model/
# dict, monophones, 8000/, 11025/, 16000/ 폴더가 있어야 함python3 align.py <audio.wav> <transcript.txt> <output.TextGrid>예시:
python3 align.py test/BREY00538.wav test/BREY00538.txt test/BREY00538.TextGrid-r RATE: 샘플레이트 지정 (8000, 11025, 16000 중 하나)-s START: 시작 시간 (초 단위, 기본값 0)-e END: 종료 시간 (초 단위)
예시:
# 16kHz로 강제 변환
python3 align.py -r 16000 audio.wav transcript.txt output.TextGrid
# 특정 구간만 정렬 (5초부터 15초까지)
python3 align.py -s 5.0 -e 15.0 audio.wav transcript.txt output.TextGrid- 형식: WAV (PCM)
- 샘플레이트: 8kHz, 11.025kHz, 16kHz (권장)
- 채널: 모노 (단일 채널)
- 비트 깊이: 16-bit
- 인코딩: UTF-8, UTF-16, Latin-1 지원
- 내용: 순수 텍스트 (영어 대소문자 모두 가능)
- 특수 기호: 자동으로 제거됨 (
,,.,!,?등)
예시:
The quick brown fox jumps over the lazy dog.
This is a test sentence for alignment.
- 형식: Praat TextGrid (short format)
- 티어:
- phone: 음소 단위 정렬
- word: 단어 단위 정렬
efaligner/
├── align.py # 메인 정렬 스크립트
├── run.sh # 테스트 실행 스크립트
├── README.md # 이 파일
├── model/ # P2FA 음향 모델
│ ├── dict # 발음 사전
│ ├── monophones # 음소 목록
│ ├── 8000/ # 8kHz 모델
│ │ ├── config
│ │ ├── hmmdefs
│ │ └── macros
│ ├── 11025/ # 11.025kHz 모델
│ │ ├── config
│ │ ├── hmmdefs
│ │ └── macros
│ └── 16000/ # 16kHz 모델
│ ├── config
│ ├── hmmdefs
│ └── macros
├── test/ # 테스트 파일
│ ├── BREY00538.wav
│ ├── BREY00538.txt
│ └── BREY00538.TextGrid
├── tmp/ # 임시 작업 디렉토리 (자동 생성)
└── webapp/ # Flask 웹 애플리케이션
├── app.py
├── templates/
└── data/
cd webapp
python3 app.py
# 브라우저에서 http://localhost:5020 접속cd webapp
gunicorn -w 4 -b 0.0.0.0:5020 app:app웹앱은 다음 환경변수를 통해 업로드 제한 및 보안 옵션을 제어합니다. 저장소 루트(efaligner/)에 .env 파일을 생성하면 start_webapp.sh, start_production.sh에서 자동으로 로드됩니다. 샘플은 .env.example을 참고하세요.
- FLASK_SECRET_KEY: 세션 암호화 키
- PORT: 웹앱 포트 (기본 5020)
- MAX_CONTENT_LENGTH_MB: 업로드 허용 최대 용량(MB, 기본 64)
- MAX_FILES_PER_REQUEST: 한 번에 업로드 가능한 파일 개수(기본 100)
- ENABLE_CLAMAV_SCAN: 업로드 파일에 대한 안티바이러스 검사 활성화(1=활성, 0=비활성, 기본 0)
- MAIL_*: 비밀번호 초기화 메일 발송 설정(선택)
예시 .env:
FLASK_SECRET_KEY=change-me
PORT=5020
MAX_CONTENT_LENGTH_MB=64
MAX_FILES_PER_REQUEST=100
ENABLE_CLAMAV_SCAN=1
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=True
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_DEFAULT_SENDER=noreply@efaligner.local
앱 내부에서는 위 값을 자동으로 읽어 적용합니다(webapp/app.py).
Gunicorn 앞단에 Nginx를 두어 리버스 프록시/업로드 제한/정적파일 처리를 할 수 있습니다. 예시 설정 파일은 nginx/efaligner_nginx.conf에 포함되어 있습니다.
- 설정 복사 및 활성화
sudo cp nginx/efaligner_nginx.conf /etc/nginx/sites-available/efaligner
sudo ln -s /etc/nginx/sites-available/efaligner /etc/nginx/sites-enabled/efaligner
- 서버명/업로드 제한 수정
server_name을 실제 도메인으로 변경client_max_body_size를.env의 MAX_CONTENT_LENGTH_MB와 동일하게 조정
- 구문 검사 및 재시작
sudo nginx -t
sudo systemctl reload nginx
- Gunicorn 서비스(선택)
start_production.sh로도 충분하지만, 시스템 서비스로 관리하려면 다음과 같은 유닛 파일을 참고하세요.
sudo tee /etc/systemd/system/efaligner.service >/dev/null <<'UNIT'
[Unit]
Description=EFaligner Gunicorn Service
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/html/efaligner/webapp
EnvironmentFile=/var/www/html/efaligner/.env
ExecStart=/var/www/html/efaligner/venv/bin/gunicorn -w 4 -b 127.0.0.1:5020 app:app
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
UNIT
sudo systemctl daemon-reload
sudo systemctl enable --now efaligner
이후 Nginx는 127.0.0.1:5020으로 프록시합니다.
- 파일 업로드: 음성 파일(.wav)과 전사 파일(.txt) 업로드
- 배치 처리: 여러 파일 동시 정렬
- 결과 다운로드: TextGrid 파일 및 ZIP 압축 다운로드
- 사용자 인증: 계정 기반 작업 관리
- 기반: P2FA (Penn Forced Aligner) v1.003
- 학습 데이터: TIMIT 코퍼스
- 음소 세트: CMU 음소 체계 기반
- HMM 상태: 3-state left-to-right HMM
- 전처리: 텍스트 정규화 및 사전 확인
- 특징 추출: PLP (Perceptual Linear Prediction) 계수
- 정렬: Viterbi 알고리즘 기반 강제 정렬
- 후처리: sp(short pause) 분리 및 TextGrid 생성
- sil (Silence): 발화 전후의 긴 침묵 구간
- sp (Short Pause): 단어 사이의 짧은 휴지 (P2FA 모델에서 사용)
- 처리: 각 단어의 정확한 시작/끝 시간 사용 (v1.1+)
- 효과: 더 정확한 단어 경계 및 침묵 구간 표현
- 수정 전: Word tier에서 각 단어의 끝 시간이 다음 단어의 시작 시간으로 잘못 표시됨
- 수정 후: 각 단어/침묵 구간이 실제 음소 경계 기반의 정확한 시작/끝 시간을 가짐
- 영향: 침묵 구간(sil/sp)의 정확도 향상, 단어 간 간격 정확히 표현
# HTK가 PATH에 있는지 확인
which HCopy
# 없으면 HTK 재설치 또는 PATH 설정
export PATH=/usr/local/bin:$PATH# sox 설치
sudo apt-get install sox libsox-fmt-all- 발음 사전에 없는 단어
dict.local파일에 발음 추가:
NEWWORD N Y UW W ER D
- 음성 파일과 텍스트 불일치
- 음성 품질 확인 (노이즈, 볼륨)
- 전사 텍스트 정확성 확인
- 샘플레이트: 16kHz 사용 권장 (정확도 향상)
- 파일 크기: 한 번에 처리할 파일 크기는 5MB 이하 권장
- 배치 처리: 웹 인터페이스에서 최대 100개 파일까지 처리
P2FA 기본 사전(model/dict)에 없는 단어는 정렬 과정에서 "SKIPPING WORD"로 무시됩니다. 필요한 경우 사용자 사전 dict.local을 프로젝트 루트(efaligner/)에 생성하면, 실행 시 자동으로 기본 사전과 병합하여 사용합니다.
- 위치와 파일명
- 경로:
efaligner/dict.local - 인코딩: UTF-8 권장
- 형식
- 한 줄에 하나의 항목:
WORD PHONEME1 PHONEME2 ... - 단어는 대문자 사용 권장(P2FA/CMU 관례)
- 발음은 ARPABET 음소 체계 사용(P2FA 모델과 일관)
예시:
AIYOUNG EY1 Y AH2 NG
GITHUB G IH1 T HH AH2 B
COPILOT K OW1 P AY2 L AH0 T
- 주의사항
sil,sp등 특수 토큰은 재정의하지 마세요(모델/스크립트에서 사용).- 동일 단어가 여러 번 정의되면 예측 불가 동작이 발생할 수 있으므로 한 번만 정의하세요.
- 대소문자 매칭에 유의하세요(사전은 대문자를 기대합니다).
- 점검 방법
- 실행 전 빠르게 포함 여부 확인:
grep -n "^WORD " model/dict dict.local - 실행 중 로그에서
SKIPPING WORD가 사라졌는지 확인
- 백업 권장
dict.local은 버전 관리에 포함하여 협업 시 충돌을 방지하세요.- 대규모 추가 전에는 사본을 만들어 변경 이력을 남기세요.
이 프로젝트는 MIT 라이선스 하에 배포됩니다.
- P2FA (Penn Forced Aligner): 기본 모델 및 코드 제공
- HTK (Hidden Markov Model Toolkit): 음성 인식 엔진
- TIMIT 코퍼스: 음향 모델 학습 데이터
문제가 발생하거나 개선 사항이 있으면 이슈를 등록해주세요.
EFaligner - Precise English Speech Alignment Made Easy