OpenCV で動画を編集して、音声つきで保存する方法について投稿する。まず元ファイルから音声無しの編集済動画( out.mp4 )を作る。次に元ファイルから音声を抽出して、動画と繋げて音声つきの動画にする。
作成した動画
作成した動画、といっても元の動画と同じ。音声がついていて、かつ mkimg 関数(ユーザー定義関数)にて動画の編集・変更が可能だという点に、技術的な意味がある。
コード概要
大きな流れは下記。
- 元ファイルから、音声無しの加工動画を作る
- 元ファイルから、音声を取り出す
- 1.の加工動画と、2の音声を連結し、音声付きの加工動画にする
VideoWriter のセットアップ
まずは、音声無しの動画を作る。そのセットアップをする。動画の幅・高さ・総フレーム数・フレームレートを取得し、cv2.VideoWriter に教えてあげる。
video = cv2.VideoCapture(srcfile)
# 幅と高さを取得
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
size = (width, height)
#総フレーム数/フレームレートを取得
frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
frame_rate = int(video.get(cv2.CAP_PROP_FPS))
# 保存用
fmt = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
writer = cv2.VideoWriter(imgfile, fmt, frame_rate, size)
画像の編集
音声無しの加工動画を作る。video.read() でフレームを1枚ずつ読み、 mkimg 関数(ユーザー定義関数)にて適当にフレームを加工する。 writer.write に加工したフレームを渡す。
for i in range(frame_count):
ret, frame = video.read()
write_frame = mkimg(frame)
writer.write(write_frame)
音声つきにする
最後に、 set_audio 関数(ユーザー定義関数)を呼び出して、映像と音声を連結する。set_audio 関数は、元のファイルから音声を抽出して、それを過去済みの映像ファイルに追加する機能を持つ。
def set_audio(srcfile,imgfile,outfile):
# Extract audio from input video.
clip_input = mp.VideoFileClip(srcfile)
clip_input.audio.write_audiofile('audio.mp3')
# Add audio to output video.
clip = mp.VideoFileClip(imgfile).subclip()
clip.write_videofile(outfile, audio='audio.mp3')
コード全文
引数にファイル名を渡すと動く。
import cv2
import sys
import numpy as np
import moviepy.editor as mp
# 画像を加工する
def mkimg(img):
# ここに変更を記述する
return img
# 動画関連 -------------------------------------------------------------
def set_audio(srcfile,imgfile,outfile):
# Extract audio from input video.
clip_input = mp.VideoFileClip(srcfile)
clip_input.audio.write_audiofile('audio.mp3')
# Add audio to output video.
clip = mp.VideoFileClip(imgfile).subclip()
clip.write_videofile(outfile, audio='audio.mp3')
# 動画のファイル名 設定
srcfile = sys.argv[1]
imgfile = "out.mp4"
outfile = sys.argv[1].replace(".mp4","out.mp4").replace(".MP4","out.MP4")
video = cv2.VideoCapture(srcfile)
# 幅と高さを取得
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
size = (width, height)
#総フレーム数/フレームレートを取得
frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
frame_rate = int(video.get(cv2.CAP_PROP_FPS))
# 保存用
fmt = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
writer = cv2.VideoWriter(imgfile, fmt, frame_rate, size)
for i in range(frame_count):
ret, frame = video.read()
write_frame = mkimg(frame)
writer.write(write_frame)
cv2.imshow("Frame", frame)
cv2.imshow("newf", write_frame)
cv2.moveWindow("newf",3700,0)
# qキーが押されたら途中終了
if cv2.waitKey(25) & 0xFF == ord('q'):
break
writer.release()
video.release()
cv2.destroyAllWindows()
# 最後に音をつける
set_audio(srcfile,imgfile,outfile)
コメント