2016-07-16 9 views
2

Linuxサーバーでアニメーションをレンダリングするkivyアプリを作成しました。 アニメーションを直接ビデオファイルに変換する良い方法はありますか?kivyをビデオファイルに変換する方法

現在、私はXvfb + ffmpegアプローチを試みました。しかし、私が避けたいと思ういくつかの問題があります:

  • ffmpegは、アニメーション開始前に空のx-windowsデスクトップも記録します。

答えて

3

あなたはすべてのフレーム後の画像ファイルにウィジェットを保存しffmpegまたはcv2ライブラリーのようなツールを使ってムービーを構築するためにkivy.uix.widget.Widget.export_to_pngを使用することができますが、それは時間をtooksディスクにデータを保存するため、アニメーションが遅くなります。そこでここでは別のアプローチです:それはファイルにテクスチャを保存しようとしませんが、代わりに、それはリストにそれを追加して

from functools import partial 

from kivy.app import App 
from kivy.uix.floatlayout import FloatLayout 
from kivy.lang import Builder 
from kivy.animation import Animation 
from kivy.graphics import Fbo, ClearColor, ClearBuffers, Scale, Translate 

Builder.load_string(''' 
<MyWidget>: 
    Button: 
     size_hint: 0.4, 0.2 
     pos_hint: {'center_x' : 0.5, 'center_y' : 0.5} 
     text: 'click me' 
     on_press: root.click_me(args[0]) 
''') 

class MyWidget(FloatLayout): 
    def click_me(self, button, *args):  
     anim = Animation(
      size_hint = (0.8, 0.4) 
     ) 

     textures = [] 
     anim.bind(on_complete=partial(self.save_video, textures)) 
     anim.bind(on_progress=partial(self.save_frame, textures))    

     anim.start(button) 

    # modified https://github.com/kivy/kivy/blob/master/kivy/uix/widget.py#L607 
    def save_frame(self, textures, *args): 
     if self.parent is not None: 
      canvas_parent_index = self.parent.canvas.indexof(self.canvas) 
      if canvas_parent_index > -1: 
       self.parent.canvas.remove(self.canvas) 

     fbo = Fbo(size=self.size, with_stencilbuffer=True) 

     with fbo: 
      ClearColor(0, 0, 0, 1) 
      ClearBuffers() 
      Scale(1, -1, 1) 
      Translate(-self.x, -self.y - self.height, 0) 

     fbo.add(self.canvas) 
     fbo.draw() 
     textures.append(fbo.texture) # append to array instead of saving to file 
     fbo.remove(self.canvas) 

     if self.parent is not None and canvas_parent_index > -1: 
      self.parent.canvas.insert(canvas_parent_index, self.canvas) 

     return True   

    def save_video(self, textures, *args): 
     for i, texture in enumerate(textures): 
      texture.save("frame{:03}.png".format(i), flipped=False)  

class MyApp(App): 
    def build(self):   
     return MyWidget() 

if __name__ == '__main__': 
    MyApp().run() 

私はexport_to_png方法を変更しました。アニメーションが終了したら、すべてのデータを別のイメージに保存します。その間、アプリケーションのレスポンスが低下するため、「アニメーションは保存しています...」モーダルを追加するとよいでしょう。

関連する問題