見出し画像

PythonでFFmpegを用いて動画処理と保存


1.はじめに

 本記事では、Pythonでコマンドを実行できるsubprocessを用いて、FFmpegを実行し、フレームの取得、画像処理、動画の保存の事例を紹介します。
 一般的にPythonでOpencvを用いてカメラ映像や動画の読み込み、動画の保存などが実施されますが、動画の読み込みの際にフレームレートを調節できないといった問題がありました。一方、FFmpegではフレームレートを調整してカメラ映像や動画を読み込みができることから、それを試してみます。また、GPUを用いたエンコード・デコードを実施する際にOpenCVではビルドが手間ですが、FFmpegではOpenCVに比べてビルドの手間がかかりません
 そういった理由から本記事ではPythonでコマンドを実行できるsubprocessを用いて、FFmpegを実行し、フレームの取得、画像処理、動画の保存の事例を紹介します。

2.FFmpeg

以下FFmpegです。

Ubuntuでは下記のコマンドでインストールできます。

$ sudo apt install ffmpeg

また、GPUを用いたエンコード・デコードをする際のビルド方法は以下のページになります。

映像を扱う際の基本的な引数は下記です。

  • -i url:入力動画パス or RTSPリンク

  • -f fmt:入力や出力のファイル形式。フォーマットは通常、入力に対して自動検出される。

  • -y:出力ファイルを上書きする。

  • -c codec or -codec codec:コーデック。libx264など

  • -r fps:フレームレートを設定

  • -s 'width x height':フレームサイズを設定

  • -vcodec (=-codec:v) codec:ビデオコーデックの設定。

  • -pix_fmt format:ピクセル形式を設定

  • -hwaccel hwaccel:デコードするハードウェアアクセラレーションを設定

引数のドキュメントは下記リンクになります。


3. PythonでFFmpegを使用して動画処理

 PythonでFFmpegを用いて動画の取得、保存を行うプログラムを下記に示します。

import time
import subprocess
import cv2
import numpy as np

input_videoname = 'sample.mp4' # 入力動画ファイルのパス
width=1280 # 保存時の動画幅
height=720 # 保存時の動画高さ
fps=6 # 入力、保存時の動画のフレームレート
output_bitrate=1024 # 保存時のビットレート
output_vieoname='output.mp4' # 保存動画ファイルのパス

command1 = ['ffmpeg',
           '-loglevel', 'quiet',
           '-i', '{}'.format(input_videoname),
           '-f', 'rawvideo',
           '-pix_fmt', 'bgr24',
           '-vcodec', 'rawvideo',
           '-r', '{}'.format(fps),
           '-'
           ]

command2 = ['ffmpeg',
            '-y',
            '-loglevel', 'quiet',
            '-f', 'rawvideo',
           '-pix_fmt', 'bgr24',
           '-vcodec', 'rawvideo',
           '-s', '{}x{}'.format(width, height),
           '-r', '{}'.format(fps),
           '-i', '-',
           '-pix_fmt', 'yuv420p',
           '-b:v', '{}k'.format(output_bitrate),
           '{}'.format(output_vieoname)
           ]

p1 = subprocess.Popen(command1, stdout=subprocess.PIPE, shell=False)
p2 = subprocess.Popen(command2, stdin=subprocess.PIPE, shell=False)

while True:
    start = time.time()
    in_bytes = p1.stdout.read(width*height*3)
    if len(in_bytes) == 0:
        print('break')
        break

    frame = np.frombuffer(in_bytes, np.uint8).reshape([height, width, 3])
    p2.stdin.write(frame.astype(np.uint8).tobytes())
    print(time.time()-start)

4.PythonでFFmpegを使用してRTSPでカメラ映像取得・処理

 PythonでFFmpegを使用してRTSPでカメラ映像取得・処理する際には下記のプログラムを用います。TCPにて取得するため、「'-rtsp_transport', 'tcp'」を追加します。

ここから先は

3,034字

¥ 500

この記事が気に入ったらサポートをしてみませんか?