🤩
複数の動画を同一オプションでワンライナー処理するスクリプト
はじめに
FFmpegはコマンドラインで動画ファイルを処理できるので大変便利です。
しかし、同じような処理を複数の動画ファイルに対して適用するには、コマンドのパスの部分をファイルごとに変えなければなりません。
これは少し手間です。
以下のスクリプトは、その手間を省いてくれるPythonスクリプトです。
FFmpegを外部コマンドとして呼び出すだけなので、パッケージのインストールは不要です。
コード
import re
import sys
from argparse import ArgumentParser
from pathlib import Path
from subprocess import Popen
parser = ArgumentParser(description='Wrapper for FFmpeg to process multiple files in one-line')
parser.add_argument('-c', '--command', default='ffmpeg', help='command to be executed')
parser.add_argument('-o', '--output', type=Path, help='output directory path')
parser.add_argument('-m', '--multi', action='store_true', help='enable multi-processing')
parser.add_argument('-g', '--glob', default='**/*', help='glob to filter input paths')
parser.add_argument('-wf', '--whitefilter', default='', type=re.compile, help='regex to filter input paths')
parser.add_argument('options', help='options passed to FFmpeg, ex: "-i {} {}.mp4"')
parser.add_argument('input', nargs='+', type=Path, help='input file or directory path(s)')
args = parser.parse_args()
inputs = []
for input in args.input:
if input.is_file():
sub_inputs = [input]
else:
sub_inputs = input.glob(args.glob)
inputs += [sub_input for sub_input in sub_inputs if sub_input.is_file() and args.whitefilter.search(str(sub_input))]
placeholder_count = args.options.count('{}')
if placeholder_count not in [1, 2]:
print('The number of placeholders in options must be 1 or 2.')
sys.exit()
elif placeholder_count == 2 and args.output is None:
print('The output directory path must be specified when the number of placeholders in options is 2.')
sys.exit()
procs = []
for input in inputs:
sub_args = args.command.strip()
params = [str(input)]
if args.output:
output = args.output / input.stem
params.append(str(output))
sub_args += ' ' + args.options.format(*[f'"{param}"' for param in params])
print(sub_args)
proc = Popen(sub_args, shell=True)
if not args.multi:
proc.wait()
procs.append(proc)
print()
codes = {}
for proc in procs:
code = proc.wait()
if code in codes:
codes[code] += 1
else:
codes[code] = 1
code_count = sum(codes.values())
for code, count in codes.items():
print(f"returncode[{code}]:", count, '/', code_count)
使用例
例えば、特定のディレクトリ以下のすべての動画ファイルをH.265でエンコードしなおすには以下のコマンドを実行します。
python script.py "-i {} -c:v libx265 -c:a copy {}.mp4" path/to/input/directory -o path/to/output/directory
Discussion