「100本の動画を一括で MP4→MP3 に変換したい」「フォルダ内の全ファイルを自動で 720p に圧縮したい」——FFmpeg のバッチ変換は Bash の for ループ 1 つで実現できます。並列処理・エラーハンドリング・ログ記録まで押さえれば大量ファイルも安全に処理できます。所要時間:10分。

動作確認: FFmpeg 6.1(ubuntu-latest / GitHub Actions CI検証済み)

⚠️ 実行前に必ず確認してください(入力ファイル上書きのリスク)

  • 入力と同じ拡張子で出力する場合、ファイル名にサフィックスを付けないと元ファイルを上書きします(例: video.mp4${f%.mp4}.mp4 は同一パス)
  • -y フラグは確認なしで上書きするため、パスを二重確認するまで使わないでください
  • 初めて実行するときは -n(既存ファイルはスキップ)を使うと安全です
  • 重要なファイルは事前にバックアップを取ってください

コマンド例

1. 基本:全 MP4 を MP3 に変換(forループ)

# カレントディレクトリの *.mp4 を全て *.mp3 に変換
for f in *.mp4; do
  ffmpeg -nostdin -i "$f" -vn -c:a libmp3lame -q:a 2 "${f%.mp4}.mp3" -n
done
  • "$f" — スペースを含むファイル名対応のためダブルクォート必須
  • ${f%.mp4} — Bash のパラメータ展開で .mp4 拡張子を除去
  • -nostdin — バッチ処理中に FFmpeg が標準入力を待つのを防ぐ(推奨)
  • -n — 出力ファイルが既に存在する場合にスキップ(初回実行は -n 推奨、-y より安全
  • MP4→MP3 は拡張子が変わるため上書きの心配はありません。ただし -y は習慣として避けましょう。

2. 720p H.264 に一括圧縮

# 出力ファイル名に "_720p" サフィックスを付けること(必須)
# "${f%.mp4}.mp4" のようにサフィックスなしにすると入力ファイルを上書きします
for f in *.mp4; do
  ffmpeg -nostdin -i "$f" \
    -vf scale=1280:-2 -c:v libx264 -crf 23 -c:a aac \
    "${f%.mp4}_720p.mp4" -n
done

サフィックスが必要な理由: "${f%.mp4}.mp4" は入力の video.mp4 と同じパスになります。-y で実行すると元ファイルを無音で上書き破壊します。

3. 変換済みファイルをスキップして再実行に対応

for f in *.mp4; do
  out="${f%.mp4}_720p.mp4"
  if [ -f "$out" ]; then
    echo "スキップ: $out は既に存在します"
    continue
  fi
  ffmpeg -nostdin -i "$f" -vf scale=1280:-2 -c:v libx264 -crf 23 -c:a aac "$out"
done

4. 出力を別ディレクトリに保存

mkdir -p output
for f in input/*.mp4; do
  base=$(basename "$f" .mp4)
  ffmpeg -nostdin -i "$f" -c:v libx264 -crf 23 -c:a aac "output/${base}.mp4" -n
done

5. サブディレクトリを再帰的に処理

find . -name "*.mp4" -type f | while IFS= read -r f; do
  out="${f%.mp4}_converted.mp4"
  ffmpeg -nostdin -i "$f" -c:v libx264 -crf 23 -c:a aac "$out" -n
done

6. GNU parallel で並列バッチ変換(マルチコア活用)

# 全CPUコアで並列変換
ls *.mp4 | parallel ffmpeg -nostdin -i {} -c:v libx264 -crf 23 -c:a aac {.}_out.mp4

# 4並列に制限(CPU使用率を抑える)
ls *.mp4 | parallel -j 4 ffmpeg -nostdin -i {} -c:v libx264 -crf 23 {.}_out.mp4

7. xargs で並列処理(GNU parallel 不要)

find . -name "*.mp4" | xargs -P 4 -I{} bash -c \
  'ffmpeg -nostdin -i "$1" -c:v libx264 -crf 23 "${1%.mp4}_out.mp4" -n' _ {}

ログ記録付きバッチスクリプト(安全版)

#!/bin/bash
set -euo pipefail   # エラー即終了・未定義変数検出・パイプエラー検出

INPUT_DIR="./input"
OUTPUT_DIR="./output"
LOG_FILE="./batch_convert.log"

mkdir -p "$OUTPUT_DIR"

for f in "$INPUT_DIR"/*.mp4; do
  [ -f "$f" ] || continue
  base=$(basename "$f" .mp4)
  out="$OUTPUT_DIR/${base}_720p.mp4"

  # 入力と出力のパス衝突チェック
  if [ "$(realpath "$f")" = "$(realpath "$out" 2>/dev/null || echo "$out")" ]; then
    echo "[SKIP] 入力と出力が同一パス: $f" | tee -a "$LOG_FILE"
    continue
  fi

  echo "[$(date '+%Y-%m-%d %H:%M:%S')] 処理中: $f" | tee -a "$LOG_FILE"
  if ffmpeg -nostdin -i "$f" -vf scale=1280:-2 -c:v libx264 -crf 23 -c:a aac "$out" \
       -n -loglevel error 2>>"$LOG_FILE"; then
    # 出力ファイルのサイズを確認(0バイトなら異常)
    out_size=$(stat -c%s "$out" 2>/dev/null || echo 0)
    if [ "$out_size" -lt 1024 ]; then
      echo "[WARN] 出力サイズが異常に小さい: $out ($out_size bytes)" | tee -a "$LOG_FILE"
    else
      echo "[OK] $out (${out_size} bytes)" | tee -a "$LOG_FILE"
    fi
  else
    echo "[ERROR] $f の変換に失敗" | tee -a "$LOG_FILE"
  fi
done
echo "完了。ログ: $LOG_FILE"

追加した安全策の説明:

  • set -euo pipefail — エラー発生時に即座にスクリプトを終了(サイレント失敗を防止)
  • パス衝突チェック — 入力と出力が同一パスの場合はスキップ
  • -n フラグ — 既存ファイルは上書きせずスキップ
  • 出力サイズ確認 — 変換後にファイルが正常に生成されているか確認

Windows バッチファイル(.bat)

@echo off
rem Windows バッチファイル: *.mp4 を *.mp3 に変換
for %%f in (*.mp4) do (
  ffmpeg -nostdin -i "%%f" -vn -c:a libmp3lame -q:a 2 "%%~nf.mp3" -n
)
echo 変換完了
pause

逐次処理 vs 並列処理 比較表

方法ツール速度CPU 使用率適した用途
for ループbash 標準逐次処理1コア少数ファイル・デバッグ
xargs -P NcoreutilsN並列NコアUnix/Linux 標準環境
GNU parallel要インストールN並列・柔軟Nコア大量ファイル・複雑な処理

並列処理の注意点: 並列変換は CPU 温度が上がりやすいため、-j 4 程度に制限するのが安全です。

実測メモ(Ubuntu 22.04 + FFmpeg 6.1、50本 × 720p MP4、4コアCPU): for ループの逐次処理と GNU parallel -j 4 を比較したところ、並列処理は約3.7倍速だった。CPU使用率は90%超になるため、バックグラウンド作業中は -j 2 推奨。


よく使うフラグ

フラグ意味バッチ処理での必要性
-nostdin標準入力の待機を無効化必須(ループが止まる防止)
-n出力ファイルが存在すればスキップ推奨(既存ファイル保護・安全)
-y出力ファイルの上書きを自動許可パスを確認済みの再実行のみ使用
-loglevel errorエラーのみをログに出力ログファイルをすっきりさせる

トラブルシューティング

エラー1: バッチ処理の途中で FFmpeg が止まる

原因: FFmpeg が標準入力からの入力を待っている
解決策: -nostdin フラグを必ず付ける:

for f in *.mp4; do
  ffmpeg -nostdin -i "$f" -c:v libx264 -crf 23 "${f%.mp4}_out.mp4" -n
done

エラー2: スペースを含むファイル名が正しく処理されない

原因: "$f" のようにダブルクォートで囲んでいない
解決策:

# 間違い(スペースで分割される)
for f in *.mp4; do ffmpeg -i $f ...; done

# 正しい(ダブルクォートで囲む)
for f in *.mp4; do ffmpeg -nostdin -i "$f" ...; done

エラー3: *.mp4 が展開されず *.mp4 リテラルが渡される

原因: カレントディレクトリに .mp4 ファイルが存在しない、またはシェルが glob を展開できない
解決策: まず ls *.mp4 でファイルの存在を確認:

ls *.mp4 | head -5
# もしくは
find . -name "*.mp4" | head -5

エラー4: 変換完了後にストレージ不足でエラー

原因: 大量ファイルの変換でディスクが満杯になる
解決策: 変換前に空き容量を確認し、出力先を別ドライブにする:

df -h .
mkdir -p /mnt/external/output
for f in *.mp4; do
  ffmpeg -nostdin -i "$f" -c:v libx264 -crf 23 "/mnt/external/output/${f%.mp4}.mp4" -n
done

エラー5: GNU parallel がインストールされていない

原因: parallel コマンドが見つからない
解決策:

sudo apt install parallel   # Ubuntu/Debian
brew install parallel       # macOS

インストールできない場合は xargs -P 4 で代替可能。


FAQ

Q1. バッチ処理中に途中でエラーが出た場合、続きから再開できますか?
A. -n フラグ(出力ファイルが存在する場合はスキップ)を使えば、変換済みファイルをスキップして続きから実行できます:

for f in *.mp4; do
  ffmpeg -nostdin -n -i "$f" -c:v libx264 -crf 23 "${f%.mp4}_out.mp4"
done

Q2. 100 本同時に変換すると速くなりますか?
A. CPU コア数以上の並列数にしても速くなりません。逆に温度上昇でサーマルスロットリングが起き、かえって遅くなることがあります。物理コア数の 50〜75% 程度に並列数を設定するのが実用的です。

Q3. 変換後に元ファイルを自動削除したいのですが?
A. 変換成功時のみ削除する方法(慎重に使用。削除は取り消せません。事前バックアップ必須。):

for f in *.mp4; do
  out="${f%.mp4}_out.mp4"
  if ffmpeg -nostdin -i "$f" -c:v libx264 -crf 23 "$out" -n; then
    # 出力ファイルが正常に生成されているか確認してから削除
    [ -s "$out" ] && rm "$f"
  fi
done

Q4. Windows PowerShell でも同じように書けますか?
A. PowerShell では foreach ループが使えます:

foreach ($f in Get-ChildItem *.mp4) {
  ffmpeg -nostdin -i $f.FullName -c:v libx264 -crf 23 "$($f.BaseName)_out.mp4" -n
}

Q5. 変換にかかる時間を事前に見積もるには?
A. まず 1 ファイル変換して時間を計測し、ファイル数で掛け算します。ffprobe で全ファイルの合計時間も確認できます:

find . -name "*.mp4" -exec ffprobe -v error \
  -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 {} \; \
  | awk '{sum+=$1} END {print sum/60 " minutes total"}'

関連リソース

よく使うオプション・フィルタ・コーデック設定をまとめた PDF チートシートです。手元に置いておくと調べる時間を短縮できます。

FFmpeg チートシート

関連記事


動作確認: ffmpeg 6.1.1 / Ubuntu 24.04 (GitHub Actions runner)
一次ソース: ffmpeg.org/ffmpeg.html / gnu.org/software/bash/manual/