web-dev-qa-db-ja.com

ffmpegでmatplotlibアニメーションを保存できません

Jake Vanderplas から単純なmatplotlibアニメーションを保存しようとしていますが、_OSError: [Errno 13] Permission denied_を取得し続けます。

ジェイクヴァンダープラスの例に2つの小さな変更を加えたことに注意してください。 MacPortsからffmpegをインストールしたので、_plt.rcParams['animation.ffmpeg_path'] = '/opt/local/bin'_の行を追加し、( FFmpegとIPython )で説明した問題に遭遇したため、FFwriter = animation.FFMpegWriter()を追加しました。

これがコードです:

_import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
plt.rcParams['animation.ffmpeg_path'] = '/opt/local/bin'

fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)

def init():
    line.set_data([], [])
    return line,

def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return line,

anim = animation.FuncAnimation(fig, animate, init_func=init,
                           frames=200, interval=20, blit=True)

FFwriter = animation.FFMpegWriter()
anim.save('basic_animation.mp4', writer = FFwriter, fps=30, extra_args=['-vcodec', 'libx264'])
_

ここにトレースバックがあります:

_File "ani_debug.py", line 34, in <module>
  anim.save('basic_animation.mp4', writer = FFwriter, fps=30, extra_args=['-vcodec', 'libx264'])
File "/Users/Ben/Library/Enthought/Canopy_64bit/User/lib/python2.7/site- packages/matplotlib/animation.py", line 712, in save
  with writer.saving(self._fig, filename, dpi):
File "/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/contextlib.py", line 17, in __enter__
  return self.gen.next()
File "/Users/Ben/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/matplotlib/animation.py", line 169, in saving
  self.setup(*args)
File "/Users/Ben/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/matplotlib/animation.py", line 159, in setup
  self._run()
File "/Users/Ben/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/matplotlib/animation.py", line 186, in _run
  stdin=subprocess.PIPE)
File "/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/subprocess.py", line 709, in __init__
  errread, errwrite)
File "/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/subprocess.py", line 1326, in _execute_child
  raise child_exception
OSError: [Errno 13] Permission denied
_

また、Spyderの組み込みpythonを使用してみましたが、同様のトレースバックを受け取りました。何か提案はありますか?


編集:私はffmpegへの適切なパスを与えていないことに気付きました。どうやら、_plt.rcParams['animation.ffmpeg_path']_はPYTHONPATHと同様に機能しません。 ffmpegが_plt.rcParams['animation.ffmpeg_path'] = '/opt/local/bin/ffmpeg'_である場所をアニメーションモジュールに正確に通知する必要があります。

再生できる動画ファイルを取得しましたが、コンテンツが完全に文字化けしています。何を見ているのかわかりません。

ここにトレースバックがあります:

_Exception in Tkinter callback
Traceback (most recent call last):
  File "Tkinter.pyc", line 1470, in __call__
  File "Tkinter.pyc", line 531, in callit
  File "/Applications/Spyder.app/Contents/Resources/lib/python2.7/matplotlib/backends/backend_tkagg.py", line 141, in _on_timer
    TimerBase._on_timer(self)
  File "/Applications/Spyder.app/Contents/Resources/lib/python2.7/matplotlib/backend_bases.py", line 1203, in _on_timer
    ret = func(*args, **kwargs)
  File "/Applications/Spyder.app/Contents/Resources/lib/python2.7/matplotlib/animation.py", line 876, in _step
    still_going = Animation._step(self, *args)
  File "/Applications/Spyder.app/Contents/Resources/lib/python2.7/matplotlib/animation.py", line 735, in _step
    self._draw_next_frame(framedata, self._blit)
  File "/Applications/Spyder.app/Contents/Resources/lib/python2.7/matplotlib/animation.py", line 753, in _draw_next_frame
    self._pre_draw(framedata, blit)
  File "/Applications/Spyder.app/Contents/Resources/lib/python2.7/matplotlib/animation.py", line 766, in _pre_draw
    self._blit_clear(self._drawn_artists, self._blit_cache)
  File "/Applications/Spyder.app/Contents/Resources/lib/python2.7/matplotlib/animation.py", line 806, in _blit_clear
    a.figure.canvas.restore_region(bg_cache[a])
KeyError: <matplotlib.axes.AxesSubplot object at 0x104cfb150>
_

編集:何らかの理由で、今はすべて正常に動作しています。私は自宅のコンピューターと職場のコンピューターで物事を試しましたが、ffmpegパスの問題を修正した後に取得した文字化けしたビデオファイルを再作成することはできません。


