[Python] opencvで動画を範囲時間でトリミングする方法
PythonでOpenCVを使用して動画を範囲時間でトリミングするには、まずcv2.VideoCapture
で動画を読み込み、fps
(フレームレート)を取得します。
次に、開始時間と終了時間を指定し、それに基づいてフレーム番号を計算します。
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
で開始フレームに移動し、指定した範囲のフレームをcv2.VideoWriter
で保存します。
動画トリミングの基本
動画トリミングは、特定の時間範囲を選択して動画の一部を切り出すプロセスです。
これにより、不要な部分を削除したり、特定のシーンを強調したりすることができます。
PythonのOpenCVライブラリを使用することで、簡単に動画をトリミングすることが可能です。
OpenCVは画像処理やコンピュータビジョンに特化したライブラリで、動画の読み込み、フレームの操作、保存などの機能を提供しています。
本記事では、OpenCVを用いて動画を範囲時間でトリミングする方法を詳しく解説します。
OpenCVで動画を読み込む方法
OpenCVを使用して動画を扱うためには、まず動画ファイルを読み込む必要があります。
以下に、動画を読み込むための基本的な手順を示します。
cv2.VideoCaptureの使い方
cv2.VideoCapture
は、動画ファイルを読み込むためのクラスです。
以下のサンプルコードでは、動画ファイルを読み込み、最初のフレームを表示します。
import cv2
# 動画ファイルのパスを指定
video_path = 'sample_video.mp4'
# VideoCaptureオブジェクトを作成
cap = cv2.VideoCapture(video_path)
# 動画が正常にオープンできたか確認
if not cap.isOpened():
print("動画ファイルを開けませんでした。")
else:
# 最初のフレームを読み込む
ret, frame = cap.read()
if ret:
cv2.imshow('First Frame', frame)
cv2.waitKey(0) # キー入力待ち
cap.release() # リソースを解放
cv2.destroyAllWindows() # ウィンドウを閉じる
このコードを実行すると、指定した動画の最初のフレームが表示されます。
動画のフレーム数とfpsの取得
動画のフレーム数やフレームレート(fps)を取得するには、cv2.VideoCapture
のメソッドを使用します。
以下のサンプルコードでは、動画のフレーム数とfpsを取得して表示します。
import cv2
video_path = 'sample_video.mp4'
cap = cv2.VideoCapture(video_path)
# フレーム数を取得
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# fpsを取得
fps = cap.get(cv2.CAP_PROP_FPS)
print(f"フレーム数: {frame_count}")
print(f"フレームレート: {fps} fps")
cap.release()
このコードを実行すると、動画のフレーム数とフレームレートがコンソールに表示されます。
動画の解像度やプロパティの確認
動画の解像度やその他のプロパティを確認するには、cv2.VideoCapture
のメソッドを使用します。
以下のサンプルコードでは、動画の幅、高さ、コーデックを取得して表示します。
import cv2
video_path = 'sample_video.mp4'
cap = cv2.VideoCapture(video_path)
# 幅と高さを取得
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# コーデックを取得
codec = int(cap.get(cv2.CAP_PROP_FOURCC))
print(f"解像度: {width} x {height}")
print(f"コーデック: {codec}")
cap.release()
このコードを実行すると、動画の解像度とコーデック情報が表示されます。
コーデックは数値で表示されるため、必要に応じて変換が必要です。
動画の範囲指定とトリミングの手順
動画をトリミングするためには、まずトリミングしたい範囲を指定する必要があります。
以下に、開始時間と終了時間の指定方法やフレーム番号の計算方法について解説します。
開始時間と終了時間の指定方法
トリミングを行うためには、動画の開始時間と終了時間を指定します。
時間は秒単位で指定することが一般的です。
以下のサンプルコードでは、開始時間と終了時間を設定します。
# トリミングの開始時間(秒)
start_time = 10 # 10秒から
# トリミングの終了時間(秒)
end_time = 20 # 20秒まで
フレーム番号の計算方法
動画のフレーム数はフレームレート(fps)によって決まります。
開始時間と終了時間からフレーム番号を計算するには、以下の式を使用します。
以下のサンプルコードでは、開始時間と終了時間からフレーム番号を計算します。
# フレームレートを取得(例: 30 fps)
fps = 30
# 開始フレームと終了フレームを計算
start_frame = int(start_time * fps)
end_frame = int(end_time * fps)
print(f"開始フレーム: {start_frame}, 終了フレーム: {end_frame}")
cv2.CAP_PROP_POS_FRAMESでフレーム位置を指定
OpenCVでは、cv2.CAP_PROP_POS_FRAMES
を使用して、動画の特定のフレーム位置に移動することができます。
以下のサンプルコードでは、計算した開始フレームに移動し、トリミングを開始します。
import cv2
video_path = 'sample_video.mp4'
cap = cv2.VideoCapture(video_path)
# 開始フレームに移動
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
# トリミングのためのフレームを取得
for frame_number in range(start_frame, end_frame):
ret, frame = cap.read()
if not ret:
break
# フレームを処理(例: 表示や保存など)
cv2.imshow('Frame', frame)
cv2.waitKey(30) # 30ms待機
cap.release()
cv2.destroyAllWindows()
指定範囲のフレームを取得する方法
指定した範囲のフレームを取得するには、for
ループを使用して、開始フレームから終了フレームまでのフレームを順に読み込みます。
上記のコード例では、開始フレームから終了フレームまでのフレームを取得し、表示しています。
必要に応じて、取得したフレームを保存することも可能です。
トリミングした動画の保存
トリミングした動画を保存するためには、OpenCVのcv2.VideoWriter
を使用します。
以下に、動画の保存方法について詳しく解説します。
cv2.VideoWriterの使い方
cv2.VideoWriter
は、動画ファイルを作成するためのクラスです。
動画の保存には、出力ファイル名、フレームレート、解像度、コーデックを指定する必要があります。
以下のサンプルコードでは、cv2.VideoWriter
を使用して動画を保存する準備をします。
import cv2
# 出力ファイル名
output_path = 'trimmed_video.mp4'
# フレームレート
fps = 30
# 解像度(幅と高さ)
width = 640
height = 480
# VideoWriterオブジェクトを作成
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # コーデックの指定
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
このコードでは、mp4v
コーデックを使用して、指定した解像度とフレームレートで動画を保存するためのVideoWriter
オブジェクトを作成しています。
保存する動画のフォーマットとコーデックの指定
動画のフォーマットとコーデックは、出力ファイルの品質や互換性に影響を与えます。
一般的なフォーマットとコーデックの組み合わせは以下の通りです。
フォーマット | コーデック | 説明 |
---|---|---|
.mp4 | mp4v | 高品質で広く使われる |
.avi | XVID | 古いフォーマットだが互換性が高い |
.mov | MJPG | Apple製品でよく使われる |
適切なフォーマットとコーデックを選択することで、動画の再生や編集がスムーズになります。
トリミングした動画の書き出し
トリミングした動画を保存するには、取得したフレームをVideoWriter
オブジェクトに書き出します。
以下のサンプルコードでは、トリミングしたフレームを保存する方法を示します。
import cv2
video_path = 'sample_video.mp4'
output_path = 'trimmed_video.mp4'
cap = cv2.VideoCapture(video_path)
# フレームレートと解像度を取得
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))
# VideoWriterオブジェクトを作成
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# トリミング範囲を指定
start_frame = 300 # 例: 300フレームから
end_frame = 600 # 例: 600フレームまで
# 開始フレームに移動
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
# 指定範囲のフレームを取得して保存
for frame_number in range(start_frame, end_frame):
ret, frame = cap.read()
if not ret:
break
out.write(frame) # フレームを書き出す
# リソースを解放
cap.release()
out.release()
このコードを実行すると、指定した範囲のフレームがtrimmed_video.mp4
として保存されます。
VideoWriter
オブジェクトを使用することで、トリミングした動画を簡単に書き出すことができます。
エラーハンドリングと注意点
動画をトリミングする際には、さまざまなエラーが発生する可能性があります。
ここでは、一般的なエラーハンドリングの方法と注意点について解説します。
動画ファイルが読み込めない場合の対処法
動画ファイルが正しく読み込めない場合、cv2.VideoCapture
のisOpened()メソッド
を使用して、ファイルが正常にオープンできたかを確認することが重要です。
以下のサンプルコードでは、動画ファイルが読み込めない場合の対処法を示します。
import cv2
video_path = 'invalid_video.mp4'
cap = cv2.VideoCapture(video_path)
# 動画が正常にオープンできたか確認
if not cap.isOpened():
print("エラー: 動画ファイルを開けませんでした。ファイルパスを確認してください。")
else:
# 動画処理を続行
pass
cap.release()
このように、ファイルが開けない場合にはエラーメッセージを表示し、処理を中断することが推奨されます。
フレーム範囲が動画の長さを超える場合の処理
指定したフレーム範囲が動画の長さを超える場合、プログラムがエラーを引き起こす可能性があります。
これを防ぐために、フレーム数を確認し、範囲が有効かどうかをチェックすることが重要です。
以下のサンプルコードでは、フレーム範囲のチェックを行います。
import cv2
video_path = 'sample_video.mp4'
cap = cv2.VideoCapture(video_path)
# フレーム数を取得
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# トリミング範囲を指定
start_frame = 300
end_frame = 600
# フレーム範囲が有効か確認
if start_frame < 0 or end_frame > frame_count or start_frame >= end_frame:
print("エラー: 指定したフレーム範囲が無効です。")
else:
# トリミング処理を続行
pass
cap.release()
このように、フレーム範囲が無効な場合にはエラーメッセージを表示し、処理を中断することが重要です。
コーデックやフォーマットの互換性に関する注意点
動画のコーデックやフォーマットは、再生や編集の互換性に影響を与えます。
特に、異なるプラットフォームやデバイスで動画を再生する場合、適切なコーデックを選択することが重要です。
以下の点に注意してください。
- コーデックの選択: 一般的に使用されるコーデック(例:
mp4v
,XVID
,MJPG
)を選ぶことで、互換性を高めることができます。 - フォーマットの確認: 出力フォーマット(例:
.mp4
,.avi
,.mov
)が再生環境でサポートされているか確認してください。 - テスト再生: 動画を保存した後、異なるプレーヤーやデバイスで再生して、互換性を確認することが推奨されます。
これらの注意点を考慮することで、トリミングした動画がスムーズに再生されることを確保できます。
応用例:複数の範囲でトリミングする
動画トリミングの応用として、複数の範囲を指定してトリミングしたり、トリミングした動画を結合したりする方法を解説します。
また、特定のフレームにフィルタを適用する方法についても触れます。
複数の時間範囲を指定してトリミング
複数の時間範囲を指定してトリミングするには、各範囲をリストに格納し、ループを使用してそれぞれの範囲を処理します。
以下のサンプルコードでは、2つの範囲を指定してトリミングを行います。
import cv2
video_path = 'sample_video.mp4'
output_path = 'trimmed_video.mp4'
cap = cv2.VideoCapture(video_path)
# トリミング範囲を指定(秒単位)
time_ranges = [(5, 10), (15, 20)] # 5-10秒と15-20秒をトリミング
# VideoWriterオブジェクトを作成
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
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))
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
for start_time, end_time in time_ranges:
start_frame = int(start_time * fps)
end_frame = int(end_time * fps)
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
for frame_number in range(start_frame, end_frame):
ret, frame = cap.read()
if not ret:
break
out.write(frame) # フレームを書き出す
cap.release()
out.release()
このコードを実行すると、指定した時間範囲のフレームがtrimmed_video.mp4
として保存されます。
トリミングした複数の動画を結合する方法
トリミングした複数の動画を結合するには、cv2.VideoWriter
を使用して新しい動画ファイルに書き出すことができます。
以下のサンプルコードでは、2つのトリミングした動画を結合します。
import cv2
# トリミングした動画のパス
video_paths = ['trimmed_video1.mp4', 'trimmed_video2.mp4']
output_path = 'combined_video.mp4'
# VideoWriterオブジェクトを作成
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
fps = 30 # 結合後のフレームレート
width = 640 # 幅
height = 480 # 高さ
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
for video_path in video_paths:
cap = cv2.VideoCapture(video_path)
while True:
ret, frame = cap.read()
if not ret:
break
out.write(frame) # フレームを書き出す
cap.release() # リソースを解放
out.release() # 最後にVideoWriterを解放
このコードを実行すると、指定したトリミングした動画が結合され、combined_video.mp4
として保存されます。
特定のフレームにフィルタを適用してトリミング
トリミングした動画の特定のフレームにフィルタを適用することも可能です。
以下のサンプルコードでは、トリミングしたフレームにグレースケールフィルタを適用します。
import cv2
video_path = 'sample_video.mp4'
output_path = 'filtered_video.mp4'
cap = cv2.VideoCapture(video_path)
# VideoWriterオブジェクトを作成
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
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))
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# トリミング範囲を指定
start_frame = 100
end_frame = 200
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
for frame_number in range(start_frame, end_frame):
ret, frame = cap.read()
if not ret:
break
# グレースケールフィルタを適用
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
out.write(gray_frame) # フィルタを適用したフレームを書き出す
cap.release()
out.release()
このコードを実行すると、指定した範囲のフレームにグレースケールフィルタが適用され、filtered_video.mp4
として保存されます。
フィルタを変更することで、さまざまなエフェクトを適用することができます。
応用例:トリミングと同時に動画を加工する
動画をトリミングする際に、同時にリサイズや回転、テキストや画像の挿入を行うことができます。
以下に、それぞれの方法について解説します。
トリミングしながらリサイズする方法
動画をトリミングしながらリサイズするには、cv2.resize関数
を使用します。
以下のサンプルコードでは、トリミングしたフレームを指定した解像度にリサイズします。
import cv2
video_path = 'sample_video.mp4'
output_path = 'resized_trimmed_video.mp4'
cap = cv2.VideoCapture(video_path)
# VideoWriterオブジェクトを作成
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
fps = cap.get(cv2.CAP_PROP_FPS)
width = 320 # リサイズ後の幅
height = 240 # リサイズ後の高さ
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# トリミング範囲を指定
start_frame = 100
end_frame = 200
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
for frame_number in range(start_frame, end_frame):
ret, frame = cap.read()
if not ret:
break
# フレームをリサイズ
resized_frame = cv2.resize(frame, (width, height))
out.write(resized_frame) # リサイズしたフレームを書き出す
cap.release()
out.release()
このコードを実行すると、指定した範囲のフレームがリサイズされ、resized_trimmed_video.mp4
として保存されます。
トリミングしながら回転や反転を行う方法
トリミングしたフレームに回転や反転を適用することも可能です。
以下のサンプルコードでは、フレームを90度回転させ、さらに上下反転を行います。
import cv2
video_path = 'sample_video.mp4'
output_path = 'rotated_trimmed_video.mp4'
cap = cv2.VideoCapture(video_path)
# VideoWriterオブジェクトを作成
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
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))
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# トリミング範囲を指定
start_frame = 100
end_frame = 200
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
for frame_number in range(start_frame, end_frame):
ret, frame = cap.read()
if not ret:
break
# フレームを90度回転
rotated_frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
# フレームを上下反転
flipped_frame = cv2.flip(rotated_frame, 0)
out.write(flipped_frame) # 加工したフレームを書き出す
cap.release()
out.release()
このコードを実行すると、指定した範囲のフレームが回転・反転され、rotated_trimmed_video.mp4
として保存されます。
トリミングしながらテキストや画像を挿入する方法
トリミングしたフレームにテキストや画像を挿入することもできます。
以下のサンプルコードでは、フレームにテキストを追加します。
import cv2
video_path = 'sample_video.mp4'
output_path = 'text_inserted_video.mp4'
cap = cv2.VideoCapture(video_path)
# VideoWriterオブジェクトを作成
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
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))
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# トリミング範囲を指定
start_frame = 100
end_frame = 200
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
for frame_number in range(start_frame, end_frame):
ret, frame = cap.read()
if not ret:
break
# フレームにテキストを挿入
cv2.putText(frame, 'トリミング中', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
out.write(frame) # テキストを挿入したフレームを書き出す
cap.release()
out.release()
このコードを実行すると、指定した範囲のフレームに「トリミング中」というテキストが挿入され、text_inserted_video.mp4
として保存されます。
画像を挿入する場合は、cv2.addWeighted
やcv2.add
を使用して、フレームに画像を重ねることができます。
応用例:GUIを使った動画トリミングツールの作成
PythonのTkinterライブラリを使用して、動画トリミングツールのGUIを作成することができます。
以下に、簡単なGUIの作成方法や動画のプレビュー機能、範囲指定の方法について解説します。
Tkinterを使った簡単なGUIの作成
Tkinterを使用して、基本的なウィンドウを作成します。
以下のサンプルコードでは、ウィンドウを作成し、タイトルを設定します。
import tkinter as tk
def create_gui():
# メインウィンドウを作成
root = tk.Tk()
root.title("動画トリミングツール")
root.geometry("400x200") # ウィンドウサイズ
# ラベルを追加
label = tk.Label(root, text="動画トリミングツール", font=("Arial", 16))
label.pack(pady=20) # 上下の余白を設定
# ウィンドウを表示
root.mainloop()
create_gui()
このコードを実行すると、シンプルなウィンドウが表示されます。
これを基に、さらに機能を追加していきます。
動画のプレビュー機能を追加する
動画のプレビュー機能を追加するには、OpenCVを使用して動画を読み込み、TkinterのCanvasウィジェットに表示します。
以下のサンプルコードでは、動画をプレビューするための関数を追加します。
import cv2
import tkinter as tk
from PIL import Image, ImageTk
def play_video(video_path, canvas):
cap = cv2.VideoCapture(video_path)
def update_frame():
ret, frame = cap.read()
if ret:
# BGRからRGBに変換
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = Image.fromarray(frame)
img_tk = ImageTk.PhotoImage(image=img)
canvas.create_image(0, 0, anchor=tk.NW, image=img_tk)
canvas.img_tk = img_tk # 参照を保持
canvas.after(10, update_frame) # 10ms後に次のフレームを更新
update_frame()
def create_gui():
root = tk.Tk()
root.title("動画トリミングツール")
root.geometry("640x480")
canvas = tk.Canvas(root, width=640, height=360)
canvas.pack()
# 動画のパスを指定
video_path = 'sample_video.mp4'
play_video(video_path, canvas)
root.mainloop()
create_gui()
このコードを実行すると、指定した動画がウィンドウ内でプレビューされます。
範囲指定をGUIで行う方法
範囲指定をGUIで行うために、開始時間と終了時間を入力するためのエントリーウィジェットを追加します。
以下のサンプルコードでは、ユーザーが開始時間と終了時間を入力できるようにします。
import cv2
import tkinter as tk
from PIL import Image, ImageTk
def play_video(video_path, canvas):
cap = cv2.VideoCapture(video_path)
def update_frame():
ret, frame = cap.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = Image.fromarray(frame)
img_tk = ImageTk.PhotoImage(image=img)
canvas.create_image(0, 0, anchor=tk.NW, image=img_tk)
canvas.img_tk = img_tk
canvas.after(10, update_frame)
update_frame()
def trim_video(start_time, end_time):
# トリミング処理をここに実装
print(f"トリミング範囲: {start_time}秒から{end_time}秒まで")
def create_gui():
root = tk.Tk()
root.title("動画トリミングツール")
root.geometry("640x480")
canvas = tk.Canvas(root, width=640, height=360)
canvas.pack()
# 動画のパスを指定
video_path = 'sample_video.mp4'
play_video(video_path, canvas)
# 開始時間と終了時間の入力フィールド
start_label = tk.Label(root, text="開始時間(秒):")
start_label.pack()
start_entry = tk.Entry(root)
start_entry.pack()
end_label = tk.Label(root, text="終了時間(秒):")
end_label.pack()
end_entry = tk.Entry(root)
end_entry.pack()
# トリミングボタン
trim_button = tk.Button(root, text="トリミング", command=lambda: trim_video(float(start_entry.get()), float(end_entry.get())))
trim_button.pack()
root.mainloop()
create_gui()
このコードを実行すると、ユーザーが開始時間と終了時間を入力できるエントリーウィジェットが追加され、トリミングボタンを押すことで指定した範囲をトリミングする処理を呼び出すことができます。
トリミング処理の実装は、前述のトリミング手法を参考にしてください。
まとめ
この記事では、PythonのOpenCVを使用して動画をトリミングする方法について詳しく解説しました。
具体的には、動画の読み込みからトリミング、保存、さらにはGUIを使ったツールの作成まで、幅広い内容を取り上げました。
これを機に、実際に自分の動画をトリミングしてみたり、さまざまな加工を施したりすることで、動画編集のスキルを向上させてみてはいかがでしょうか。