OpenCV で動画を編集し、音声つきで保存する

OpenCV で動画を編集して、音声つきで保存する方法について投稿する。まず元ファイルから音声無しの編集済動画( out.mp4 )を作る。次に元ファイルから音声を抽出して、動画と繋げて音声つきの動画にする。

作成した動画

作成した動画、といっても元の動画と同じ。音声がついていて、かつ mkimg 関数(ユーザー定義関数)にて動画の編集・変更が可能だという点に、技術的な意味がある。

コード概要

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 に加工したフレームを渡す。

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)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)