본문으로 건너뛰기

한국어 콘텐츠 LID 정확도 비교 — Whisper vs VoxLingua107

1. 개요

1.1 배경 — STT 파이프라인 LID 단계 문제

STT 는 보통 Whisper 를 쓰지만, 다국어가 섞인 영상에서는 환각과 오류가 두드러진다. 원인 중 하나는 WhisperX 의 lock-in — 영상 초반 30초만 듣고 메인 언어를 정한 뒤 전체를 그 언어로 전사하므로, 중간에 등장하는 외국어 구간이 한국어 모드로 억지 해석되어 garbled 결과가 나온다.

각 발화 구간마다 정확한 언어를 미리 알려주면 결과는 크게 개선된다. 이를 위해 LID(Language Identification, 언어 식별) 를 전사기에서 분리해 별도 단계로 실행하는 구조가 필요한데, 다음 질문이 남는다 — 어떤 모델을 쓰고, 입력은 raw 인가 denoise 인가? 우리가 다루는 콘텐츠는 BGM·효과음·함성이 항상 깔린 한국 드라마/예능/뉴스 등이라, 일반 깨끗한 음성 기준의 모델 평가가 그대로 통하지 않는다. 정량 데이터 없이 모델도 denoise 적용 여부도 감으로 결정할 수밖에 없는 상태가 본 POC 의 출발점이다.

1.2 POC 목적

본 문서는 BGM 이 섞인 한국 영상에서 어떻게 언어를 식별·선택해야 할지를 정량 비교로 답한다. 비교 대상 LID 모델 두 가지(Whisper LID, VoxLingua107) × 입력 두 가지(raw, denoise) = 4-way 매트릭스이며, 동일 샘플에 네 조합을 동시 실행해 일치율과 처리 시간을 측정한다.

1.3 결정사항

POC 검증 도구이므로 단순함을 우선했고, 비교 결과의 신뢰성을 위해 변수를 최소화했다.

  • 보정 정책 없음 — script check, override, blacklist 등 후처리 X. 네 가지 LID 결과를 그대로 비교.
  • VAD 통제 — raw audio 에 Silero VAD 를 한 번만 실행하고, 같은 시간 구간을 denoise audio 에도 동일 적용. raw / denoise 가 서로 다른 구간을 보는 일이 없도록 통제.
  • 모델 사전 로드 — 네 모델을 모두 먼저 로드한 뒤 측정 시작. 처리 시간에서 모델 로딩 비용 제외.
  • denoise 강도 고정 — DeepFilterNet v3, atten_lim_db=-30 (강도 1단). 강도 비교는 본 POC 범위 밖.
  • LID 단계만 — diarize / ASR 호출 없음. 단일 GPU(cuda:0), 단일 audio 순차 처리.

1.4 처리 흐름

[Denoise 적용시]
audio → VAD → 각 발화 구간 → denoise → [Whisper | VoxLingua]LID

[Denoise 미 적용시]
audio → VAD → 각 발화 구간 → [Whisper | VoxLingua]LID

2. 비교 설계

2.1 모델

비교 대상은 두 가지 LID 모델이다.

Whisper LID (baseline). faster-whisper large-v3-turbo
(mobiuslabsgmbh/faster-whisper-large-v3-turbo ) 의 detect_language() 를 호출. Whisper 는 다국어 음성인식을 학습한 모델이며, LID 는 그 부산물로 얻는 100여 언어 분류 결과다. 입력 오디오의 처음 30초만 사용한다. 상위 STT 파이프라인이 이미 쓰고 있으므로 본 POC 의 baseline 으로 둔다.

VoxLingua107 (실험군). SpeechBrain ECAPA-TDNN 기반 LID 전용 모델 (speechbrain/lang-id-voxlingua107-ecapa ). 107개 언어를 분류하도록 학습되었고, 음향이 유사한 언어 쌍(ko/ja, zh/ja, th/lo/km 등) 구분이 강한 것으로 알려져 있다. 짧은 발화에서도 비교적 안정적인 신뢰도를 낸다.

LID 전용 모델 후보는 여럿(NeMo TitaNet, ECAPA 포크 등)이지만, VoxLingua107 은 한국어가 학습 언어에 포함되어 있고 우리 환경(GPU 단일, HF 캐시)에 즉시 통합 가능하며, 비교 자료가 풍부해 결과 해석이 쉽다.
따라서 본 POC 의 대안으로 채택했다.

2.2 변수

입력 변수로 raw vs denoise 를 함께 본다. denoise 는 BGM·효과음·함성을 제거해 음성을 도드라지게 만들지만, enhance 모델은 LID 학습 시 본 적 없는 신호 변형을 만들 수도 있어 LID 정확도에 미치는 효과가 한쪽으로 단정되지 않는다. 상위 STT 파이프라인은 "denoise 가 LID 를 망친다" 는 경험적 가정 아래 raw chunk 로 LID 를 호출하고 있으나, 이 가정 자체를 본 POC 의 검증 대상으로 둔다.

