静止画像については以前に2つ記事書いてます
https://qiita.com/studio_haneya/items/a50847be3891daa8e2f8
https://qiita.com/studio_haneya/items/111f0975eae6fdecb1aa
1. インストールとimport
pipで入ります
pip install opencv-python
importするときはcv2で呼びます
import cv2
2. 動画を読み込む
今回は「C0001.MP4」という名前のファイルを加工したいと思います
path = './C0001.MP4'
cap = cv2.VideoCapture(path)
cap
cv2.VideoCaptureはカメラからリアルタイムで取得するのにも使えるようです
https://note.nkmk.me/python-opencv-videocapture-file-camera/
3. 動画の情報を取得
cap.get()で動画の情報を取得できます
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
print("size: ({}, {}), fps: {:1.2f}".format(width, height, fps))
frame_num = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
play_time = frame_num / fps / 60
print('{} frames, {:1.1f} minutes'.format(frame_num, play_time))
4. 1フレームずつ画像を取得する
cv2.VideoCapture.read()を呼ぶ度に1フレームずつ読みだしてくれます
for k in range(3):
ret, img = cap.read()
if ret:
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()
5. 動画を加工して保存する
cv2.VideoWriterクラスをつくり、write()メソッドに1フレームずつ渡せば書き出してくれます
# 書き出し用のWriteクラスを作成
fmt = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
writer = cv2.VideoWriter('./hoge.mp4', fmt, fps, (width, height),0)
while(True):
# 1フレームずつ読み込み
ret, img = cap.read()
# 動画の最後までいったらretがFalseになるので終了する
if not ret:
break
# 画像をグレースケールに加工
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 1フレーム分を書き出し
writer.write(img_gray)
# 読み込んだ動画と書き出し先の動画を解放する
cap.release()
writer.release()
imgはnp.arrayなので、python版のOpenCVで静止画像と同様に扱えます
6. 動画に音声を付けて保存する
2021年12月リリースのOpenCV 4.5.5では音声も扱えるようになったらしいんですが、該当するドキュメントが見つけられませんでしたので、従来通り別ライブラリに音声部分を追加してもらうやり方をやろうと思います。ここではmoviepyを使いました。
6-1. moviepyのインストール手順など
moviepyのインストール手順はこちら
https://pypi.org/project/moviepy/
moviepyのドキュメントはこちら
https://zulko.github.io/moviepy/getting_started/quick_presentation.html
moviepyはffmpegなどを使って動く為か上手く入らないことがあるようです。僕の場合はpip install moviepy -Iしたら直りました。
6-2. 動画全体を編集する場合
以下ではmoviepy.editor.VideoFileClipで動画ファイルを読み込んで音声トラックを書き出しておいて、先ほど書き出したhoge.mp4に追加してhoge2.mp4として書き出しています。
import moviepy.editor as mp
# 音声トラックを書き出す
clip_input = mp.VideoFileClip(path)
clip_input.audio.write_audiofile('./audio.mp3')
# 音声トラックを動画に追加する
clip = mp.VideoFileClip("./hoge.mp4").subclip()
clip.write_videofile("./hoge2.mp4", audio='./audio.mp3')
6-3. 動画の一部を編集する場合
まず開始フレームと終了フレームを決めて、開始時間と終了時間を算出しておきます
start_frame = 10000
end_frame = 11000
start_time = start_frame / fps
end_time = end_frame / fps
print('{}フレーム({:1.3f}秒)から{}フレーム({:1.3f}秒)まで切り出します'.format(start_frame, start_time, end_frame, end_time))
cap.set()で開始フレームに移動して、終了フレームまでを書き出します
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
fmt = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
writer = cv2.VideoWriter('./hoge.mp4', fmt, fps, (width, height), 0)
for _ in tqdm(range(end_frame - start_frame + 1)):
ret, img = cap.read()
if not ret:
break
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
writer.write(img_gray)
cap.release()
writer.release()
moviepyはsubclip()で開始時間と終了時間を指定するとトリミングしてくれるので、書き出したい範囲の音声トラックを書き出すことが出来ます。
# 音声トラックを書き出す
clip = mp.VideoFileClip("./hoge.mp4").subclip()
clip_input = mp.VideoFileClip(path).subclip(start_time, end_time)
clip_input.audio.write_audiofile('./audio.mp3')
# 音声トラックを動画に追加する
clip.write_videofile("./hoge2.mp4", audio='./audio.mp3')
フレームと時間で微妙にずれそうな気もしますが、フレーム単位で指定する方法が見つかりませんでした
参考にしたページなど
音声を付けて動画書き出しする手順を紹介しているサイト
https://kp-ft.com/684