手持ちの動画を加工したいときはありませんか?
例えば、既存の動画から背景を切り抜いた動画を作りたい、動画の画質をSDからHi-Visionにアップグレードしたい、画質のコントラストを上げたい時など・・・
ビデオ編集ツールを使えば解決できそうな内容ですが、実際には一部の有料ツールにしか搭載されていないのが現状です。
そこで、今回は動画から画像と音声を抽出する機能と、画像と音声から再び動画を作成する機能を搭載した「動画・画像変換ツール」を紹介したいと思います。
本ツールと別のツール(例えば背景切り抜きツールなど)を組み合わせることで、既存の動画から背景を切り抜いた動画を作成することができるようになります。
自作ツールを作るためのポイントと今後公開予定の自作ツール一覧を「【実践】Pythonで事務処理向け自作ツールを作ろう!」で紹介していますので、併せてご覧ください。
動画・画像変換ツールの概要と使い方
今回紹介する動画・画像変換ツールは、動画から画像と音声を抜き出したり、その逆に画像と音声から動画を作成することができます。
- 指定した動画ファイルから画像と音声を抽出し、指定フォルダに保存します。
- 指定フォルダに保存されている画像と音声から、動画を作成します。
- 入力フォルダ、出力ファルダに入力した内容は保持され、次回起動時に復元されます。
画面項目 | 説明 |
---|---|
入力ファイル | 画像と音声の抽出対象となる動画ファイルのパスを指定 |
画像と音声を抽出 | 動画から画像と音声を抽出する処理を実行 |
作業フォルダ | 抽出した画像と音声の保存先フォルダを指定 |
画像と音声から動画を作成 | 作業フォルダに置かれた画像と音声から動画ファイルを作成 |
出力ファイル | 作業フォルダの画像と音声から作成された動画ファイルの保存先パスを指定 |
動画から画像と音声を抽出する
- 入力ファイル欄に、対象の動画ファイルを指定する。
- 作業フォルダ欄に、画像と音声の保存先フォルダを指定する。
- 「画像と音声を抽出」ボタンをクリックする
例えば、作業フォルダに "O:\TestData\temp" を指定した場合、その配下に audio と image フォルダが作成され、それぞれに音声ファイル(audio.aac)と画像ファイル(000000000~.png)が保存されます。
画像と音声から動画を作成する
- 作業フォルダ欄に、画像と音声の保存先フォルダを指定する。
- 出力ファイル欄に、作成した動画のファイル名(ファイルのパス)を指定する。
- 「画像と音声から動画を作成」ボタンをクリックする
例えば、作業フォルダに "O:\TestData\temp" を指定した場合、その配下にある audio と image フォルダから音声と画像を取り出し、それらを用いて result.mp4 を作成し、O:\TestDataフォルダに保存します。
プログラムのダウンロードと動作環境の設定
Pythonのインストールが必要です。既に構築済みの方は読み飛ばしてください。詳細は下記の個別記事をご覧ください。
自作ツールのためのポータブルPython開発・実行環境を作ろう! | プログラム実行時に必要 |
WinPython環境に ffmpeg を入れよう! | プログラム実行時に必要 |
WinPythonにVSCode Portable版を入れよう! | プログラム修正時に必要 |
Python 環境に下記のライブラリをインストールします。 command.bat を実行後、下記のコマンドを実行します。
pip install customtkinter
pip install Pillow
pip install tkinterdnd2
動画・画像変換ツールと共通パッケージの2つをダウンロードし、2つのフォルダが同一階層になるように解凍します。
動画⇔画像変換ツール
実行方法
次の手順で実行してください。
- WinPython のインストールフォルダ内にある command.bat を実行
- ダウンロードしたプログラムファイルをコピーした場所にカレントディレクトリを移動
- Python main.py を実行
Python main.py
しばらくすると下記の画面が表示されます。初回起動時はすべての入力欄が空白で表示されますが、次回からは直前に入力した値が画面に復元されます。
動画・画像変換ツールで画像と音声の抽出、または動画の作成ボタンをクリックすると、コンソール画面にffmpeg が出力する途中経過が表示されます。
動画・画像変換ツールの仕様
プログラムの構成
main.py の中で画面の表示と動画⇔画像変換ボタンのイベント処理を記述しています。main.py の中で直接変換処理を行う方法もありますが、再利用性を高めるため videoimageconverter.py で処理するようにしました。
モジュール名 | 役割 |
---|---|
main.py | 画面の表示とボタンクリックのイベント処理 |
videoimageconverter.py | 動画から画像と音声の抽出、画像と音声から動画を作成 |
create_ui.py | UI定義ファイルを読み込んで画面にウィジェットを表示 |
customtkinter | ファイル選択やフォルダ選択、ドラッグ&ドロップを実現するための補助 |
appconfig.py | 画面に入力された値をJson形式のファイルに保存/読込する |
ソースコード
main.py
画面にボタンが2つ設置されており、どちらをクリックされても func 関数が呼び出されます。
このfunc関数の中で、param["_clicked_widget"]を参照することで、どのボタンがクリックされたかを判断し、処理を分岐しています。
import os
import sys
sys.path.append(os.path.join(os.path. dirname(__file__), '../libs'))
from create_ui import CreateUI
from videoimageconverter import VideoImageConverter
# ボタンが押された時の処理
def func(param):
ff = VideoImageConverter(param["extract_folder"])
if param["_clicked_widget"] == "extract_button":
ff.movie_to_image(param["input_file"])
if param["_clicked_widget"] == "merge_button":
ff.image_to_movie(param["output_save"])
# インスタンス生成
ui = CreateUI(func)
# 画面の表示
ui.show()
videoimageconverter.py
VideoImageConverter は、動画⇒画像・音声、及び画像・音声⇒動画 に変換するためのクラスです。
メソッド | 説明 |
---|---|
__init__( temp_folder, # 作業フォルダのパス format="png", # 抽出する画像のフォーマット fps=30 # フレームレート | を指定します。 フレームレートに応じた枚数の画像が出力されます。 | 作業フォルダ、画像フォーマット、フレームレート
movie_to_image( input_video, #動画入力ファイルのパス mode="av" # a:音声を抽出 v:画像を抽出 ) | 保存します。 画像だけを抽出したい場合は "v" 、音声だけを抽出 したい場合は "a" を mode に指定してください。 | 動画から画像と音声を抽出し、作業フォルダに
image_to_movie( output_video # 動画出力ファイルのパス ) | コンストラクタに指定したフレームレートで動画 が作成されます。 入力と出力のフレームレートを変更したい場合は、 メソッドを呼ぶ直前に、fps プロパティに値をセット してください。 | 作業フォルダの画像と音声を使って動画を作成します。
import subprocess
import os
import shutil
class VideoImageConverter:
def __init__(self,temp_folder,format="png",fps=30):
"""
コンストラクタ
Args:
temp_folder (str): 出力フォルダ
format (str): 画像の種類(png,jpg,bmp など)
fps (int): フレームレート
"""
self.fps = fps
self.format = format
self.image_folder = f"{temp_folder}/image"
self.audio_folder = f"{temp_folder}/audio"
def movie_to_image(self,input_video,mode="av"):
"""
動画を画像と音声に分解する。
output_folder配下に temp/image と temp/audio フォルダが作成される
Args:
input_video (str): 入力動画ファイル
mode (str): "a":動画から音声を抽出 "v":動画から画像を抽出
"""
if "v" in mode:
# 画像の格納先フォルダ作成
self.drop_and_create_folder(self.image_folder)
# 画像の抽出
command = f'ffmpeg -i "{input_video}" -q:v 1 -r {self.fps} "{self.image_folder}/%10d.{self.format}"'
subprocess.call(command, shell=True)
if "a" in mode:
# 音声の格納先フォルダ作成
self.drop_and_create_folder(self.audio_folder)
# 音声の抽出
command = f'ffmpeg -i "{input_video}" -c:a aac "{self.audio_folder}/audio.aac"'
subprocess.call(command, shell=True)
def image_to_movie(self,output_video):
"""
画像ファイルを動画に結合する
Args:
output_video (str): 出力動画ファイル名
"""
# 出力先のファイルがあれば削除
if os.path.isfile(output_video):
os.remove(output_video)
# 音声ファイルがあれば、動画に加える
audio_path = f"{self.audio_folder}/audio.aac"
option = ""
if os.path.isfile(audio_path):
option = f' -i "{audio_path}" '
# ffmpegコマンドを作成
command = f'ffmpeg -r {self.fps} -i "{self.image_folder}/%10d.{self.format}" {option} -c:v libx264 -pix_fmt yuv420p "{output_video}"'
# ffmpegを実行
subprocess.call(command, shell=True)
def drop_and_create_folder(self,folder):
"""
フォルダを作成する。既に存在すれば削除して再作成する
Args:
folder (str): フォルダ名
"""
# 既にフォルダがあれば削除
if os.path.exists(folder):
shutil.rmtree(folder)
# フォルダを作成
os.makedirs(folder, exist_ok=True)
本クラスを直接使用する場合は、下記のサンプルを参考にしてください。
# 作業フォルダを指定してインスタンスを生成
ff = VideoImageConverter("./temp")
# 動画から画像と音声を抽出して作業フォルダに保存
ff.movie_to_image("d:/hoge.mp4")
# 作業フォルダ内の画像と音声から動画を作成
ff.image_to_movie("d:/join.mp4")
design.txt
title:動画⇔画像変換ツール
mode:light
max:1024,350
size:600,350
min:600,350
input_file:入力ファイル,ファイル選択
extract_button:画像と音声を抽出
extract_folder:作業フォルダ,フォルダ選択
merge_button:画像と音声から動画を作成
output_save:出力ファイル,ファイル選択
design.txt の記述方法については、下記の記事で詳しく解説しています。
まとめ
今回は、「動画・画像変換ツール」について、使い方から環境構築に至るまでの手順、仕様について紹介しました。
画面は非常にシンプルなので、ノンコーディングでUI画面が簡単に作成できるCureateUIクラスを使いました。
ffmpeg を使うことで、動画から画像や音声を抽出したり、画像や音声から動画を作成することが簡単に行えますが、fmpeg が高機能なため引数のバリエーションが多く、どれを組み合わせれば良いのか判断に迷うこともしばしば発生します。
本ツールは、動画と画像の相互変換を行うことだけに特化し、動画ファイルと作業フォルダを指定するだけで相互変換ができるようにしています。
本記事で紹介するソースは基本的な部分のみになるので、必要に応じて修正の上、ご利用いただければ幸いです。
コメント