動画編集には、撮影された2つ以上の動画を組み合わせて様々な効果を出す方法があります。ここではPythonのOpenCVを使って簡単に動画の連結をする方法を紹介します。
こんにちは。wat(@watlablog)です。
Pythonを使えば楽々と動画連結も可能です!ここでは複数の動画を時間方向に連結する方法を紹介します!
動画連結の概要と得られる効果
動画連結の解説(図解)
まず初めに、今回作成する動画連結プログラムの図解説明を行います。
動画連結は2つ以上の複数の動画を使いますが、各動画ファイルはそれぞれ横軸を時間に取ると有限のフレームで構成されていることになります。
以下の図は、N個のフレームから成る「movie1.mp4」とM個のフレームから成る「movie2.mp4」という2つの動画ファイルを連結してN+M個のフレームを持つ「movie_out.mp4」を作成している図です。
今回は単純に繋げましたというプログラムを作ります。
動画を連結させることでシーンの切り替えを表現することができる
動画連結技術は映画やドラマ等ではお馴染みの「シーン切り替え」で多用されていますね。
場所が変わったり、役者を交互に移したりといった演出は多数の動画を切ったり連結したりを繰り返している処理をしています。
外部のサイト様ですが、これらの動画編集テクニックがわかりやすく解説されているページがありました。僕も参考にしたいので以下にリンクを貼らせて頂きます。
外部リンク:11のクリエイティブな動画編集テクニック
ジャンプカット、クロスディゾルブ…様々な種類があるんですね!
Pythonで動画連結するコード
連結する2つのサンプル動画
以下の2つの動画「movie1.mp4」と「movie2.mp4」を単純に連結させ、元動画に対し動体検知処理をした場合の変化を1つの動画で表現してみます。
movie1.mp4
ちなみにこの動画ファイルは「Python/OpenCVでWebカメラ!撮影した動画を保存する」で保存したファイルです。
movie2.mp4
こちらの動画は「Python/OpenCVで動体検知!動画の動いている部分を検出」で処理した結果です。上「movie1.mp4」に対して動いている部分を検出し白くマスクをかけたものです。
複数動画を連結させるプログラムの全コード
以下が動画を連結させるための全コードです。m_combineという関数内で連結をしています。
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 |
import cv2 # 複数動画を連結させる関数 def m_combine(movie_info, path_out, scale_factor): i = 0 # 動画数カウント用指標iを用意 # 動画数分ループを回す for j in movie_info: # 動画情報([path, T/F])をjに格納 path = j[0] # 動画ファイルへのパス color_flag = j[1] # カラーかどうかをフラグ # 動画読み込みの設定 movie = cv2.VideoCapture(path) # 動画ファイル保存用の設定 fps = int(movie.get(cv2.CAP_PROP_FPS)) # 元動画のFPSを取得 fps_new = int(fps * scale_factor) # 動画保存時のFPSはスケールファクターをかける w = int(movie.get(cv2.CAP_PROP_FRAME_WIDTH)) # 動画の横幅を取得 h = int(movie.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 動画の縦幅を取得 fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') # 動画保存時のfourcc設定(mp4用) # 最初だけvideoを定義(連結させるため) if i == 0: video = cv2.VideoWriter(path_out, fourcc, fps_new, (w, h), color_flag) # 動画の仕様 else: pass i = i + 1 # iを増分(動画連結数カウント) # ファイルからフレームを1枚ずつ取得して動画処理後に保存する while True: ret, frame = movie.read() # フレームを取得 video.write(frame) # 動画を保存する # フレームが取得できない場合はループを抜ける if not ret: break # 動画数分のループが終了した最後に、撮影用オブジェクトとウィンドウの解放 movie.release() return # ここからメイン実行文 movie1 = ['movie1.mp4', True] # 元動画のパス1, カラーはTrue movie2 = ['movie2.mp4', False] # 元動画のパス2, 白黒はFalse path_out = 'movie_out.mp4' # 保存する動画のパス scale_factor = 1 # FPSにかけるスケールファクター movie_info = [movie1, movie2] # 動画情報を配列にまとめる # 複数動画を連結させる関数を実行 m_combine(movie_info, path_out, scale_factor) |
「# ここからメイン実行文」と書いてある部分で引数の設定をして関数を実行するスタイルですが、movie1とmovie2の変数にはそれぞれ動画ファイルの情報をタプルで入れています。
最初の情報は動画ファイルへのパスで、プログラムの実行ディレクトリに動画ファイルが入っている時はファイル名のみの記載で構いません。
二つ目のTrueとFalseはカラー動画であればTrue、それ以外であればFalseを記載します。通常Webカメラやスマホで撮影した動画はカラー画像なのですが、動体検知等画像処理を施してから動画を作成すると白黒の動画を作るということが多々あるため、このような引数の構成にしています。
scale_factorは動画の再生速度にかける係数です。「Python/OpenCVで動画速度(FPS)を変えて再保存」の記事で取り扱った内容ですが、割と使えるのでそのまま残しています。
m_combine関数は基本これまで紹介した記事に記載のコードと同じ方法で動画の読み込み、書き込みをしていますが、今回は複数の動画を同時に取り扱うため、for文を使って動画ファイル個数分の読み込みと書き込み処理をしています。
iは最初のループで0となり、2回目以降のループではそれ以外の値になっていればよかったので正直毎ループで増分させる必要はなかったのですが、他に意味のある数値が思いつかなかったためこうしています(混乱させてしまったらスミマセン…)。
複数動画の処理中に毎回videoの定義とmovie.release()までやってしまうと、複数動画は連結されずに最後の元動画がもう一つできるだけのプログラムになってしまうので、if文で処理しているというロジックになります。
実行結果
以下が動画連結の結果です。約8[s]過ぎくらいから動画が切り替わっていることが確認できると思います。
まとめ
今回は複数の動画を連結させるというコードを説明、紹介しました。コードの実行結果はWebカメラで撮影した動画とその動画に対して動体検知をした結果を1つの動画内で切り替えるというものです。
このコードを使えば単純に場面の切り替えを表現することができるようになりますので、是非使ってみて下さい。
動画の連結を習得しました!連結時の演出も今後プログラムできるようにしていきたいな!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!
コメント