PR

【保存版】YouTube動画の音量バラつきを“業界標準”に正規化する完全ガイド(Windows+FFmpeg+初心者向け)


【保存版】YouTube動画の音量バラつきを“業界標準”に正規化する完全ガイド(Windows+FFmpeg+初心者向け)


🎯 この記事で得られること

  • 音量がバラバラな動画を、プロ品質で安定・自動的に最適化する方法
  • 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 LUFSYouTube/Spotify等ストリーミング最適化、聴きやすさ重視
TP-1.5 dBTPクリッピング防止、音質確保、安全性の両立
LRA11 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フォルダに集約される

🚀 次の拡張提案

  1. TkinterでGUI化
  2. 並列処理対応(大量ファイル向けに速度アップ)
  3. LRAの自動最適化オプション追加(例えば教育動画用にLRAを絞る)
  4. 処理進捗バー表示(ユーザー体験向上)

具体的には:

  • 見た目に軽くグラデーション 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環境に、Pythonffmpegを正しくインストール
  • 音量最適化ツール(Tkinter GUI版)を動かして、動画を一括音量調整できるようにする
  • 誰でもミスなく3ステップで完了!

① 事前準備:必要なもの

項目内容
OSWindows 11
ネット環境必須(ダウンロードあり)
必要なソフトPython(最新版推奨)、ffmpeg

② ステップ1:Pythonインストール

1-1. Python公式サイトからダウンロード

👉 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公式ビルドをダウンロード

👉 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)がない可能性

🎉 まとめ

この手順を完了すれば
→ **「数クリックで大量動画を最適音量化」**できる環境がすぐ整います!

  • 時間をかけて手作業する必要なし
  • ファイル個別チェックも不要
  • すぐ収益用コンテンツに展開できる状態!

コメント

タイトルとURLをコピーしました