【保存版】YouTube動画の音量バラつきを“業界標準”に正規化する完全ガイド(Windows+FFmpeg+初心者向け)
- 🎯 この記事で得られること
- 🔍 そもそも最初に動画を確認しなくていいの?
- 📊 音量正規化の3つの主要パラメータを理解しよう
- 🎯 なぜ「I=-14, TP=-1.5, LRA=11」がベストな初期設定か?
- 🧪 応用Tips:処理不要な動画をスキップするには?
- 📁 ファイル自動処理時のベストプラクティス
- 🔁 まとめ:音量正規化で得られる最大のメリット
- 📥 次のステップ:2パス精密処理スクリプトを自動化しよう
- 📜 スクリプト全体像
- 🗂 フォルダ構成イメージ
- 💬 ポイント解説
- 🚀 次の拡張提案
- 🎯 ゴール
- ① 事前準備:必要なもの
- ② ステップ1:Pythonインストール
- ③ ステップ2:ffmpegインストール
- ④ ステップ3:ツールを実行する
🎯 この記事で得られること
- 音量がバラバラな動画を、プロ品質で安定・自動的に最適化する方法
- LUFS、TP、LRAなどの意味と、業界で推奨される「音量の基準値」
- 実用性と再現性を兼ね備えたFFmpegバッチスクリプト
- 初心者でも実践できる、自動化・省力化の構成
🔍 そもそも最初に動画を確認しなくていいの?
はい、動画の音量状況を事前に確認することは、非常に重要です。
理由は以下の通り:
- 音源によってはすでに適切なラウドネス(例:-14 LUFS前後)に調整されている場合がある
- ラウドネスレンジ(LRA)が極端に狭い/広い動画は、過度な処理で音が不自然になる可能性がある
- 一律処理=最適ではない → 事前確認により「処理不要 or 軽処理」に分岐できる
✅ 事前確認用コマンド(解析のみ)
ffmpeg -i input.mp4 -af loudnorm=I=-14:TP=-1.5:LRA=11:print_format=summary -f null -
この出力を使って、以下の指標を把握します。
📊 音量正規化の3つの主要パラメータを理解しよう
① I
:Integrated Loudness(統合ラウドネス)
- 人間が感じる“平均音量”に近い値
- 単位:LUFS(Loudness Units relative to Full Scale)
- 基準値:
- YouTube・Spotify:-14 LUFS
- テレビ(放送基準):-23 LUFS
- ポッドキャスト:-16〜-18 LUFS
✅ YouTube動画・配信者なら -14 LUFS が標準
② TP
:True Peak(真のピーク)
- デジタル波形の最高点。スピーカーや再生環境でクリッピング(音割れ)を防ぐための保護値
- 単位:dBTP(デシベル・トゥルーピーク)
- 通常の上限:-1.0dBTP〜-2.0dBTP
✅ -1.5dBTPは、音質と安全性のバランスが取れた推奨設定
③ LRA
:Loudness Range(音量のばらつき幅)
- 映画などで必要な“ダイナミックさ”と、ポッドキャストやゲーム実況で必要な“安定感”を調整する指標
- 単位:LU(Loudness Units)
- 推奨値:
- 会話中心(配信・実況):6〜12 LU
- 映画・ドラマ(抑揚重視):>12 LU
✅ LRA=11 は、バラつきすぎず自然さも維持できる中間値。YouTube用途に非常に適しています。
🎯 なぜ「I=-14, TP=-1.5, LRA=11」がベストな初期設定か?
パラメータ | 推奨値 | 理由 |
---|---|---|
I | -14 LUFS | YouTube/Spotify等ストリーミング最適化、聴きやすさ重視 |
TP | -1.5 dBTP | クリッピング防止、音質確保、安全性の両立 |
LRA | 11 LU | 自然さと安定感のバランス、会話メインにも対応可能 |
🎧「ゲーム実況」「教育コンテンツ」「BGM付き解説」など、多くのジャンルで最も無難かつ汎用的な設定。
🧪 応用Tips:処理不要な動画をスキップするには?
if measured_I > -14.5 and measured_I < -13.5 and measured_TP < -1.0 (
skip normalization
)
このように閾値を設ければ、「すでに適正音量な動画」は無処理でスキップ可能。
再処理を防ぎ、時間と品質を両立します(=最大効率化)。
📁 ファイル自動処理時のベストプラクティス
- 音声処理は「一発出力より2パス(解析→補正)」が精度高
- 元動画は必ずバックアップ!
- 処理後の出力ファイル名に
_normalized
をつけることで混在回避 - LUFS測定結果をログとして保存すると後からレビューしやすい
🔁 まとめ:音量正規化で得られる最大のメリット
- 視聴者に「次の動画だけ音がデカい/小さい」と思われない
- 再生環境に左右されにくいプロ品質
- 収益化チャンネルにおいて、離脱率低下・視聴完了率UP
- スクリプト化により、今後の作業時間ゼロ化が可能(自動化ROI最大)
📥 次のステップ:2パス精密処理スクリプトを自動化しよう
🎯【要件整理】
項目 | 内容 |
---|---|
入力 | 指定したフォルダ配下すべての.mp4ファイル(サブフォルダ含めてもOK) |
処理 | – 音量解析(ffmpeg loudnorm)- 目標値(I=-14 LUFS、TP=-1.5dB、LRA=11)に対して → 【変換が必要なら】正規化して出力 → 【変換不要なら】コピーだけ |
出力 | 指定した出力フォルダ(元ファイルには一切上書きしない) |
ログ | 処理結果(LUFS、TP、LRA)をJSONまたはテキストで保存 |
その他 | GUIから入力フォルダ・出力フォルダを指定可能(Tkinter簡易アプリ版も対応可) |
これを踏まえた上で、
まずは**CLI版(Pythonスクリプト)**から実装します。 (その後、GUI版にもすぐ拡張できる構成にします)
🛠 Pythonスクリプト(v1 CLI版)
動作環境:
- Windows 11
- ffmpegがインストール済み(パスが通っている)
- Python 3.10以上推奨(標準ライブラリのみ使用)
📜 スクリプト全体像
import os
import subprocess
import json
import shutil
from pathlib import Path
# ==============================
# 設定項目(ここだけ変える)
# ==============================
INPUT_DIR = r'C:\path\to\input'
OUTPUT_DIR = r'C:\path\to\output'
TARGET_I = -14.0 # LUFS
TARGET_TP = -1.5 # dBTP
TARGET_LRA = 11.0 # LU
# 変換をスキップする許容誤差
I_TOLERANCE = 0.5 # LUFS
TP_TOLERANCE = 0.5 # dBTP
# ==============================
def analyze_audio(file_path):
"""ffmpegでloudnorm解析(1パス目)"""
command = [
"ffmpeg", "-i", str(file_path),
"-af", f"loudnorm=I={TARGET_I}:TP={TARGET_TP}:LRA={TARGET_LRA}:print_format=json",
"-f", "null", "-"
]
result = subprocess.run(command, capture_output=True, text=True)
# JSON部分だけ抜き出す
output_lines = result.stderr.split('\n')
json_data = ''
in_json = False
for line in output_lines:
if '{' in line:
in_json = True
if in_json:
json_data += line
if '}' in line and in_json:
break
return json.loads(json_data)
def needs_normalization(data):
"""変換が必要かどうかを判定"""
input_i = float(data.get('input_i', 0))
input_tp = float(data.get('input_tp', 0))
if abs(input_i - TARGET_I) > I_TOLERANCE or input_tp > (TARGET_TP + TP_TOLERANCE):
return True
return False
def normalize_audio(input_file, output_file, measured_data):
"""2パス式で正規化変換"""
measured_I = measured_data['input_i']
measured_TP = measured_data['input_tp']
measured_LRA = measured_data['input_lra']
offset = measured_data['target_offset']
command = [
"ffmpeg", "-i", str(input_file),
"-af", (
f"loudnorm=I={TARGET_I}:TP={TARGET_TP}:LRA={TARGET_LRA}:"
f"measured_I={measured_I}:measured_TP={measured_TP}:measured_LRA={measured_LRA}:"
f"offset={offset}:linear=true:print_format=summary"
),
"-c:v", "copy", # 映像はコピー
str(output_file)
]
subprocess.run(command, check=True)
def process_videos(input_dir, output_dir):
"""メイン処理"""
input_dir = Path(input_dir)
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
for file_path in input_dir.rglob('*.mp4'):
print(f"▶ 処理中: {file_path.name}")
out_file_path = output_dir / file_path.name
log_file_path = output_dir / (file_path.stem + "_loudness.json")
# 音量解析
loudness_data = analyze_audio(file_path)
with open(log_file_path, 'w', encoding='utf-8') as f:
json.dump(loudness_data, f, indent=2, ensure_ascii=False)
if needs_normalization(loudness_data):
print(f" → 音量補正が必要、変換します")
normalize_audio(file_path, out_file_path, loudness_data)
else:
print(f" → 音量適正、コピーのみ")
shutil.copy2(file_path, out_file_path)
print("\n✅ 全処理が完了しました!")
if __name__ == "__main__":
process_videos(INPUT_DIR, OUTPUT_DIR)
🗂 フォルダ構成イメージ
C:\path\to\input\
├─ video1.mp4
├─ video2.mp4
└─ subfolder\
└─ video3.mp4
C:\path\to\output\
├─ video1.mp4
├─ video2.mp4
├─ video3.mp4
├─ video1_loudness.json
├─ video2_loudness.json
└─ video3_loudness.json
💬 ポイント解説
- rglob():サブフォルダも含めた.mp4一括検索
- 2パス処理:正確なラウドネス補正を実現
- 劣化なし:映像は再エンコードせずコピー(
-c:v copy
) - ログ保存:音量解析の結果を残して後から検証可能
- 変換不要でもコピー:すべてoutputフォルダに集約される
🚀 次の拡張提案
- TkinterでGUI化
- 並列処理対応(大量ファイル向けに速度アップ)
- LRAの自動最適化オプション追加(例えば教育動画用にLRAを絞る)
- 処理進捗バー表示(ユーザー体験向上)
具体的には:
- 見た目に軽くグラデーション or 柔らかい色味
- 入力と出力フォルダを直感的に選べるボタン
- 処理進行中はプログレスバー表示
- 完了時にはポップアップ通知で知らせる
こんな雰囲気を目指して設計します!
✨【仕様まとめ】Tkinter版 おしゃれGUIアプリ
項目 | 内容 |
---|---|
フォルダ指定 | – 入力ディレクトリ選択ボタン- 出力ディレクトリ選択ボタン |
処理開始 | スタートボタン(押すと解析&正規化開始) |
進捗表示 | プログレスバー |
完了通知 | メッセージボックス |
ログ出力 | 各ファイルのloudness JSONを出力 |
その他 | 入力/出力パスは画面に表示される |
🖥 GUIイメージ(ラフ)
--------------------------------------------
音量最適化ツール🎵(おしゃれ版)
入力フォルダ: [選択ボタン] (パス表示)
出力フォルダ: [選択ボタン] (パス表示)
[処理開始ボタン]
[■■■■□□□□□□](進捗バー)
--------------------------------------------
🛠【Python Tkinter版スクリプト】(プロトタイプ v1)
import os
import subprocess
import json
import shutil
import threading
from pathlib import Path
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
# ==============================
# 設定(目標ラウドネス)
# ==============================
TARGET_I = -14.0
TARGET_TP = -1.5
TARGET_LRA = 11.0
I_TOLERANCE = 0.5
TP_TOLERANCE = 0.5
# ==============================
def analyze_audio(file_path):
command = [
"ffmpeg", "-i", str(file_path),
"-af", f"loudnorm=I={TARGET_I}:TP={TARGET_TP}:LRA={TARGET_LRA}:print_format=json",
"-f", "null", "-"
]
result = subprocess.run(command, capture_output=True, text=True)
output_lines = result.stderr.split('\n')
json_data = ''
in_json = False
for line in output_lines:
if '{' in line:
in_json = True
if in_json:
json_data += line
if '}' in line and in_json:
break
return json.loads(json_data)
def needs_normalization(data):
input_i = float(data.get('input_i', 0))
input_tp = float(data.get('input_tp', 0))
if abs(input_i - TARGET_I) > I_TOLERANCE or input_tp > (TARGET_TP + TP_TOLERANCE):
return True
return False
def normalize_audio(input_file, output_file, measured_data):
measured_I = measured_data['input_i']
measured_TP = measured_data['input_tp']
measured_LRA = measured_data['input_lra']
offset = measured_data['target_offset']
command = [
"ffmpeg", "-i", str(input_file),
"-af", (
f"loudnorm=I={TARGET_I}:TP={TARGET_TP}:LRA={TARGET_LRA}:"
f"measured_I={measured_I}:measured_TP={measured_TP}:measured_LRA={measured_LRA}:"
f"offset={offset}:linear=true:print_format=summary"
),
"-c:v", "copy",
str(output_file)
]
subprocess.run(command, check=True)
def process_videos(input_dir, output_dir, progress_callback):
input_dir = Path(input_dir)
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
files = list(input_dir.rglob('*.mp4'))
total_files = len(files)
for idx, file_path in enumerate(files, start=1):
out_file_path = output_dir / file_path.name
log_file_path = output_dir / (file_path.stem + "_loudness.json")
loudness_data = analyze_audio(file_path)
with open(log_file_path, 'w', encoding='utf-8') as f:
json.dump(loudness_data, f, indent=2, ensure_ascii=False)
if needs_normalization(loudness_data):
normalize_audio(file_path, out_file_path, loudness_data)
else:
shutil.copy2(file_path, out_file_path)
progress_callback(idx, total_files)
def start_processing():
input_dir = input_path.get()
output_dir = output_path.get()
if not input_dir or not output_dir:
messagebox.showwarning("警告", "入力フォルダと出力フォルダを両方選んでください")
return
def run():
process_videos(input_dir, output_dir, update_progress)
messagebox.showinfo("完了", "すべての処理が完了しました!")
progress_bar['value'] = 0
threading.Thread(target=run).start()
def select_input():
path = filedialog.askdirectory()
if path:
input_path.set(path)
def select_output():
path = filedialog.askdirectory()
if path:
output_path.set(path)
def update_progress(current, total):
progress_bar['value'] = (current / total) * 100
# ======== GUI定義 ========
root = tk.Tk()
root.title("音量最適化ツール 🎵")
root.geometry("500x300")
root.resizable(False, False)
# 色とフォント
root.configure(bg="#f0f4f7")
font_title = ("Helvetica", 16, "bold")
font_normal = ("Helvetica", 11)
input_path = tk.StringVar()
output_path = tk.StringVar()
tk.Label(root, text="音量最適化ツール 🎵", bg="#f0f4f7", font=font_title).pack(pady=10)
frame = tk.Frame(root, bg="#f0f4f7")
frame.pack(pady=5)
tk.Label(frame, text="入力フォルダ:", bg="#f0f4f7", font=font_normal).grid(row=0, column=0, sticky="e")
tk.Entry(frame, textvariable=input_path, width=40).grid(row=0, column=1, padx=5)
tk.Button(frame, text="選択", command=select_input).grid(row=0, column=2)
tk.Label(frame, text="出力フォルダ:", bg="#f0f4f7", font=font_normal).grid(row=1, column=0, sticky="e")
tk.Entry(frame, textvariable=output_path, width=40).grid(row=1, column=1, padx=5)
tk.Button(frame, text="選択", command=select_output).grid(row=1, column=2)
tk.Button(root, text="処理開始", command=start_processing, bg="#4CAF50", fg="white", font=font_normal, width=20).pack(pady=15)
progress_bar = ttk.Progressbar(root, orient="horizontal", length=400, mode="determinate")
progress_bar.pack(pady=10)
root.mainloop()
✅ このGUI版でできること
- 入力&出力フォルダを選ぶだけで、ffmpeg解析+変換が完了
- 全ファイル一括処理
- 音量が適正ならコピーのみ(ムダなエンコードなし)
- シンプルでちょっと可愛いデザイン
✨ 次の拡張候補(希望あれば続き対応)
- 変換後、ファイル名に_normalizedとか付与(元と区別)
- 動画以外(例:音声ファイル)も対応(
.mp3
,.wav
) - エラーハンドリング(変換失敗時にリトライ)
- 多言語対応(日本語⇔英語UI切替)
了解しました!
【初心者向け・失敗しない】Python+ffmpeg+音量最適化ツールインストール手順を超わかりやすく一括ガイド化します。
※「最短・確実」を優先します!
【保存版】Windows 11向け:Python+ffmpeg+音量最適化ツール一括インストール完全ガイド
🎯 ゴール
- Windows 11環境に、Pythonとffmpegを正しくインストール
- 音量最適化ツール(Tkinter GUI版)を動かして、動画を一括音量調整できるようにする
- 誰でもミスなく3ステップで完了!
① 事前準備:必要なもの
項目 | 内容 |
---|---|
OS | Windows 11 |
ネット環境 | 必須(ダウンロードあり) |
必要なソフト | Python(最新版推奨)、ffmpeg |
② ステップ1:Pythonインストール
1-1. Python公式サイトからダウンロード
- 「Download Python 3.x.x」をクリックしてダウンロード
(※ x.xはバージョン番号。例:3.12.3など)
1-2. インストーラを起動して設定
- 最初の画面で 「Add Python 3.x to PATH」に必ずチェック ✅ を入れる!
- その後、「Install Now」 を押してインストール
(これを忘れると、後でエラーが出ます!)
1-3. インストール確認
インストール完了後、Windowsキー+R → cmd
→ Enter
コマンドプロンプトを開いて
python --version
と入力。
✅ Python 3.x.x
と表示されればOK!
③ ステップ2:ffmpegインストール
2-1. ffmpeg公式ビルドをダウンロード
- 「Release builds」の中の「ffmpeg-release-essentials.zip」をダウンロード
2-2. 解凍してフォルダを配置
- ダウンロードしたZIPファイルを右クリック → 「すべて展開」
- 中にあるフォルダ(例:
ffmpeg-xxxx-win64-static
)を
C:\Program Files\ffmpeg などに移動(どこでもいいがシンプルに)
例)C:\Program Files\ffmpeg\bin\ffmpeg.exe
2-3. PATHを通す(システムに認識させる)
- Windowsキー → 「環境変数」と検索 → 「システム環境変数の編集」クリック
- 「環境変数(N)…」ボタン押す
- 「システム環境変数」から「Path」を選択 → 編集 → 新規追加
C:\Program Files\ffmpeg\bin
を追加 → OK
2-4. インストール確認
再びコマンドプロンプトを開き
ffmpeg -version
と入力。
✅ バージョン情報が出れば成功!
④ ステップ3:ツールを実行する
3-1. 必要なPythonパッケージをインストール
コマンドプロンプトで以下を実行:
pip install tk
※tkinter
は標準搭載ですが、念のためインストールしておくと確実です。
3-2. ツール用のPythonファイルを作成
- 任意のフォルダに、先ほどの**「音量最適化ツール(Tkinter版スクリプト)」**をコピペして保存
- 例)ファイル名:
audio_normalizer_gui.py
3-3. ツール起動!
コマンドプロンプトでツールファイルがあるフォルダへ移動し、
python audio_normalizer_gui.py
と実行!
- おしゃれGUI画面が出たら成功✨
- あとは、入力フォルダと出力フォルダを選んで「処理開始」を押すだけ!
🛡 トラブルシューティング
状態 | 対応方法 |
---|---|
'python' は内部コマンドまたは外部コマンドとして認識されていません。 | PATH設定が抜けています。Python再インストール+「Add to PATH」を必ずチェック |
ffmpeg -version でエラー | ffmpegのbinフォルダパスがPathに通っているか確認 |
画面が出ない/エラーになる | Pythonバージョンが古すぎる場合あり。3.9以上推奨 |
GUIのボタン押しても動かない | フォルダパスの指定漏れか、対象に動画ファイル(.mp4)がない可能性 |
🎉 まとめ
この手順を完了すれば
→ **「数クリックで大量動画を最適音量化」**できる環境がすぐ整います!
- 時間をかけて手作業する必要なし
- ファイル個別チェックも不要
- すぐ収益用コンテンツに展開できる状態!
コメント