otterbの日記: VistaでPythonを使ってffmpegに画像をパイプしてエンコード
最近よくPythonでわからないことがあるとStackoverflow.comにお世話になる。Stackoverflow.comはいつもわからないことがあるとGoogleさんがつれてってくれるデベロッパーの人たちのすてきなディスカッションサイト。
サイトの作りが非常にいいと思う。だれでもすぐコメントできてオープンだし、うまくモチベーションをくすぐるようなリピュテーションポイント等のシステム、参加者のやる気を引き出して答えの質とか雰囲気がよく保たれていて感心する。
研究の補助ツールとして、たくさんあるnumpyのアレイを中間の画像ファイルを作らずにビデオにエンコードしたかったんだけどStackoverflow.com (http://stackoverflow.com/questions/4092927/generating-movie-from-python-without-saving-individual-frames-to-files) を参考にやってみた。
ffmpegの最新リリースをダウンロードして、VistaなのでMingW32+MSYSいれてコンパイルしようとするとprがないとおこられたのでprってなんじゃ?だったけどSource Forgeから適当にprがはいっているパッケージから抜き出してなんとかコンパイルできた。ffmpegのドキュメンテーションにもMingW32+MSYSだけではだめと書いてあるのでCYGWINにしとけばよかったな。
Stackoverflowの記事にはffmpegのバグでPNGをPIPE INするとPNGパーサーがエラーになるのでパッチをあてろとある。パッチを当てるためにUbuntuからブートしてpatchコマンドつかって適用。記事にもあるとおりlibavcodecのMakefileについてはパッチがエラーになるので手作業で変更を済ます。しかし、新しく追加されたPNGパーサーのところでコンパイルがエラーになってしまった。もとの記事の人はMacでやっているのでMacのGCCならうまくいくのだろうか。
しょうがないのでmatplotlibの代わりにPython Image Library(PIL)をつかってPNGではなくJPEGで送ってみようと試みる。
matplotlibだと
plt.savefig(p.stdin, format='png')
p.stdinのようにファイルオブジェクトのところにffmpegのサブプロセスpのメソッドを呼ぶことができるみたいだけど、これをそのままPILでやろうとすると
im.save(p.stdin,'jpg')
コンソールに大量の文字列とともに恐ろしいビープ音が鳴り響く事態となった。
しょうがないのでPILのドキュメンテーションよみすすめて、とりあえずtostringをつかってJPEGデータのバッファーを得ることに成功。あとはこれをsubprocessでPIPEしてやればいいはず。オフィシャルのドキュメンテーションのsubprocessの項をもうすこし気合いいれて読み進む。subprocessにデータをPIPEするにはp.communicateとかp.stdin.writeとすればいいみたいだ。
Warning Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.
とあるのでp.communicate()をつかってやってみるとなんかうまくいかないが、p.stdin.write()だとあっさりうまくいった。これでパッチが必要なくなったし、同じような問題ではまっている人もいるかもなのでStackoverflowにアカウントつくってコメントつけてみたら、だれかがreputation pointくれた。そしたらTeacherのバッチももらってしまった。Stackoverflow太っ腹!
VistaでPythonを使ってffmpegに画像をパイプしてエンコード More ログイン