タイトルの通り、ちょっと地味な内容ですが、毎度やり方を忘れそうになるので、自分用のメモとして記録します。
動画をもとにフォトグラメトリをやりたいとき、ソフト側が動画読み込みに対応している場合も多いですが、たとえば、「現場で撮った動画を会社にある高性能PCで処理したいんだけど、動画そのまま送るには回線が貧弱で……」というような場合に、このワザが役立つかもしれません。
前に書いたコードを使い回す
以前の記事で、FFmpegを使って、360°動画から画像を切り出す方法について書きましたが
今回はこれをちょこっと改造する(というか、ほぼオプションを削る)だけです。
あと、FFmpegをPythonから触りたいとき、FFmpeg-PythonなるPythonラッパーもあるようですが、今回はそれほど複雑ではないので、Subprocessでコマンド直叩きします。コマンドが複雑になる場合には便利そうです。
Pythonコード
ということで、さっそくですが、こちらが出来上がったコードです。
詳しいことは、インラインのコメントから読み解いてください。
import subprocess import os import sys import glob # 引数でディレクトリを指定、動画ファイルだけ input_path = sys.argv[1] print(input_path) # ディレクトリだったら if os.path.isdir(input_path): # ファイルパスをリストにして突っ込む files = glob.glob(input_path + '/*.*') # ファイルだったら elif os.path.isfile(input_path): # ファイルパスを突っ込む files = [input_path] # こっちはディレクトリパスに置き換える input_path = os.path.dirname(input_path) else: # どっちでもなければ雑にエラー処理 files = [] print('不正なインプットです。') for input_file_path in files: input_file_name = os.path.splitext(os.path.basename(input_file_path))[0] # 画像切り出しのフレームレート、ドローンの飛行速度・高度に合わせて適当に決める output_fps = 1 # JPEGの品質、1が最高 output_quality = 1 # 出力フォルダをつくる output_dir_path=fr'{input_path}/{input_file_name}_frames' os.makedirs(output_dir_path, exist_ok=True) # 出力ファイル名とパスをつくる output_file_name=fr'{input_file_name}-%06d.jpg' output_file_path=fr'{output_dir_path}/{output_file_name}' # コマンドを組み立てる commands = [ 'ffmpeg', f'-i "{input_file_path}"', f'-q:v {output_quality}', f'-r {output_fps}', f'"{output_file_path}"' ] command = ' '.join(commands) print(command) # ffmpeg実行 subprocess.call(command, shell=True) print('完了しました。')
これをコピーして、Pythonスクリプトとして保存します。名前はとりあえず「video2jpg.py」とでもしておきましょう。
使い方
Python video2jpg.py入力フォルダorファイルパス
フォルダを指定するとその直下のファイルを一括処理、ファイル指定なら単体処理が走ります。
ためしに1つやってみると
こんな感じです。
ファイルサイズは…
ファイルサイズを92%カットすることができました! このサイズなら、通信環境が悪くてもなんとか送れそうです。途中で区切って分割送信って手も使えますね。
それでは、今日はここまで。