背景
AVCHD 内の.MTS ファイルを mp4 に一括変換したかったのですが、フリーソフトにろくなもんがないため、chatGPT に教えてもらいながら python でそれを実行できるコードを書きました
ffmpeg(v6)を使用しているので、ffmpeg が対応してるコーデックならなんでも変換できるはず(未検証)
簡単な機能説明
・指定ディレクトリ内の.MTS ファイルを.mp4 に変換して別の指定ディレクトリに置く
・その際ファイル名は動画ファイルの撮影日時を使用(2023-07-25-14-32.mp4 みたいな)
・コマンドラインで簡単めに実行できるといい
前提
Mac で動くことを確認してます(一応 windows でも動くはず)
python のバージョンは3.11.4
です
セットアップ
- 任意の場所に
mp4-converter.py
を作成する - 下記のコードを貼り付け後保存
import os
import argparse
import datetime
import platform
from tqdm import tqdm
import subprocess
input_formats = ["MTS", "AVI", "MOV", "MP4", "MKV", "WMV"]
output_formats = ["mp4", "avi", "mov", "mkv", "wmv"]
def run_ffmpeg_command(command):
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
for line in process.stdout:
yield line
process.wait()
# 完了音
def play_notification_sound():
if platform.system() == "Darwin":
# Mac環境の場合はosaScriptを使って通知音を鳴らす
try:
subprocess.run(['osascript', '-e', 'display notification "すべてのファイルの変換が完了しました" with title "FFmpeg Conversion" sound name "Glass"'])
except Exception as e:
print(f"Error while trying to play notification sound: {e}")
elif platform.system() == "Windows":
try:
import winsound
# Windows環境の場合はwinsoundを使ってビープ音を鳴らす
winsound.Beep(440, 500)
except Exception as e:
print(f"Error while trying to play notification sound: {e}")
def convert_to_mp4(input_directory, output_directory, extension="MTS",output_extension="mp4", quality="medium"):
output_directory = os.path.expanduser(output_directory) # ホームディレクトリを展開
os.makedirs(output_directory, exist_ok=True)
files = [file for file in os.listdir(input_directory) if file.endswith(f".{extension}")]
total_files = len(files)
converted_count = 0
if not os.path.exists(output_directory):
os.makedirs(output_directory)
for file in tqdm(files, desc="進捗", unit="ファイル"): # tqdmを使って進捗バーを表示
input_file = os.path.join(input_directory, file)
creation_time = datetime.datetime.fromtimestamp(os.path.getmtime(input_file)) # ファイルの作成日時を取得
output_file = os.path.join(output_directory, f"{get_datetime_string(creation_time)}.{output_extension}")
crf = "18" if quality == "high" else "23" # 高画質: CRF 18, 中画質: CRF 23
# 既に同じ名前のファイルが存在する場合、連番をつける
count = 1
while os.path.exists(output_file):
output_file = os.path.join(output_directory, get_datetime_string(creation_time) + f"-{count}.mp4")
count += 1
command = f"ffmpeg -i {input_file} -c:v libx264 -crf {crf} -loglevel warning -preset slow -c:a aac -strict experimental {output_file}"
os.system(command)
converted_count += 1
print(f"変換完了: {converted_count}/{total_files}")
def get_datetime_string(dt):
return dt.strftime("%Y-%m-%d-%H-%M")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="動画ファイルを指定のフォーマットに変換できます")
parser.add_argument("input_directory", help="入力ディレクトリのパス")
parser.add_argument("output_directory", help="出力ディレクトリのパス")
parser.add_argument("--extension", choices=input_formats, default="MTS", help="変換する拡張子 (デフォルト: MTS)")
parser.add_argument("--output_extension", choices=output_formats, default="mp4", help="変換先の拡張子 (デフォルト: mp4)")
parser.add_argument("--quality", choices=["high", "medium"], default="medium", help="変換品質を選択 (デフォルト: medium)")
args = parser.parse_args()
convert_to_mp4(args.input_directory, args.output_directory, args.extension, args.output_extension, args.quality)
play_notification_sound()
おわり
使い方
mp4-converter.py
をおいたディレクトリにcd
して実行します。
最低限のコマンドはこちら
python3 mp4-converter.py {変換したいファイルがあるディレクトリのパス} {変換したファイルの格納先パス}
ただこれだと.MTS ファイルを mp4 に中画質で変換するコマンドなので、コード見てやりたいふうに変えてください。
例えば.mp4 を.mov に高画質で変換したい場合、以下のコマンドになります。(成功するかはわからない)
python3 mp4-converter.py {変換したいファイルがあるディレクトリのパス} {変換したファイルの格納先パス} mp4 mov high
実行には結構かかるので、気長に待ちましょう。
正常に実行されている場合このような画面になります。
ModuleNotFoundError: No module named '~~~~'
のようなエラーが出た場合
pip3 install ~~~~
でモジュールをダウンロードしてください
終わりに
chatGPT は神
参考