따라서 비교 매트릭스는 모델 2 × 입력 2 = 4-way 다.

raw audiodenoise audio
Whisper LIDW-rawW-den
VoxLingua107V-rawV-den

같은 발화 구간에 네 결과를 동시 산출하고 일치/불일치를 비교한다.

2.3 측정 지표

일치율 (정확도 proxy)

콘텐츠에 ground truth 레이블이 없어 정확도를 직접 잴 수 없다. 대신 네 결과(W-raw / V-raw / W-den / V-den)의 상호 일치 여부 를 proxy 로 쓴다. 모두 같으면 안전한 발화, 불일치는 어느 한쪽이 틀렸다는 신호다.

산출 항목:

  • 4-way 일치율 — 네 결과 전부 일치
  • W-raw vs V-raw / W-den vs V-den — 같은 입력에서 모델 간 일치
  • W-raw vs W-den / V-raw vs V-den — denoise 가 각 모델에 주는 영향

처리 시간

모델 로딩 시간은 제외하고 audio 한 건의 순수 처리 시간만 단계별로 기록한다.

단계범위
denoiseDeepFilterNet 호출 + 16k 리샘플
vadSilero VAD 호출
whisper_lid모든 segment 의 Whisper LID 호출 합 (raw+denoise)
voxlingua_lid모든 segment 의 VoxLingua107 호출 합 (raw+denoise)
totalrun() 진입부터 완료까지

산출물: 세그먼트별 output/<stem>.csv + 파일별 output/timings.csv .

2.4 데이터셋

한국 영상 콘텐츠 6종 (장르별 한 편씩) 을 사용했다. 16kHz mono WAV 전처리 완료, 길이 30분~2시간대, 정답 레이블 없음(2.3 의 일치율 proxy 방식).

한국어가 메인이지만 장르별로 외국어 / 배경 소음 양상이 다르다.

구분방송재생시간URL
뉴스KBS 9 뉴스48:30https://www.youtube.com/watch?v=rX1P-jOoNmM
다큐슈퍼피쉬 1부58:40https://www.youtube.com/watch?v=iNbWqC1iqKw
드라마KBS 겨울 연가1:04:52https://www.youtube.com/watch?v=irVKEhb9g8M
사극태조 왕건54:10https://www.youtube.com/watch?v=nmlE2iPWLGM
예능출장십오야 X 스타쉽 전국체전 풀버전1:00:06https://www.youtube.com/watch?v=6wJGpi1nkCg
스포츠2009 프로야구 한국시리즈 7차전1:55:22https://www.youtube.com/watch?v=fP1QEs1Uj5U

장르별로 한 편씩 택한 것은 한 장르에 치우친 결론을 피하고, 콘텐츠 특성(BGM 강도, 외국어 양상)과 LID 결과 사이의 패턴을 보기 위함이다.


3. 구현

소스코드는 아래 URL 참고

3.1 디렉토리/흐름

디렉토리 구조

poc-lid-bench/
├── CLAUDE.md
├── pyproject.toml
├── conf.py # MODEL_DIR 등 경로 상수
├── log.py # 파일 로거 (lid_bench.log)
├── main.py # 진입점: wav 목록 순회 + 결과 저장
├── lib/
│ ├── denoise.py # DeepFilterNet v3 wrapper
│ ├── vad.py # Silero VAD wrapper
│ ├── whisper_lid.py # faster-whisper detect_language wrapper
│ ├── voxlingua_lid.py # SpeechBrain VoxLingua107 wrapper
│ └── bench.py # 4-way 비교 실행 + 결과 출력/저장
└── output/ # 산출물 (gitignore 권장)
├── denoise/
│ └── <stem>.wav # denoise 결과 (48kHz int16) — 입력 wav 1개당 1
├── <stem>.csv # per-segment LID 결과 — 입력 wav 1개당 1
└── timings.csv # 모든 입력 파일의 단계별 처리 시간 통합 1

