
STTのための背景ノイズ除去方法:音声テキスト変換向けノイズリダクション完全ガイド
Eric King
Author
STTのための背景ノイズ除去方法:音声テキスト変換向けノイズリダクション完全ガイド
背景ノイズは、音声録音を文字起こしする際に最もよくある課題の1つです。交通音、キーボードの打鍵音、エアコンの音、群衆ノイズなど、どのようなノイズであっても、音声テキスト変換を行う前に背景ノイズを除去することで文字起こし精度を大幅に改善できます。
この包括的なガイドでは、シンプルなソフトウェアによる解決策から高度な音声処理技術まで、STT向けの背景ノイズ除去を実践する方法を紹介します。
なぜSTTのために背景ノイズを除去するのか?
背景ノイズは、以下のような形で音声テキスト変換の精度に悪影響を与えます。
- 信号対雑音比(SNR)の低下により、モデルが音声を識別しにくくなる
- ノイズが音声周波数帯と重なる周波数マスキングが発生する
- ノイズパターンを音声と誤認することによるモデルの混乱
- 信頼度スコアの低下により、文字起こしエラーが増える
- ノイズの多い入力にモデルが苦戦し、処理時間が増加する
ノイズ除去のメリット:
- ✅ 文字起こし精度の向上(多くの場合10〜30%改善)
- ✅ 特に専門用語の単語認識が向上
- ✅ よりクリーンな音声による高速処理
- ✅ タイムスタンプとセグメンテーションの信頼性向上
- ✅ 小さな声への対応力向上
背景ノイズの種類を理解する
ノイズの種類によって、適した除去戦略は異なります。
1. 定常ノイズ(Stationary)
- 例: エアコン、ファンのうなり、電気的ハムノイズ、ホワイトノイズ
- 特徴: 周波数と振幅が一定
- 除去: スペクトル減算やフィルタリングで比較的除去しやすい
2. 変動ノイズ(Non-Stationary)
- 例: 交通音、ざわめき、キーボード打鍵音、紙のこすれ音
- 特徴: 時間とともに変化し、パターンが予測しにくい
- 除去: 深層学習モデルなど、より高度な技術が必要
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()
ノイズ低減効果の測定
Before/After比較
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")
まとめ
音声テキスト変換の前に背景ノイズを除去すると、文字起こし精度を大きく向上できます。最適なアプローチは次の要素によって決まります。
- ノイズの種類(定常か変動か)
- 音声品質(サンプルレート、ビット深度)
- 利用可能なツール(ソフトウェアかプログラミングか)
- STTモデル(モデルによってノイズ耐性が異なる)
すぐ使える推奨:
- 手早く処理したい場合: Audacityやオンラインツールを使う
- 自動化したい場合:
noisereduceのようなPythonライブラリを使う - 最高の結果を狙う場合: 複数手法を組み合わせる
- 本番運用の場合: 自分のSTTモデルで必ず検証する
覚えておきたいのは、すべての音声で前処理が必要なわけではないという点です。Whisperのような最新STTモデルはノイズにかなり強いことがあります。必ず元音声と処理後音声の両方を試し、あなたの用途でどちらが良い結果かを確認してください。
追加リソース
お使いの音声に合わせたノイズリダクションでお困りですか? ノイズ処理と前処理オプションを内蔵した SayToWords Speech-to-Text をお試しください。