TSからmp4への圧縮を一括実行するpythonスクリプト
ここで紹介するのは、録画で溜まったTSファイルをmp4ファイルへ圧縮してくれるpythonのスクリプトです。
CentOS 8.2の環境で、使用しています。今回は、ffmpegの性能を測定したスクリプトを簡単にして紹介します。
実行環境の準備
実際に確認した環境は、CentOS 8.2です。
ここで紹介するスクリプトを実行するために、以下の確認が必要です。
- python3が実行できる。
- ffmpegが実行できる。
- ffmpeg-pythonが使用できる。
(1) python3がインストールされているか確認する。
[euser@test ~]$ python3 -V Python 3.6.8
(2) ffmpegがインストールされているか確認する。
[euser@test ~]$ ffmpeg -version ffmpeg version 4.2.4 Copyright (c) 2000-2020 the FFmpeg developers built with gcc 8 (GCC) configuration: --prefix=/usr --bindir=/usr/bin --datadir=/usr/share/ffmpeg --docdir=/usr/share/doc/ffmpeg --incdir=/usr/include/ffmpeg --libdir=/usr/lib64 --mandir=/usr/share/man --arch=x86_64 --optflags='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' --extra-ldflags='-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld ' --extra-cflags=' ' --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-version3 --enable-bzlib --disable-crystalhd --enable-fontconfig --enable-frei0r --enable-gcrypt --enable-gnutls --enable-ladspa --enable-libaom --enable-libdav1d --enable-libass --enable-libbluray --enable-libcdio --enable-libdrm --enable-libjack --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libmp3lame --enable-nvenc --enable-openal --enable-opencl --enable-opengl --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librsvg --enable-libsrt --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libvorbis --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-version3 --enable-vapoursynth --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-libzimg --enable-libzvbi --enable-avfilter --enable-avresample --enable-libmodplug --enable-postproc --enable-pthreads --disable-static --enable-shared --enable-gpl --disable-debug --disable-stripping --shlibdir=/usr/lib64 --enable-libmfx --enable-runtime-cpudetect libavutil 56. 31.100 / 56. 31.100 libavcodec 58. 54.100 / 58. 54.100 libavformat 58. 29.100 / 58. 29.100 libavdevice 58. 8.100 / 58. 8.100 libavfilter 7. 57.100 / 7. 57.100 libavresample 4. 0. 0 / 4. 0. 0 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 libpostproc 55. 5.100 / 55. 5.100
(3)ffmpeg-pythonがインストールされているか確認する。
[euser@test ~]$ pip3 --version pip 9.0.3 from /usr/lib/python3.6/site-packages (python 3.6)
[euser@test ~]$ pip3 install --user ffmpeg-python Collecting ffmpeg-python Using cached https://files.pythonhosted.org/packages/d7/0c/56be52741f75bad4dc6555991fabd2e07b432d333da82c11ad701123888a/ffmpeg_python-0.2.0-py3-none-any.whl Requirement already satisfied: future in /usr/local/lib/python3.6/site-packages (from ffmpeg-python) Installing collected packages: ffmpeg-python Successfully installed ffmpeg-python-0.2.0
[euser@test ~]$ pip3 list DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning. asn1crypto (0.24.0) astroid (2.4.2) bcc (0.11.0) blivet (3.1.0) Brlapi (0.6.7) cffi (1.11.5) chardet (3.0.4) chrome-gnome-shell (0.0.0) colorama (0.4.3) configobj (5.0.6) configshell-fb (1.1.25) coverage (4.5.1) crayons (0.4.0) cryptography (2.3) cupshelpers (1.0) dbus-python (1.2.4) decorator (4.2.1) ethtool (0.14) ffmpeg-python (0.2.0) future (0.18.2)
以上で、python3、ffmpeg、ffmpeg-pythonが実行できることが確認できました。
スクリプトの説明
今回作成したスクリプトは、二つに分かれています。
- 実行制御スクリプト
crf値、preset値を設定して、実行を制御します。
今回は、1440×1080の解像度で、crf=22、preset=veryfastで1回処理します。 - 圧縮処理スクリプト
与えられたcrf値、preset値を用いて、ffmpegで圧縮を実行します。
また、logに圧縮速度・圧縮率を記録することができます。
(1)実行制御スクリプト(ts_to_mp4_1440.py)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #ts_to_mp4_1440.py #created 2020-10-05 by simplelife0530 import trans_mp4 import pathlib import os # mode = 1440 or 1920 mode = 1440 in_dir = "./ts/" # p_list = [veryfast] # c_list 1440 = [22] # c_list 1920 = [25] p_list = [ "veryfast" ] if mode = = 1440 : c_list = [ 22 ] else : c_list = [ 25 ] for preset in p_list: for crf in c_list: out_dir = "./mp4/" + str (crf) + "-" + preset + "/" os.makedirs(out_dir, exist_ok = True ) f_list = pathlib.Path(in_dir).glob( "*.ts" ) for f in f_list: trans_mp4.transcode(in_dir + f.name, out_dir + f.name.replace( ".ts" , ".mp4" ),crf,preset, "") |
(2)圧縮処理スクリプト(trans_mp4.py)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #trans_mp4.py #created 2020-03-30 by simplelife0530 # import ffmpeg import pathlib import glob import subprocess import sys import time import json import os import datetime import csv def transcode(input_file,output_file,crfValue,presetValue,sValue): in_options = {} if not sValue: out_options = { 'vcodec' : 'libx264' , 'crf' :crfValue, 'preset' :presetValue} out_tag = str (crfValue) + "-" + presetValue else : out_options = { 'vcodec' : 'libx264' , 'crf' :crfValue, 'preset' :presetValue, 's' :sValue} out_tag = str (crfValue) + "-" + presetValue + "-" + sValue log_path = "./log/" os.makedirs(log_path, exist_ok = True ) today = datetime.date.today() log_info = str (crfValue) + "-" + presetValue log_file = log_path + log_info + ".csv" header = [ "ファイル名" , "再生時間" , "処理時間" , "トランスコード速度" , "入力ファイルサイズ" , "出力ファイルサイズ" , "圧縮率" ] try : with open (log_file, 'x' ) as f: writer = csv.writer(f) writer.writerow(header) except FileExistsError: pass start = time.time() ( ffmpeg . input (input_file, * * in_options) .output(output_file, * * out_options) .run() ) elapsed_time = time.time() - start print ( "処理時間:{:.1f}" . format (elapsed_time)) file_name = os.path.basename(input_file) video_info = ffmpeg.probe(input_file) video_stream = next ((stream for stream in video_info[ 'streams' ] if stream[ 'codec_type' ] = = 'video' ), None ) video_duration = float (video_stream[ 'duration' ]) print ( "再生時間:{:.1f}" . format (video_duration)) compression_speed = video_duration / elapsed_time print ( "速度:{:.1f}" . format (compression_speed)) input_filesize = os.path.getsize(input_file) output_filesize = os.path.getsize(output_file) print ( "入力サイズ:" , input_filesize) print ( "出力サイズ:" , output_filesize) compression_ratio = output_filesize / input_filesize print ( "圧縮率:{:.3f}" . format (compression_ratio) ) with open (log_file, 'a' ) as f: writer = csv.writer(f) writer.writerow([file_name, '{:.1f}' . format (video_duration), '{:.1f}' . format (elapsed_time), '{:.1f}' . format (compression_speed), input_filesize, output_filesize, '{:.3f}' . format (compression_ratio)]) |
実行制御スクリプトを変更することで、複数のcrf値、複数のpreset値で圧縮を行うことができます。
スクリプトの利用手順
本スクリプトを利用する手順は、以下のとおりです。
- TSファイルを用意する。
- TSファイルのサイズの1.5倍以上の容量が確保できるフォルダを作成する。
- 作成したフォルダの中に、tsという名前のフォルダを作成し、TSファイルを保存する。
- 二つのスクリプト ts_to_mp4_1440.pyとtrans_mp4.pyを作成したフォルダにコピーする。
- ターミナルを使って、ts_to_mp4.pyを実行する。
以下が、実行準備が整った状態。
ターミナルを開き、コマンドを入力する。
[euser@test test]$ ls trans_mp4.py ts ts_to_mp4_1440.py [euser@test test]$ python3 ts_to_mp4_1440.py
処理が終了した時の状態。
新たに、「mp4」、「log」、「–pycache–」の3つのフォルダができる。
「mp4」フォルダの中に、「22-veryfast」というフォルダがあり、その中に圧縮してできたmp4ファイルが保存されている。
「log」フォルダの中に、22-veryfast.csvというファイルがあり、ファイルごとの圧縮速度、圧縮率がcsv形式で記録されている。
テストスクリプト
スクリプトをもう一種類紹介します。こちらは、
3種類のpreset(superfast、veryfast、faster)、
5種類のcrf
(21、22、23、24、25)(1440×1080)、
(23、24、25、26、27)(1920×1080)
計15パターンで圧縮を実施します。
FFmpegの性能調査を実施する際に便利なスクリプトです。
test_mp4_1440.pyは、1440x1080の解像度の、主に地上波のTSファイルのためのスクリプトです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #test_mp4_1440.py #created 2020-09-12 by simplelife0530 import trans_mp4 import pathlib import os # mode = 1440 or 1920 mode = 1440 in_dir = "./ts/" # p_list = [superfast, veryfast, faster] # c_list 1440 = [21, 22, 23, 24, 25] # c_list 1920 = [23, 24, 25, 26, 27] p_list = [ "veryfast" ] if mode = = 1440 : c_list = [ 21 , 22 , 23 , 24 , 25 ] else : c_list = [ 23 , 24 , 25 , 26 , 27 ] for preset in p_list: for crf in c_list: out_dir = "./mp4/" + str (crf) + "-" + preset + "/" os.makedirs(out_dir, exist_ok = True ) f_list = pathlib.Path(in_dir).glob( "*.ts" ) for f in f_list: trans_mp4.transcode(in_dir + f.name, out_dir + f.name.replace( ".ts" , ".mp4" ),crf,preset, "") |
test_mp4_1920.pyは、1920x1080の解像度の、主にBSプレミアム、BS11、WOWOW向けのTSファイルのためのスクリプトです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #test_mp4_1920.py #created 2020-09-12 by simplelife0530 import trans_mp4 import pathlib import os # mode = 1440 or 1920 mode = 1920 in_dir = "./ts/" # p_list = [superfast, veryfast, faster] # c_list 1440 = [21, 22, 23, 24, 25] # c_list 1920 = [23, 24, 25, 26, 27] p_list = [ "veryfast" ] if mode = = 1440 : c_list = [ 21 , 22 , 23 , 24 , 25 ] else : c_list = [ 23 , 24 , 25 , 26 , 27 ] for preset in p_list: for crf in c_list: out_dir = "./mp4/" + str (crf) + "-" + preset + "/" os.makedirs(out_dir, exist_ok = True ) f_list = pathlib.Path(in_dir).glob( "*.ts" ) for f in f_list: trans_mp4.transcode(in_dir + f.name, out_dir + f.name.replace( ".ts" , ".mp4" ),crf,preset, "") |
スクリプトのダウンロード
スクリプトは、以下からダウンロードできる。
コメントを残す