これはなに
matplotlibのanimation
を利用してmp4を出力しようとしたら、ValueError: unknown file extension: .mp4
と言われて出力できなかった。
このときに取った対応策を備忘録として残す。
原因: ffmpegへのパスが通っていない
この問題の原因は、ffmpegへのパスが通っていなかったことだった。 ffmpegをダウンロードして、matplotlibに場所を教えてあげれば解決できる。
当時の環境
- Windows 10
- Python 3.9.5
問題を再現する最小限のコード
以下のコードは、問題を再現する最小限のサンプルである。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
loop_num = 10
fig = plt.figure()
artists = []
for i in range(loop_num):
signal = np.random.rand(100)
artist = plt.plot(signal)
artists.append(artist)
anim = animation.ArtistAnimation(fig=fig, artists=artists, interval=10)
anim.save("test.mp4", fps=30)
エラーの詳細
matplotlib.animation.ArtistAnimation
で生成したアニメーションを保存するときに拡張子をmp4にすると、下記のエラーが発生した。
MovieWriter ffmpeg unavailable; using Pillow instead.
Traceback (most recent call last):
File "python\path\PIL\Image.py", line 2331, in save
format = EXTENSION[ext]
KeyError: '.mp4'
The above exception was the direct cause of the following exception:
##### 中略 #####
File "python\path\PIL\Image.py", line 2333, in save
raise ValueError(f"unknown file extension: {ext}") from e
ValueError: unknown file extension: .mp4
何が問題だったのか
ffmpegへのパスが通ってなかった。
解決策
ffmpegをダウンロードして、matplotlibに場所を教えてあげれば解決できる。
ffmpegをダウンロードする
ffmpegの公式サイト からffmpegをダウンロードする。 DownloadからWindowsを選び、出てくるサイトからWindows用のffmpegファイルをダウンロードすればよい。 詳細はこのあたりのサイト を参考にすれば問題ないだろう。
matplotlibにffmpegの場所を教える
ffmpegのzipファイルをダウンロードしたら、解凍して、
中に入っているbinファイルをC:\ffmpeg\
直下に置く。
ffmpegというディレクトリがなければ、C:\
直下に新たに作成する。
その後、matplotlibにffmpegの場所を教える。 matplotlibにffmpegの場所を教えるやり方は2通りある。
- 環境変数のPathに追加する方法。
C:\ffmpeg\bin
を環境変数に追加する。 plt.rcParams['animation.ffmpeg_path']
に指定する方法。Pythonプログラムのmp4を保存する前の行に、下記コードを追加する。
plt.rcParams["animation.ffmpeg_path"] = "C:\\ffmpeg/bin/ffmpeg.exe"
修正後の最小限のコード
修正後のコードは以下のとおりである。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
+ plt.rcParams["animation.ffmpeg_path"] = "C:\\ffmpeg/bin/ffmpeg.exe"
loop_num = 10
fig = plt.figure()
artists = []
for i in range(loop_num):
signal = np.random.rand(100)
artist = plt.plot(signal)
artists.append(artist)
anim = animation.ArtistAnimation(fig=fig, artists=artists, interval=10)
anim.save("test.mp4", fps=30)
これを実行すると、無事test.mp4が生成される。