
STT용 배경 소음 제거 방법: 음성-텍스트 변환을 위한 노이즈 감소 완벽 가이드
Eric King
Author
STT용 배경 소음 제거 방법: 음성-텍스트 변환을 위한 노이즈 감소 완벽 가이드
배경 소음은 오디오 녹음을 전사할 때 가장 흔한 문제 중 하나입니다. 교통 소리, 키보드 타이핑, 에어컨 소리, 군중 소음 등 어떤 경우든 음성-텍스트 처리 전에 배경 소음을 제거하면 전사 정확도를 크게 높일 수 있습니다.
이 포괄적인 가이드에서는 간단한 소프트웨어 솔루션부터 고급 오디오 처리 기법까지, STT용 배경 소음 제거를 위한 실용적인 방법을 다룹니다.
STT에서 배경 소음을 제거해야 하는 이유
배경 소음은 여러 방식으로 음성-텍스트 정확도에 부정적인 영향을 줍니다:
- 신호 대 잡음비(SNR) 감소로 인해 모델이 음성을 구분하기 어려워짐
- 소음이 음성 주파수와 겹치는 주파수 마스킹
- 소음 패턴이 음성과 유사할 때 발생하는 모델 혼란
- 신뢰도 점수 하락으로 인한 전사 오류 증가
- 모델이 잡음 입력과 씨름하면서 처리 시간 증가
노이즈 제거의 이점:
- ✅ 전사 정확도 향상(보통 10~30% 개선)
- ✅ 특히 기술 용어에서 더 나은 단어 인식
- ✅ 더 깨끗한 오디오로 더 빠른 처리
- ✅ 더 신뢰할 수 있는 타임스탬프와 세그먼트 분할
- ✅ 작은 음성에 대한 처리 개선
배경 소음 유형 이해하기
소음 유형마다 제거 전략이 다릅니다:
1. 일정한 소음(정상성 소음)
- 예시: 에어컨, 선풍기 웅웅거림, 전기 험(hum), 화이트 노이즈
- 특징: 주파수와 진폭이 일정함
- 제거 방법: 스펙트럼 감산 또는 필터링으로 비교적 쉽게 제거 가능
2. 가변 소음(비정상성 소음)
- 예시: 교통 소음, 군중 대화 소리, 키보드 타이핑, 종이 마찰음
- 특징: 시간에 따라 변하며 패턴 예측이 어려움
- 제거 방법: 딥러닝 모델 같은 더 고급 기법 필요
3. 충격성 소음
- 예시: 클릭, 팝, 문 닫히는 소리, 전화 벨
- 특징: 짧고 갑작스러운 버스트
- 제거 방법: 감지 후 대체/보간 필요
4. 주기성 소음
- 예시: 삐 소리, 알람, 반복되는 소리
- 특징: 특정 주파수에서 규칙적인 패턴
- 제거 방법: 노치 필터로 필터링 가능
방법 1: 오디오 편집 소프트웨어 사용
Audacity (무료, 오픈소스)
Audacity는 내장 노이즈 감소 기능을 갖춘 강력한 무료 오디오 편집기입니다:
단계:
- Audacity에서 오디오 파일 열기
- 소리(음성 없음)만 있는 구간 선택
- Effect → Noise Reduction으로 이동
- Get Noise Profile 클릭
- 오디오 트랙 전체 선택
- 다시 Effect → Noise Reduction으로 이동
- 설정 조정:
- Noise reduction (dB): 12-24 dB (15부터 시작)
- Sensitivity: 6.0 (기본값)
- Frequency smoothing (bands): 3 (기본값)
- OK를 클릭해 적용
모범 사례:
- 0.5~2초 길이의 소음 샘플 사용
- 대표적인 소음을 포함한 구간 선택
- 중간 정도 설정으로 시작해 필요 시 증가
- 전체 트랙에 적용하기 전에 미리 듣기
Adobe Audition
Adobe Audition은 전문가급 노이즈 감소 기능을 제공합니다:
- 오디오 파일 열기
- 소음만 있는 구간 선택
- Effects → Noise Reduction/Restoration → Capture Noise Print로 이동
- 트랙 전체 선택
- **Effects → Noise Reduction/Restoration → Noise Reduction (process)**로 이동
- 조정:
- Noise Reduction: 40-80% (60%부터 시작)
- Reduce by: 6-12 dB
- High Frequency Transition: 4000-8000 Hz
- Apply 클릭
방법 2: Python 오디오 처리 라이브러리
noisereduce 라이브러리 사용
noisereduce 라이브러리는 사용하기 쉬운 노이즈 감소 기능을 제공합니다:import noisereduce as nr
import soundfile as sf
# Load audio file
audio_data, sample_rate = sf.read("noisy_audio.wav")
# Method 1: Stationary noise reduction (for constant noise)
reduced_noise = nr.reduce_noise(
y=audio_data,
sr=sample_rate,
stationary=True,
prop_decrease=0.8 # Reduce noise by 80%
)
# Method 2: Non-stationary noise reduction (for variable noise)
reduced_noise = nr.reduce_noise(
y=audio_data,
sr=sample_rate,
stationary=False,
prop_decrease=0.8
)
# Save cleaned audio
sf.write("cleaned_audio.wav", reduced_noise, sample_rate)
설치:
pip install noisereduce soundfile
librosa를 사용한 스펙트럴 게이팅
import librosa
import numpy as np
import soundfile as sf
def spectral_gate(audio_path, threshold_db=-40):
"""Remove noise using spectral gating."""
# Load audio
y, sr = librosa.load(audio_path, sr=None)
# Compute short-time Fourier transform (STFT)
stft = librosa.stft(y)
magnitude = np.abs(stft)
phase = np.angle(stft)
# Convert to dB
magnitude_db = librosa.amplitude_to_db(magnitude)
# Apply threshold (remove frequencies below threshold)
magnitude_db_cleaned = np.where(
magnitude_db > threshold_db,
magnitude_db,
-80 # Silence very quiet parts
)
# Convert back to linear scale
magnitude_cleaned = librosa.db_to_amplitude(magnitude_db_cleaned)
# Reconstruct audio
stft_cleaned = magnitude_cleaned * np.exp(1j * phase)
y_cleaned = librosa.istft(stft_cleaned)
return y_cleaned, sr
# Usage
cleaned_audio, sample_rate = spectral_gate("noisy_audio.wav", threshold_db=-35)
sf.write("cleaned_audio.wav", cleaned_audio, sample_rate)
scipy를 사용한 하이패스 필터링
저주파 소음(예: 럼블, 바람 소리) 제거:
from scipy import signal
import soundfile as sf
def high_pass_filter(audio_path, cutoff_freq=80):
"""Remove low-frequency noise with high-pass filter."""
# Load audio
audio_data, sample_rate = sf.read(audio_path)
# Design high-pass filter
nyquist = sample_rate / 2
normalized_cutoff = cutoff_freq / nyquist
b, a = signal.butter(4, normalized_cutoff, btype='high')
# Apply filter
filtered_audio = signal.filtfilt(b, a, audio_data)
return filtered_audio, sample_rate
# Usage
cleaned_audio, sr = high_pass_filter("noisy_audio.wav", cutoff_freq=100)
sf.write("cleaned_audio.wav", cleaned_audio, sr)
방법 3: 딥러닝 기반 노이즈 감소
RNNoise 사용
RNNoise는 노이즈 감소를 위해 특별히 설계된 딥러닝 모델입니다:
import rnnoise
import numpy as np
import soundfile as sf
def rnnoise_denoise(audio_path):
"""Remove noise using RNNoise model."""
# Load audio
audio_data, sample_rate = sf.read(audio_path)
# RNNoise expects 16kHz mono audio
if sample_rate != 16000:
import librosa
audio_data = librosa.resample(audio_data, orig_sr=sample_rate, target_sr=16000)
sample_rate = 16000
# Convert to mono if stereo
if len(audio_data.shape) > 1:
audio_data = np.mean(audio_data, axis=1)
# Process in chunks (RNNoise processes 480 samples at a time)
chunk_size = 480
denoised_audio = []
denoiser = rnnoise.RNNoise()
for i in range(0, len(audio_data), chunk_size):
chunk = audio_data[i:i+chunk_size]
if len(chunk) < chunk_size:
chunk = np.pad(chunk, (0, chunk_size - len(chunk)))
denoised_chunk = denoiser.process(chunk)
denoised_audio.extend(denoised_chunk)
return np.array(denoised_audio), sample_rate
# Usage
cleaned_audio, sr = rnnoise_denoise("noisy_audio.wav")
sf.write("cleaned_audio.wav", cleaned_audio, sr)
설치:
pip install rnnoise
Facebook의 Demucs 사용
Demucs는 배경 소음에서 음성을 분리할 수 있습니다:
from demucs.pretrained import get_model
from demucs.audio import AudioFile
import torch
def demucs_separation(audio_path):
"""Separate speech from noise using Demucs."""
# Load pre-trained model
model = get_model('htdemucs')
model.eval()
# Load audio
wav = AudioFile(audio_path).read(streams=0, samplerate=model.sample_rate, channels=model.audio_channels)
ref = wav.mean(0)
wav = (wav - ref.mean()) / ref.std()
wav = torch.from_numpy(wav).float()
# Separate sources
with torch.no_grad():
sources = model(wav[None])
sources = sources * ref.std() + ref.mean()
# Extract vocals (speech) - usually index 0 or 3
speech = sources[0, 0].cpu().numpy()
return speech, model.sample_rate
# Usage
speech_audio, sr = demucs_separation("noisy_audio.wav")
sf.write("speech_only.wav", speech_audio, sr)
방법 4: 온라인 노이즈 감소 도구
1. Audacity Online (클라우드 버전)
- 무료, 브라우저 기반
- 빠른 처리에 적합
- 파일 크기 제한 있음
2. Adobe Podcast Enhance
- AI 기반 노이즈 감소
- 제한된 사용량 내 무료
- 음성에 대해 뛰어난 결과
3. Krisp.ai
- 실시간 소음 억제
- 통합을 위한 API 제공
- 라이브 오디오에 적합
4. Cleanvoice.ai
- 자동 노이즈 제거
- 여러 소음 유형 처리
- 일괄 처리 지원
완전한 워크플로: STT용 오디오 전처리
다음은 여러 기법을 결합한 완전한 Python 스크립트입니다:
import librosa
import noisereduce as nr
import soundfile as sf
from scipy import signal
import numpy as np
def preprocess_audio_for_stt(audio_path, output_path):
"""Complete audio preprocessing pipeline for STT."""
# Step 1: Load audio
print("Loading audio...")
y, sr = librosa.load(audio_path, sr=16000, mono=True)
# Step 2: Remove DC offset
print("Removing DC offset...")
y = y - np.mean(y)
# Step 3: High-pass filter (remove low-frequency noise)
print("Applying high-pass filter...")
nyquist = sr / 2
normalized_cutoff = 80 / nyquist
b, a = signal.butter(4, normalized_cutoff, btype='high')
y = signal.filtfilt(b, a, y)
# Step 4: Normalize volume
print("Normalizing volume...")
max_val = np.max(np.abs(y))
if max_val > 0:
y = y / max_val * 0.95 # Normalize to 95% to avoid clipping
# Step 5: Noise reduction
print("Reducing noise...")
y = nr.reduce_noise(
y=y,
sr=sr,
stationary=False, # Use non-stationary for variable noise
prop_decrease=0.8 # Reduce noise by 80%
)
# Step 6: Final normalization
print("Final normalization...")
max_val = np.max(np.abs(y))
if max_val > 0:
y = y / max_val * 0.95
# Step 7: Save processed audio
print(f"Saving to {output_path}...")
sf.write(output_path, y, sr)
print("Preprocessing complete!")
return y, sr
# Usage
preprocess_audio_for_stt("noisy_recording.wav", "cleaned_for_stt.wav")
노이즈 제거 모범 사례
1. 적절한 방법 선택
- 일정한 소음: 스펙트럼 감산 또는 정상성 노이즈 감소 사용
- 가변 소음: 비정상성 감소 또는 딥러닝 모델 사용
- 충격성 소음: 클릭 제거 또는 보간 사용
- 복합 소음 유형: 여러 기법 결합
2. 음성 품질 보존
- 과도하게 처리하지 않기(아티팩트 유발 가능)
- 중간 수준 노이즈 감소 설정 사용(60~80%)
- 사람 음성의 주파수 범위 보존(80-8000 Hz)
- 자연스러운 음성 특성 유지
3. 테스트 및 반복
- 전체 트랙 적용 전 항상 미리 듣기
- 원본 오디오와 처리 오디오 비교
- 두 버전 모두로 전사 정확도 테스트
- 결과에 따라 설정 조정
4. STT 모델 고려
- 일부 모델(예: Whisper)은 소음을 잘 처리함
- 전처리가 항상 필요한 것은 아님
- 전처리 적용/미적용 모두 테스트
- 더 큰 모델일수록 소음에 강인함
피해야 할 일반적인 실수
❌ 과도하게 공격적인 노이즈 감소
- 음성 주파수를 제거할 수 있음
- 아티팩트와 왜곡 생성
- 음성이 로봇처럼 들리게 됨
❌ 저주파를 너무 많이 제거
- 중요한 음성 성분이 사라질 수 있음
- 음성이 가늘거나 금속성으로 들릴 수 있음
- 자연스러움에 영향
❌ 사용 중인 STT 모델로 테스트하지 않음
- 전처리가 정확도를 높이지 못할 수 있음
- 일부 모델은 원본 오디오에서 더 잘 동작함
- 항상 A/B 테스트 수행
❌ 오디오 형식 무시
- 적절한 샘플레이트 보장(16kHz 권장)
- 가능하면 무손실 포맷 사용
- 이중 압축 피하기
Speech-to-Text와 통합
OpenAI Whisper와 함께 사용
import whisper
import noisereduce as nr
import soundfile as sf
def transcribe_with_noise_reduction(audio_path):
"""Transcribe audio with noise reduction preprocessing."""
# Step 1: Reduce noise
audio_data, sr = sf.read(audio_path)
cleaned_audio = nr.reduce_noise(
y=audio_data,
sr=sr,
stationary=False,
prop_decrease=0.75
)
# Save temporary cleaned file
temp_path = "temp_cleaned.wav"
sf.write(temp_path, cleaned_audio, sr)
# Step 2: Transcribe with Whisper
model = whisper.load_model("base")
result = model.transcribe(temp_path)
# Clean up
import os
os.remove(temp_path)
return result["text"]
# Usage
transcription = transcribe_with_noise_reduction("noisy_audio.wav")
print(transcription)
SayToWords API와 함께 사용
import requests
import noisereduce as nr
import soundfile as sf
def transcribe_with_saytowords(audio_path):
"""Preprocess and transcribe with SayToWords."""
# Preprocess audio
audio_data, sr = sf.read(audio_path)
cleaned_audio = nr.reduce_noise(
y=audio_data,
sr=sr,
stationary=False,
prop_decrease=0.8
)
# Save cleaned audio
cleaned_path = "cleaned_for_api.wav"
sf.write(cleaned_path, cleaned_audio, sr)
# Upload and transcribe
with open(cleaned_path, 'rb') as f:
files = {'file': f}
response = requests.post(
'https://api.saytowords.com/transcribe',
files=files,
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
return response.json()
노이즈 감소 효과 측정
전/후 비교
import librosa
import numpy as np
def measure_snr(audio_path):
"""Estimate signal-to-noise ratio."""
y, sr = librosa.load(audio_path, sr=None)
# Simple SNR estimation
signal_power = np.mean(y ** 2)
noise_floor = np.percentile(np.abs(y), 10) ** 2
snr_db = 10 * np.log10(signal_power / noise_floor) if noise_floor > 0 else 0
return snr_db
# Compare before and after
original_snr = measure_snr("noisy_audio.wav")
cleaned_snr = measure_snr("cleaned_audio.wav")
print(f"Original SNR: {original_snr:.2f} dB")
print(f"Cleaned SNR: {cleaned_snr:.2f} dB")
print(f"Improvement: {cleaned_snr - original_snr:.2f} dB")
결론
음성-텍스트 처리 전에 배경 소음을 제거하면 전사 정확도를 크게 향상시킬 수 있습니다. 최적의 접근 방식은 다음에 따라 달라집니다:
- 소음 유형 (일정 vs. 가변)
- 오디오 품질 (샘플레이트, 비트 깊이)
- 사용 가능한 도구 (소프트웨어 vs. 프로그래밍)
- STT 모델 (일부는 다른 모델보다 소음을 더 잘 처리함)
빠른 권장 사항:
- 빠른 처리가 필요하면: Audacity 또는 온라인 도구 사용
- 자동화가 필요하면:
noisereduce같은 Python 라이브러리 사용 - 최고의 결과가 필요하면: 여러 기법 결합
- 프로덕션 환경이라면: 사용하는 STT 모델로 반드시 테스트
기억하세요: 모든 오디오에 전처리가 필요한 것은 아닙니다. Whisper 같은 최신 STT 모델은 소음에 꽤 강인합니다. 특정 사용 사례에서 어떤 방식이 더 나은지 확인하려면 원본 오디오와 처리된 오디오를 모두 테스트하세요.
추가 리소스
특정 오디오의 노이즈 감소에 도움이 필요하신가요? 내장 노이즈 처리 및 전처리 옵션이 포함된 SayToWords Speech-to-Text를 사용해 보세요.