moviepy (Pythonビデオ合成) は何をしますか?
短いスクリプト型の動画や、フッテージに正確なテキストを配置する場合に最適です。長時間・デザイン重視・再利用可能な動画にはRemotionを推奨します。
| moviepyを使用する場合 | Remotionを使用する場合 |
|---|---|
| プロジェクトが単一のPythonスクリプト | Reactコンポーネントとデザインシステムが必要 |
| 既存またはAI生成クリップへのテキストオーバーレイ | 複雑なアニメーショングラフィックスやチャート |
| 多数のファイルに対するバッチ編集 | ホットリロードプレビューが重要 |
| Nodeツールチェインが利用不可 | 長尺・テンプレート動画 |
セットアップ
pip install "moviepy>=2" pillow
# または: uv add moviepy pillow
このスキルは moviepy 2.x を対象としています。1.x とはAPIが異なり、インポートは moviepy から直接行い、メソッドは with_*/subclipped/resized を使用します(set_*/subclip/resize ではありません)。
基本操作
from moviepy import (VideoFileClip, AudioFileClip, ImageClip, TextClip,
CompositeVideoClip, CompositeAudioClip, concatenate_videoclips, vfx, afx)
clip = VideoFileClip("in.mp4").subclipped(5, 20) # 15秒の抜粋
clip = clip.resized(height=1080) # アスペクト比維持
clip = clip.with_effects([vfx.FadeIn(0.5), vfx.FadeOut(0.5)])
joined = concatenate_videoclips([clip, VideoFileClip("b.mp4")], method="compose")
joined.write_videofile("out/result.mp4", fps=30, codec="libx264", audio_codec="aac")
長時間スクリプトで使用する場合は、常に .close() を呼び出すか、with ブロック内でクリップを使用してファイルハンドルを解放してください。
テキストオーバーレイ(フッテージへの決定論的テキスト配置)
title = (TextClip(font="C:/Windows/Fonts/arial.ttf", # 実際のフォントファイルパス
text="山田 太郎\n主任研究員",
font_size=56, color="white",
stroke_color="black", stroke_width=2,
method="caption", size=(900, None))
.with_start(1.0).with_duration(4.0)
.with_position(("left", 860))
.with_effects([vfx.CrossFadeIn(0.3), vfx.CrossFadeOut(0.3)]))
final = CompositeVideoClip([clip, title])
注意:
TextClipにはフォントファイルのパス(TTF/OTF)が必要です。プロジェクトにブランドフォントを同梱してください。- クリップの時間は秒単位で、コンポジットの開始からの相対時間です。
- 丸いピルやグラデーションなど装飾的なテキストには、PillowでPNGをレンダリングして
ImageClipを使用してください。 - テキストは安全領域内に配置: 各辺から少なくとも5%以上内側に設定します。
オーディオ
voice = AudioFileClip("voiceover.mp3")
music = AudioFileClip("music.mp3").with_effects([afx.MultiplyVolume(0.12), afx.AudioFadeOut(2)])
music = music.with_duration(voice.duration + 1)
final = clip.with_audio(CompositeAudioClip([music, voice.with_start(0.5)]))
ナレーションがタイムラインを決定するようにします。クリップの長さは voice.duration + パディング に設定し、その逆は避けてください。
オーディオ同期パターン
scenes = [("scene1.mp3", "intro.png"), ("scene2.mp3", "chart.png")]
parts = []
for audio_path, image_path in scenes:
a = AudioFileClip(audio_path)
v = ImageClip(image_path).with_duration(a.duration + 0.6).with_audio(a)
parts.append(v)
concatenate_videoclips(parts).write_videofile("out/explainer.mp4", fps=30)
静止画のケンバーンズ効果
img = ImageClip("photo.jpg").with_duration(6)
img = img.resized(lambda t: 1.0 + 0.04 * t).with_position("center")
CompositeVideoClip([img], size=(1920, 1080)).write_videofile("out/kb.mp4", fps=30)
パフォーマンス
- プレビューは
fps=12とpreset="ultrafast"で行い、最終レンダリングは30fpsに設定。 write_videofile(..., threads=4)を使用。- 長いクリップではフレームごとのPythonラムダ式を避け、可能な場合はFFmpegで事前処理を行ってください。
注意点
| 問題 | 原因と対策 |
|---|---|
ImportError: cannot import name 'editor' | moviepy 2では moviepy.editor が削除されました。moviepy からインポートしてください。 |
AttributeError: set_duration | with_duration を使用。with_start、with_position も同様。 |
| テキストクリップがクラッシュする | 実際のフォントファイルパスを渡してください。 |
| 結合後にオーディオがずれる | すべてのクリップのfpsが同じであることを確認し、結合後にオーディオを適用してください。 |
| レンダリングが遅い | ドラフトでは解像度を下げ、大きな resized ラムダ式を避けてください。 |