1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonでサクッと動画編集moviepy(v2.0)

Posted at

はじめに

 本格的な動画編集には GUI を備えた専用ソフトを使うのが適している。しかし、大量の動画を一括で結合・変換するなど、軽い操作を効率的にこなせるツールがないか探していたところ、moviepy にたどり着いた。
 動画ファイルの「カット」「分離」「結合」「テキスト挿入」「fps 変換」といった基本的な編集を、わずか数行のコードで実現できる。本記事では、そんな moviepy のユースケースをまとめて紹介する。

目次

モジュールのインストール

pip install moviepyでモジュールをインストールする。注意点としてv2.0以降(2024.11~)でモジュールの読み出し方が大きく変わっているよう。

#v2.0以降
from moviepy import VideoFileClip

#以前
from moviepy.editor import VideoFileClip

この記事で扱うモジュール

import 概要
VideoFileClip 動画ファイルを読み込み
concatenate_videoclips 複数動画を結合
vfx 効果をつける
TextClip テキストを動画化
CompositeVideoClip 複数動画を合成

戻る

動画の読み込み

 moviepy は、動画、画像でよく使われる下記フォーマットの対応をしている。その他、FFmpeg が読み書きできる形式は全て対応している。

  フォーマット
動画 .mp4 .mts(AVCHD) .mov .mkv .avi
画像 .png .jpg .gif

VideoFileClip()で動画ファイル名を指定すると動画データを読みだす。読みだしたデータの詳細情報は.reader.infosで取得できる。close()読み込んだファイルをcloseする。

from moviepy import VideoFileClip, TextClip, CompositeVideoClip
from pprint import pprint

# 動画ファイル読み込み
filename = 'input01.MTS'
videoclip = VideoFileClip(filename)

# 基本情報
print(f'{videoclip.filename=}')
print(f'{videoclip.duration=}')
print(f'{videoclip.size=}')
print(f'{videoclip.fps=}')
print(f'{videoclip.aspect_ratio=}')
# 詳細情報
pprint(videoclip.reader.infos)

# close
videoclip.close()

'''
----------
videoclip.filename='input01.MTS'  # ファイル名
videoclip.duration=31.55          # 時間[s]
videoclip.size=[1920, 1080]       # サイズ
videoclip.fps=29.97002997002997   # FPS
videoclip.aspect_ratio=1.7777777777777777 # アスペクト比
----------
{'audio_bitrate': 384,
 'audio_found': True,
 'audio_fps': 48000,
 'bitrate': 8100,
 'default_audio_input_number': 0,
 'default_audio_stream_number': 1,
 'default_video_input_number': 0,
 'default_video_stream_number': 0,
 'duration': 31.55,
 'inputs': [{'input_number': 0,
             'streams': [{'bitrate': None,
                          'codec_name': 'h264',
                          'default': True,
                          'fps': 29.97002997002997,
                          'input_number': 0,
                          'language': None,
                          'profile': '(High)',
                          'size': [1920, 1080],
                          'stream_number': 0,
                          'stream_type': 'video'},
                         {'bitrate': 384,
                          'default': True,
                          'fps': 48000,
                          'input_number': 0,
                          'language': None,
                          'stream_number': 1,
                          'stream_type': 'audio'}]}],
 'metadata': {},
 'start': 0.8347,
 'video_bitrate': None,
 'video_codec_name': 'h264',
 'video_duration': 31.55,
 'video_found': True,
 'video_fps': 29.97002997002997,
 'video_n_frames': 945,
 'video_profile': '(High)',
 'video_size': [1920, 1080]}
'''

戻る

動画の分離・結合

subclipped(start,end)で秒数を指定して切り取り分離ができる。マイナス値を指定することもできる。結合はconcatenate_videoclips([])で結合ファイルを順番にリストで指定する。最後に.write_videofile()で出力ファイル名を指定して保存する。

from moviepy import VideoFileClip, concatenate_videoclips

# 動画ファイル2ファイル読み込み
filename1 = 'input01.MTS'
videoclip1 = VideoFileClip(filename1)
filename2 = 'input02.MTS'
videoclip2 = VideoFileClip(filename2)

