0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで音声ファイルの無音区間を検出して自動カットする

0
Last updated at Posted at 2026-10-24

ポッドキャストや講義録音を編集していると、話していない無音区間を手作業で削除する作業が意外と時間を使います。特に録音時間が長くなるほど、無音の確認とカットを繰り返すのは大変です。

今回は、Pythonのpydubを使って音声ファイルの無音区間を検出し、発話部分だけをつないだ音声ファイルを作成します。

実際に試したところ、無音判定のしきい値と無音の最小継続時間を調整するだけで、短い間や環境音を残しつつ、長い無音を自動的に削除できました。

使用するライブラリと準備

pydubは音声の読み込み、切り出し、結合、書き出しを扱えるライブラリです。ただし、MP3やM4Aなどを扱う場合は内部でffmpegを使用します。

まずPythonパッケージをインストールします。

python -m pip install pydub

Windowsの場合は、別途ffmpegをインストールしてPATHを通しておきます。インストール後、次のコマンドで確認できます。

ffmpeg -version

今回のサンプルでは、同じフォルダにinput.mp3を置き、処理結果をoutput.mp3として保存します。

無音区間を検出する

音声ファイルを読み込み、発話部分だけを抽出して書き出すまでの流れは次の通りです。

pydub.silenceには、無音区間を検出するための関数が用意されています。

  • detect_silence: 無音区間を返す
  • detect_nonsilent: 無音ではない区間を返す

今回は、発話部分の範囲を直接取得できるdetect_nonsilentを使います。

from pydub import AudioSegment
from pydub.silence import detect_nonsilent

audio = AudioSegment.from_file("input.mp3")

nonsilent_ranges = detect_nonsilent(
    audio,
    min_silence_len=800,
    silence_thresh=-40,
    seek_step=10,
)

for start_ms, end_ms in nonsilent_ranges:
    print(f"{start_ms / 1000:.2f}s - {end_ms / 1000:.2f}s")

pydubの時間単位はミリ秒です。例えば800は「800ミリ秒以上続いた区間を無音として扱う」という意味になります。

silece_threshでは、音量をデシベルで指定します。-40dBFSの場合、これより小さい音を無音と判定します。録音環境によっては、エアコンの音やマイクのノイズがあるため、無音でも完全に音量が0になるとは限りません。

発話部分だけを結合して書き出す

検出した範囲を順番に切り出し、+演算子で結合します。

from pydub import AudioSegment
from pydub.silence import detect_nonsilent

input_path = "input.mp3"
output_path = "output.mp3"

audio = AudioSegment.from_file(input_path)

nonsilent_ranges = detect_nonsilent(
    audio,
    min_silence_len=800,
    silence_thresh=-40,
    seek_step=10,
)

if not nonsilent_ranges:
    raise ValueError("発話部分を検出できませんでした。設定を見直してください。")

result = AudioSegment.empty()

for start_ms, end_ms in nonsilent_ranges:
    result += audio[start_ms:end_ms]

result.export(output_path, format="mp3", bitrate="192k")

print(f"入力: {len(audio) / 1000:.2f}秒")
print(f"出力: {len(result) / 1000:.2f}秒")
print(f"保存先: {output_path}")

この処理では、先頭、途中、末尾にある無音だけでなく、会話の間にある無音も削除されます。例えば「こんにちは」と「今日は晴れです」の間に1秒以上の無音がある場合、その区間は取り除かれます。

ただし、無音を完全に削除すると、話し方が不自然になることがあります。そこで、発話区間の前後に少しだけ無音を残す方法を使います。

from pydub import AudioSegment
from pydub.silence import detect_nonsilent

audio = AudioSegment.from_file("input.mp3")

nonsilent_ranges = detect_nonsilent(
    audio,
    min_silence_len=800,
    silence_thresh=-40,
    seek_step=10,
)

keep_silence = 120
result = AudioSegment.empty()

for start_ms, end_ms in nonsilent_ranges:
    start_ms = max(0, start_ms - keep_silence)
    end_ms = min(len(audio), end_ms + keep_silence)
    result += audio[start_ms:end_ms]

result.export("output_with_padding.mp3", format="mp3", bitrate="192k")

keep_silence=120とすると、各発話の前後に最大120ミリ秒の余白を残します。短い間を残せるため、完全に詰め込んだような音声になりにくくなります。

パラメータを調整する

無音検出の結果は、録音環境によって変わります。私が試した範囲では、次の3つを調整するのが効果的でした。

min_silence_len

無音と判定する最小時間です。

min_silence_len=500

短くすると、短い間も削除対象になります。会話の自然な間まで消える場合は、1000や1500に上げます。

silence_thresh

無音と判定する音量のしきい値です。

silence_thresh=-35

周囲のノイズが大きい場合は、-40では無音を検出しにくいことがあります。その場合は-35のように、しきい値を上げて試します。

逆に、声の小さい部分まで削除される場合は、-45などに下げます。

seek_step

音量を確認する間隔です。

seek_step=10

小さいほど細かく検出できますが、処理時間は長くなります。通常の音声編集であれば、10〜20ミリ秒程度で十分でした。

フォルダ内の音声をまとめて処理する

同じ処理を複数ファイルに適用する場合は、pathlibと組み合わせます。

from pathlib import Path

from pydub import AudioSegment
from pydub.silence import detect_nonsilent

input_dir = Path("input_audio")
output_dir = Path("output_audio")
output_dir.mkdir(exist_ok=True)

for input_path in input_dir.glob("*.mp3"):
    audio = AudioSegment.from_file(input_path)

    ranges = detect_nonsilent(
        audio,
        min_silence_len=800,
        silence_thresh=-40,
        seek_step=10,
    )

    if not ranges:
        print(f"スキップ: {input_path.name}")
        continue

    result = AudioSegment.empty()

    for start_ms, end_ms in ranges:
        start_ms = max(0, start_ms - 120)
        end_ms = min(len(audio), end_ms + 120)
        result += audio[start_ms:end_ms]

    output_path = output_dir / f"{input_path.stem}_trimmed.mp3"
    result.export(output_path, format="mp3", bitrate="192k")
    print(f"完了: {output_path}")

入力用のinput_audioフォルダにMP3を置いて実行すると、処理済みファイルがoutput_audioに保存されます。

まとめ

pydubのdetect_nonsilentを使うと、音声ファイルから発話部分を検出し、無音区間を自動的に削除できます。

基本的な流れは次の通りです。

  1. AudioSegment.from_fileで音声を読み込む
  2. detect_nonsilentで発話区間を検出する
  3. 検出範囲を切り出して結合する
  4. exportで音声ファイルを書き出す

最初はmin_silence_len=800、silence_thresh=-40、keep_silence=120あたりから試し、実際の録音を聞きながら調整するのがおすすめです。完全自動にするより、最後に一度だけ出力音声を確認する運用にすると、自然さと作業効率のバランスを取りやすくなります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?