MoviePyで実現するジェネラティブアート - アルゴリズムで生み出す動画アート


新記事を書きました📝「MoviePyで実現するジェネラティブアート」
Pythonの動画ライブラリを使って、パーリンノイズやフラクタルで抽象的なアニメーションを作る方法をまとめています。コード例付きなので、ぜひ試してみてください！

![マインドマップ (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/e6dddc02-2980-4ad0-bf5e-3fd296b3ccaa.png)

## はじめに

MoviePy は Python で動画を生成・編集するためのライブラリです。本記事では、MoviePy を活用して、パーリンノイズやフラクタルなどを使った抽象的なアニメーション(ジェネラティブアート)を作成する方法を紹介します。手軽に始められるうえ、アルゴリズム次第で無限のパターンを作り出せるので、ぜひ遊んでみてください。

![generative-art-diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/e1cba6d1-16fa-4894-bfa1-b98d36db31d9.png)

---

## 1. 環境と準備

- **Python バージョン**: 3.x 系推奨  
- **必要なライブラリ**:
  - `moviepy`  
  - ノイズ生成用: `noise` (Perlin Noise の生成に便利)  
  - 配色や配列操作用: `numpy`, `PIL` など(用途に応じて)

```bash
pip install moviepy noise numpy pillow
```

---

## 2. MoviePy の基本的な使い方

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/45c9e47a-7808-4b2c-b9d2-fd9a89d1ac9f.png)


MoviePy では、`VideoClip` や `ImageSequenceClip` などを使って動画を生成できます。  
`VideoClip` はコールバック関数を与え、経過時間(`t`)に応じてフレーム画像を返す方式です。

### シンプルな例

```python
from moviepy.editor import VideoClip
import numpy as np

def make_frame(t):
    width, height = 320, 240
    red   = int((np.sin(t * 2) + 1) * 127)
    green = int((np.sin(t * 3) + 1) * 127)
    blue  = int((np.sin(t * 4) + 1) * 127)
    
    frame = np.zeros((height, width, 3), dtype=np.uint8)
    frame[:, :, 0] = red
    frame[:, :, 1] = green
    frame[:, :, 2] = blue

    return frame

clip = VideoClip(make_frame, duration=3)
clip.write_videofile("simple_animation.mp4", fps=30)
```

生成した動画の例
<iframe width="560" height="315" src="https://www.youtube.com/embed/7lwBuZk__7c?si=4urTvHCe_YrSItnS" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
---

## 3. パーリンノイズを使ったアニメーション

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/a3563539-a6a1-4435-b6f5-07306769889d.png)


### 3.1 パーリンノイズ (Perlin Noise) とは

- Ken Perlin が考案した滑らかな乱数生成手法
- 2D・3D 空間での自然な模様(雲や煙、地形など)を再現しやすい
- Python では `noise` ライブラリを使うと便利

### 3.2 パーリンノイズを利用した動画生成

```python
from moviepy.editor import VideoClip
import numpy as np
import noise

def perlin_frame(t, width=320, height=240):
    scale = 0.02
    time_factor = 0.3 * t
    frame = np.zeros((height, width, 3), dtype=np.uint8)

    for y in range(height):
        for x in range(width):
            n = noise.snoise3(x * scale, y * scale, time_factor, octaves=1)
            val = int((n + 1) * 127.5)
            frame[y, x] = (val, val, val)

    return frame

def make_frame(t):
    return perlin_frame(t)

clip = VideoClip(make_frame, duration=5)
clip.write_videofile("perlin_noise.mp4", fps=30)
```

生成した動画の例
<iframe width="560" height="315" src="https://www.youtube.com/embed/8ncjDTc0DaM?si=b9uUQprd2tKR8Lie" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
---

## 4. フラクタルを用いたアニメーション

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/59dedefa-b97b-45c9-a8a9-b4bcac945a72.png)

### 4.1 フラクタルの例: マンデルブロ集合

マンデルブロ集合を用いたアニメーションを MoviePy で作成できます。

```python
from moviepy.editor import VideoClip
import numpy as np

def mandelbrot(c, max_iter=50):
    z = 0
    for i in range(max_iter):
        z = z*z + c
        if abs(z) > 2:
            return i
    return max_iter

def mandelbrot_frame(t, width=320, height=240):
    zoom = 1 + t * 0.2
    x_min, x_max = -2.0/zoom, 1.0/zoom
    y_min, y_max = -1.5/zoom, 1.5/zoom
    frame = np.zeros((height, width, 3), dtype=np.uint8)

    for i in range(height):
        for j in range(width):
            x = x_min + (x_max - x_min) * j / width
            y = y_min + (y_max - y_min) * i / height
            c = complex(x, y)
            m = mandelbrot(c, max_iter=100)
            color = int(255 * m / 100)
            frame[i, j] = (color, color, 255 - color)

    return frame

def make_mandelbrot_frame(t):
    return mandelbrot_frame(t)

clip = VideoClip(make_mandelbrot_frame, duration=5)
clip.write_videofile("mandelbrot_zoom.mp4", fps=30)
```

生成した動画の例
<iframe width="560" height="315" src="https://www.youtube.com/embed/dPKY1UyvD0U?si=IvwZBKz2c6XDsRQN" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

---

## 5. まとめ

![moviepy-summary.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/c80fc69f-6aaa-46a4-8a69-6e55937a90ca.png)

- MoviePy とアルゴリズム(ノイズ・フラクタルなど)を組み合わせることで、さまざまな抽象アニメーションを生成可能
- パラメータを少し変えるだけで、模様や動きが大きく変化するのがジェネラティブアートの魅力
- さらに音声合成やモーショングラフィックス的な要素を組み合わせることで、より豊かな表現が可能

みなさんも独自のアルゴリズムを考案してジェネラティブアートを楽しんでみてください。

> **参考**  
> - [MoviePy 公式ドキュメント](https://zulko.github.io/moviepy/)  
> - [noise (perlin noise) ライブラリ](https://pypi.org/project/noise/)