編集:Aaaahaaa!私はこの吸盤を追跡しました。 _plt.rcParams['savefig.bbox'] = 'tight'_が含まれているモジュールをインポートする場合があります。 (私はそのモジュールを決して使用しませんが、pythonインタープリターを再起動するまで、rcParamsは存続します。)その設定により、ビデオがすべて文字化けします。解決策を以下に投稿します。

16
Stretch

したがって、2つの問題があったことがわかります。

問題#1:ffmpegへのパスが間違っていました。 ffmpegが存在するディレクトリへのパスを提供する必要があると思いましたが、ffmpegバイナリまでのパスを提供する必要がありました。

問題#2:ビデオを生成するコードをテストする前に、plt.rcParams['savefig.bbox'] = 'tight'の設定でモジュールをインポートすることがありました。 (モジュールを使用しなかったので、あまり考えませんでしたが、pythonインタープリターを再起動するまでrcParamsは持続します。)このplt.rcParams['savefig.bbox'] = 'tight'により、ビデオファイルはエラーがありますが、ビデオを再生しようとすると、フレームがすべて文字化けします。これを追跡するのに夜通しかかりましたが、これは 既知の問題 であることがわかりました。

これは、ニースの平行移動する正弦波を使用したビデオファイルを作成する更新されたソリューションです。

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
plt.rcParams['animation.ffmpeg_path'] = '/opt/local/bin/ffmpeg'

fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)

def init():
    line.set_data([], [])
    return line,

def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return line,

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=200, interval=20, blit=True)

FFwriter = animation.FFMpegWriter()
anim.save('basic_animation.mp4', writer = FFwriter, fps=30, extra_args=['-vcodec', 'libx264'])
17
Stretch

最初に(単純に)回答3の作業例を変更してグラフをリアルタイムで表示する(そして映画を維持する)ときに、文字化けの問題が発生しました。

答え3の完全に適切な改造ではない(これは私にとってはうまくいった)

  1. plt.ion()#上の相互作用
  2. plt.draw()and plt.show()アニメーション関数内、statentを返す前
  3. フレーム数= 20、間隔=200。グラフの作成が少し遅くなりますが、4秒のムービーが作成されます

プロットは作成中にウィンドウに表示されますが、出力ムービーが文字化けします。

正しいステップ2:

  • 2a:plt.draw()insideアニメーション関数
  • 2b:plt.show()だけアニメーション関数

これで映画は文字化けなく再生されます。

0
Erik Kruus

ストレッチの答え に加えて、anim.save()に渡されているパラメーターの一部が、目的の効果を発揮していないようです。具体的には、fpsは5(デフォルト)であり、30は設定されていません。 fps=30animation.FFMpegWriterに渡すことで機能します。

そう:

FFwriter = animation.FFMpegWriter(fps=30)
anim.save('basic_animation.mp4', writer=FFwriter, extra_args=['-vcodec', 'libx264'])

ビデオの長さが40秒(200フレーム@ 5 fps)ではなく、7秒(200フレーム@ 30 fps)になったことに注意してください。また、デフォルトの5 fpsはFuncAnimationのデフォルトの200 ms /フレーム間隔に対応し、厳密に言うと、ここで使用される20 msのアニメーション間隔は50 fpsに対応します。

より良いビデオ品質を達成するのに苦労している人のために、ビットレート(kbpsの整数)をanimation.FFMpegWriterに渡すことも可能です。例:

FFwriter = animation.FFMpegWriter(fps=30, bitrate=2000)

品質を上げるために、さまざまなextra_argsを試しましたが、あまり成功しませんでした。

0
wheeled

貴重な回答をありがとう、ストレッチ。 anim.save()内で追加の引数に言及するとエラーになることがわかりました。したがって、コードは次のように更新されます。

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
plt.rcParams['animation.ffmpeg_path'] = r'I:\FFmpeg\bin\ffmpeg' #make sure you download FFmpeg files for windows 10 from https://ffmpeg.zeranoe.com/builds/

fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)

def init():
    line.set_data([], [])
    return line,

def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return line,

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=200, interval=20, blit=True)

FFwriter=animation.FFMpegWriter(fps=30, extra_args=['-vcodec', 'libx264'])
anim.save(r'I:\Understanding_objective functions\test\basic_animation.mp4', writer=FFwriter)

plt.show()

これが、アニメーションプロットを.mp4形式で保存しようとしている人に役立つことを願っています。

0
Paul Thomas