#カット 1. 最初~10秒
cut1 = videoclip1.subclipped(0,10)
#カット 2. 10秒前~最後
cut2 = videoclip2.subclipped(-10,videoclip2.duration)

# 結合
outclip = concatenate_videoclips([cut1,cut2])

# 保存
outclip.write_videofile('out.mp4')

videoclip1.close()
videoclip2.close()

戻る

動画に効果をつける

フェードイン、フェードアウト、0.5倍速、2倍速、モノクロなど、動画に効果をつけるときは.with_effects([効果を列挙])を使う。効果は、配列で複数列挙することもできる。

効果 指定
フェードイン vfx.FadeIn(秒数)
フェードアウト vfx.FadeOut(秒数)
倍速 vfx.MultiplySpeed(倍速値)
モノクロ vfx.BlackAndWhite()
from moviepy import VideoFileClip, vfx

# 動画ファイルファイル読み込み
filename1 = 'input01.MTS'
videoclip1 = VideoFileClip(filename1)

# フェードインフェードアウト
vfead = videoclip1.with_effects([vfx.FadeIn(2), vfx.FadeOut(2)])
vfead.write_videofile('vfead.mp4')

# 0.5倍速
slow = videoclip1.with_effects([vfx.MultiplySpeed(0.5)])
slow.write_videofile('slow.mp4')

# 2.0倍速
fast = videoclip1.with_effects([vfx.MultiplySpeed(2)])
fast.write_videofile('fast.mp4')

# モノクロ
whiteblack = videoclip1.with_effects([vfx.BlackAndWhite()])
whiteblack.write_videofile('whiteblack.mp4')

videoclip1.close()

戻る

テキスト挿入

動画の撮影日を表示するなどの場合テキスト挿入ができる。テキストを挿入する場合はTextClipを使う。その後、作ったテキストデータをCompositeVideoClipで結合する。日本語を扱う場合は、fontを指定しないと文字化けするので注意。windowsの場合は、C:\Windows\Fontsにfontが保存されているのでここから選択する。
テキストは表示開始時間、表示時間、表示位置などを指定できる。

from moviepy import VideoFileClip, TextClip, CompositeVideoClip
import os, datetime

# 動画ファイルファイル読み込み
filename1 = 'input01.MTS'
videoclip1 = VideoFileClip(filename1)

# ファイルの更新日時取得
dt = datetime.datetime.fromtimestamp(os.path.getmtime(filename1))
dt = dt.strftime("%Y年%m月%d日 %H:%M:%S")

# text
# 日本語の場合はfontを指定すること。
# with_position は 水平(left, right)、垂直(top,center,bottom)の順
txt =TextClip(font='C:\Windows\Fonts\meiryo.ttc', font_size=100,color='white',text=dt).with_start(2).with_duration(5).with_position(("right", "bottom"))


#結合
outclip = CompositeVideoClip([videoclip1,txt])

# 保存
outclip.write_videofile('text.mp4')

videoclip1.close()

戻る

動画の画面をトリミングする

動画の画面をトリミングする場合は.cropped()を使う

from moviepy import VideoFileClip

# 動画ファイルファイル読み込み
filename1 = 'input01.MTS'
videoclip1 = VideoFileClip(filename1)

#トリミングする
cropped = videoclip1.cropped(x1=0, y1=0, x2=940, y2=760)

# 保存
cropped.write_videofile('cropped.mp4')

videoclip1.close()

戻る

GIFファイルにする

動画を保存するときにfpsを指定するとGIFファイルとして保存することもできる。moviepyの便利なのは、保存時にファイル名を指定してあげるとそれに合わせたコーデックもしてくれるところ。Qiitaの記事で動きのある映像を載せたい場合にこのGIF化が簡単にできる、moviepyは便利。

from moviepy import VideoFileClip

# 動画ファイルファイル読み込み
filename1 = 'input01.MTS'
videoclip1 = VideoFileClip(filename1)

# 保存 fps=5 (200msに1画像)
videoclip1.write_gif('out.gif', fps=5)

videoclip1.close()

戻る

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?