외부 환경 노트 (git 사용자 대상)

  • 데이터 경로main.pytest_files 는 사내 경로 (/stg/vod/scenemaker/sound_full/*.wav ) 를 하드코딩한 상태. 외부에서 사용 시 본인 환경의 WAV 파일 경로로 교체할 것.

  • 모델 캐시 — Whisper LID 는 HF 캐시(HF_HOME ) 자동 사용, VoxLingua107 은 conf.MODEL_DIR 하위(voxlingua107/ ) 에 SpeechBrain 이 자동 다운로드. 사전 다운로드가 필요하지 않다.

  • GPU — cuda:0 고정. 멀티 GPU 환경에서는 whisper_lid.py /voxlingua_lid.py 의 device 지정을 조정.

3.2 환경 / 모델 / 의존성

환경

  • Python 3.11 (>=3.11,<3.12 — DeepFilterNet 공식 패키지가 3.11까지만 안정 지원)
  • 패키지 관리 uv (.venv + uv.lock )
  • GPU RTX 4090 24GB , cuda:0 단일 사용

의존성 (pyproject.toml )

패키지버전용도
faster-whisper>=1.0Whisper LID (detect_language )
speechbrain>=1.0VoxLingua107 LID
deepfilternet-py312>=0.5.7DeepFilterNet v3 모델
deepfilterlib>=0.5.6DF 런타임 라이브러리
soundfile>=0.13wav 로드
torch>=2.4,<2.9cu128 wheel, 상한은 DF 호환성
torchaudio>=2.4,<2.9동일

torch/torchaudio 상한 <2.9torchaudio.backend.common.AudioMetaData 가 2.9 에서 제거되며 DF 의 import 가 깨지는 문제 회피용. 검증된 조합: torch==2.8.0+cu128 .

모델

모델다운로드 위치식별자
Whisper LID (large-v3-turbo)HF 캐시 (HF_HOME )mobiuslabsgmbh/faster-whisper-large-v3-turbo
VoxLingua107 (ECAPA-TDNN)conf.MODEL_DIR/voxlingua107/speechbrain/lang-id-voxlingua107-ecapa
DeepFilterNet v3pip 패키지 내장init_df() 호출 시 자동
Silero VAD~/.cache/torch/hub/snakers4/silero-vad (torch.hub)

모든 모델은 첫 실행 시 자동 다운로드 (네트워크 필요), 사전 준비 작업 없음.

git 사용자 대상 노트

  • HF_HOME 미설정 시 기본(~/.cache/huggingface/ ) 으로 다운로드된다.
  • conf.MODEL_DIR 는 사내 캐시(/stg/models )로 설정되어 있음. 외부 환경에선 본인 경로로 변경하거나 SpeechBrain 기본 캐시(~/.cache/huggingface/ ) 사용으로 코드 수정.

3.3 실행 방법

# log.py 에서 로그파일 위치 적절히 수정
> .venv/bin/python main.py

4. 결과

4.1 정확도

모든 발화 구간의 언어를 구분하여 가장 정확하게 언어를 구분한 것들에 대한 결과는 아래 URL 에서 자세히 나와 있다.

https://docs.google.com/spreadsheets/d/1zARHI1l5UfJ_pU1VY61xOOtvmteHLZ-QPHjSbRIoZpI/edit?gid=759070170#gid=759070170

간단하게 최종 결과를 이야기 하면

Totalwhisper_rawvoxlingua_rawwhisper_denoisevoxlingua_denoise
baseball.wav10921073102610721020
docu.wav383349330349332
drama.wav314282256279251
entertain.wav502464398438366
hist_drama.wav437411382386363
news.wav387385377384379
Correct31152964276929082711
Accuracy rate10095.288.993.487.0
  • 정확도는 (가장정확) Whisper raw > Whisper denoise > voxlingua raw > voxlingua denoise (가장 부정확) 순서로 나온다.
  • (중요) denoise 를 한다고 해서 언어 구분에서는 좋와 지는 것이 없다.

4.2 비용 (처리시간)

filedurationmodelvaddenoiselidtotaltotal_hour차이
docu.wav00:58:41whisper9.97-20.1330.130.78
(3520.7)voxlingua9.97-3.2613.2313.532.3
whisper9.9710.3920.440.7641.67
voxlingua9.9710.391.9822.3322.841.8
baseball.wav01:55:23whisper19.35-57.7577.140.1
(6922.5)voxlingua19.35-7.6827.0314.062.9
whisper19.3519.558.1897.0350.46
voxlingua19.3519.56.0244.8723.332.2
drama.wav01:04:53whisper10.86-14.9525.8123.87
(3892.8)voxlingua10.86-1.8812.7411.782.0
whisper10.8610.7314.9636.5533.8
voxlingua10.8610.731.6423.2421.491.6
entertain.wav01:00:06whisper9.95-26.1136.0636
(3606.3)voxlingua9.95-3.4513.413.382.7
whisper9.959.9226.2446.1246.04
voxlingua9.959.922.8122.6922.652.0
hist_drama.wav00:54:10whisper9.02-21.5230.5433.83
00:54:10voxlingua9.02-2.4111.4312.662.7
whisper9.029.0221.8539.8944.18
voxlingua9.029.022.120.1422.312.0
news.wav00:48:30whisper7.81-20.5428.3535.07
(2910.3)voxlingua7.81-2.4410.2512.682.8
whisper7.818.1320.8436.7745.48
voxlingua7.818.132.0317.9622.222.0
  • 처리속도 순위: (가장빠름) voxlingua raw > voxlingua denoise > Whisper raw > Whisper denoise (가장느림)