Pythonコードで動画のFPSを下げる方法
生き物の行動観察をしようと、動画撮影したはいいが、動画解析にかかる時間とパソコンの処理能力の限界を感じて、動画の質を下げたいと思っている研究者の方は多いと思います。
本記事では、30 fpsで撮影した録画データ(mp4)を半分の15 fps
さらに1 fpsまで動画の質を下げる方法を紹介します。
作業環境
今回は、google様のColaboratoryを用いてPythonコードを実行しますので、googleアカウントが必要です。
なくてもPythonコードが実行できる環境でしたら大丈夫です。
Colaboratoryを開く
google chromeのホーム画面の右上の「Googleアプリ」から「ドライブ」を開きます。
左上の「+新規」から「その他」へ、そして「Google Colaboratory」に進みます。
これで、Pythonコードを書く準備ができました。
動画の読み込み(アップロード)
まずは、動画のデータを読み込みます。
一つ目のセルに以下のコードをコピペし、実行▶️します
from google.colab import files
# 動画ファイルをアップロードする
uploaded = files.upload()
実行▶️すると、「ファイル選択」というボタンが出てくるので、動画ファイルを選択します。
アップロードが完了すると、左側のファイル欄に動画データが表示されます。
OpenCVをインストール
次に、Pythonで動画などを処理することができるライブラリの「OpenCV」をインストールします。
# OpenCVのインストール
!pip install opencv-python
!pip install opencv-python-headless
これで動画処理の準備は完了です。
動画処理① 30 fpsを15 fpsに
以下のコードを実行▶️すれば、15 fpsに変換されたファイルが出力されます。
import cv2
# 入力ファイルと出力ファイルの指定
input_file = "input.mp4"
output_file = "output_15fps.mp4"
# 動画を読み込む
cap = cv2.VideoCapture(input_file)
# 動画のプロパティを取得
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# 出力動画の設定 (15fpsで保存)
out = cv2.VideoWriter(output_file, fourcc, 15.0, (width, height))
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
# 2フレームに1フレームを抽出 (30fpsを15fpsに変換)
if frame_count % 2 == 0:
out.write(frame)
frame_count += 1
# リソースを解放
cap.release()
out.release()
cv2.destroyAllWindows()
print(f"変換完了: {output_file}")
動画処理①の解説
1. ライブラリのインポート
import cv2
先ほどインストールしたOpenCVをインポートすることでOpenCVを使うことができます。
2. 入力ファイルと出力ファイルの指定
input_file = "input.mp4"
output_file = "output_15fps.mp4"
input_file には変換したい動画ファイルを指定します。
output_file には変換後に保存する動画ファイル名を指定します。
3. 動画の読み込み
cap = cv2.VideoCapture(input_file)
cv2.VideoCapture は、指定した動画ファイルを読み込む関数です。これで、動画ファイルをプログラム内で操作できるようになります。
4. 動画のプロパティを取得
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
cap.get(cv2.CAP_PROP_FPS) で、元の動画のフレームレート(ここでは30fps)を取得します。
cv2.CAP_PROP_FRAME_WIDTH と cv2.CAP_PROP_FRAME_HEIGHT で、動画の幅と高さを取得し、変換後の動画にも同じサイズを適用します。cv2.VideoWriter_fourcc(*'mp4v') は、動画のエンコード方法を指定します。ここでは、MP4形式で出力するために指定しています。
5. 出力動画の設定
out = cv2.VideoWriter(output_file, fourcc, 15.0, (width, height))
cv2.VideoWriter を使って、動画を書き出す設定をします。
出力する動画は15fpsで保存するので、第3引数には15.0を指定しています。これにより、動画の再生速度が15fpsになります。
6. フレームの抽出と保存
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
if frame_count % 2 == 0:
out.write(frame)
frame_count += 1
cap.read() で動画から1フレームずつ読み込みます。ret が False になった場合は、動画が終了したことを意味します。
フレーム番号(frame_count)が偶数のときだけ(2で割って、余りが0になる場合)フレームを出力し、奇数のフレームはスキップします。これにより、2フレームに1フレームを抽出して15 fpsに変換できます。
30 fpsでは1秒間に30フレームが再生されますが、その半分の15フレームだけを書き出すことで、動画の再生速度を15fpsに落とすことができます。
7. リソースの解放
cap.release()
out.release()
cv2.destroyAllWindows()
処理が終わった後は、読み込んだ動画と書き出した動画を解放して、リソースを適切に閉じます。これにより、メモリリークを防ぎます。
8. 処理完了メッセージ
print(f"変換完了: {output_file}")
最後に、動画の変換が完了したことを知らせるメッセージを表示します。
動画処理② 30 fpsを1 fpsに
基本的に構造は同じですが、処理の部分だけが異なります。
import cv2
# 入力ファイルと出力ファイルの指定
input_file = "input.mp4"
output_file = "output_1fps.mp4"
# 動画を読み込む
cap = cv2.VideoCapture(input_file)
# 動画のプロパティを取得
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# 出力動画の設定 (1fpsで保存)
out = cv2.VideoWriter(output_file, fourcc, 1.0, (width, height))
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
# fps分のフレームをスキップして、1fpsの間隔でフレームを取得
if frame_count % int(fps) == 0:
out.write(frame)
frame_count += 1
# リソースを解放
cap.release()
out.release()
cv2.destroyAllWindows()
print(f"変換完了: {output_file}")
動画処理②の解説
動画処理①では偶数(2で割り切れる)のフレームだけを用いましたが、1 fpsではこの部分が異なります。
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
# fps分のフレームをスキップして、1fpsの間隔でフレームを取得
if frame_count % int(fps) == 0:
out.write(frame)
frame_count += 1
1 fpsにする処理では、元の画像のfpsで割り切れるframe_countの時だけ動画を使うように処理しています。元の動画は30 fpsなので、30枚に1枚だけということです。
処理後の動画のダウンロード
あとは出力されたファイルをダウンロードすれば完成です。
ファイル欄にある出力ファイルを右クリックして「ダウンロード」するだけです。
注意点
Colaboratoryではセッション(一連の作業)が中断すると、その間にアップロードしたデータや出力結果のデータが消去されてしまいます。作業が完了したら、速やかに保存やダウンロードを行ってください。
動画データが重たい場合
動画が何時間もあるような重たいデータの場合、ColaboratoryではGoogle様のグラフィックボード(GPU)をお借りして処理することができます(時間制限あり)。
メニューの「ランタイム」から「ランタイムのタイプを変更」へ進むと「GPU」を選択することができます。これで動画処理は爆速で終わるでしょう!
まとめ
この方法では、30fpsの動画を15fpsに変換するために、2フレームに1フレームを抽出する方法と、30フレーム分の1フレームを抽出するアプローチを取っています。OpenCVの基本的な操作を理解し、フレームをスキップすることで任意のフレームレートに変換することができます。このコードを使えば、他のフレームレートへの変換も簡単に応用できるので、試してみてください。
この記事が気に入ったらサポートをしてみませんか?