見出し画像

【Python】moviepyで動画のトリミングとビットレート指定のエンコード

【状況】大きな動画から必要な部分を切り抜いて再エンコードしたい.さらに,元のビットレートだと高すぎるので調整してエンコードしたい.
【対処】切り抜きはmoviepyで簡単にできるものの,moviepy 1.0.3ではビットレートを取得できなかった(できなくなっていた?)のでOpenCVを使ってみた,のメモ(githubで議論はあったけどよく分からず).

moviepyを導入

切り抜きが簡単にできるmoviepyをインストール.執筆時点のバージョンは1.0.3.

pip install moviepy

OpenCVでビットレート取得

一番手間がかからなかったのがOpenCVを使った方法(なんかモヤモヤするけど.ffmpegを使う方法もある).

from moviepy.editor import VideoFileClip
from moviepy.video.fx.all import crop
import cv2

# 元の動画のビットレートを取得(OpenCV利用)
def get_bitrate(file_path):                     # ファイルパスを引数とする
    cap = cv2.VideoCapture(file_path)   
    bitrate = cap.get(cv2.CAP_PROP_BITRATE)     # 動画のビットレートを取得(単位:k)
    cap.release()
    return bitrate

# 元の動画ファイルから切り抜いて,指定したビットレートでエンコードする
def crop_and_encode(input_file, x1, y1, x2, y2, output_file, new_bitrate):
    video = VideoFileClip(input_file)  

    # x2, y2を1ずつ増やさないと意図通りの切り抜きがされない(moviepy1.0.3)
    clip = video.fx(crop, x1=x1, y1=y1, x2=x2+1, y2=y2+1)  
    
    # ビットレートを指定して切り抜きをエンコード
    clip.write_videofile(output_file, codec='libx264', bitrate=f"{bitrate}k")  

if __name__ == "__main__":
    input_file = "input.mp4"    # 入力動画ファイル名
    output_file = "output.mp4"  # 出力動画ファイル名
    x1, y1 = 100, 100  # 画像の左上座標
    x2, y2 = 819, 579  # 画像の右下座標

    org_bitrate = get_bitrate(video_path)
    new_bitrate = org_bitrate * 0.5 # 切り抜いた動画のビットレートを元の画像の半分にした

    # 領域の幅と高さが16の倍数になっていることが望ましい(補正処理は省略)
    crop_and_encode(input_file, x1, y1, x2, y2, output_file, new_bitrate)
    

これでできたからよし♪

※更新(2024.04.03)
クロップのパラメータ指定方法が「 x1 = x1, y1 = y1, x2 = x2, y2 = y2」のように座標値のまま与えたときに,縦横1ずつ少なく生成されていることが判
明.仕方ないので呼び出しの際に1ずつ増やしています.moviepy1.0.3時点.


いいなと思ったら応援しよう!