PaperVision3Dムービーをflvで出力保存

せっかくの3Dなのでレンダリングして動画形式や静止画として保存できたほうが便利かなぁって思い、PaperVision3Dなムービーをflv形式でファイルに出力してみました。
ひさしぶりなAirアプリになります。

こんな感じのflvが出力されます。
おまけとして静止画でも保存できるようにしてます。

今回使用したライブラリはこちら

ソースはこちら

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    creationComplete="init3D()" width="500" height="500" headerHeight="30" title="3D"
    backgroundColor="0xffffff"
    >
    <mx:Script>
<![CDATA[
/* **********************************
            PV3D
********************************** */
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.render.QuadrantRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.objects.DisplayObject3D;
import org.libspark.pv3d.Metasequoia;
import mx.graphics.codec.JPEGEncoder;
private var scene    : Scene3D;
private var viewport : Viewport3D;
private var renderer : BasicRenderEngine;
private var renderer2: QuadrantRenderEngine;
private var camera   : Camera3D;
private var camera2  : Camera3D;
private var cameraTarget : DisplayObject3D;
private var obj:Metasequoia;
//初期化
private function init3D():void{
    setupScene();
    setupCamera();
    setupMetaseq();
    setupListeners();
}
//シーンの作成
private function setupScene():void{
    viewport = new Viewport3D( myUI.width , myUI.height , true , false , true , true );
    myUI.addChildAt(viewport , 0);
    renderer = new BasicRenderEngine();
    renderer2 = new QuadrantRenderEngine();
    scene    = new Scene3D();
}
//カメラ設定
private function setupCamera():void{
    cameraTarget = new DisplayObject3D();
    camera = new Camera3D();
}
//イベントリスナー設定
private function setupListeners():void{
    addEventListener( Event.ENTER_FRAME, onRenderTick );
    addEventListener(Event.RESIZE, onResize);
}
//メタセコイア設置
private function setupMetaseq():void{
    obj = new Metasequoia();
    obj.load( "miku01.mqo" );
    scene.addChild(obj, "metaseq" );
}
//レンダリング+マウス操作
private var a:Number = 0;
protected function onRenderTick(e:Event):void {
    camera.target = obj;
    camera.z = Math.cos(a)*300;
    camera.x = Math.sin(a)*300;
    a+=0.01;
    renderer.renderScene(scene, camera, viewport);
}
//リサイズイベント
private function onResize(e : Event) : void {
}
//静止画保存
private function onSave():void{
    var file:File = File.desktopDirectory.resolvePath(Math.random()+".jpg");
    var bd2:BitmapData = new BitmapData( myUI.width , myUI.height );
    bd2.draw( myUI );
    var jenc:JPEGEncoder = new JPEGEncoder(100);
    var barray:ByteArray = jenc.encode(bd2);
    var fs:FileStream = new FileStream();
    fs.open( file , FileMode.WRITE );
    fs.writeBytes(barray);
    fs.close();
}
//Flv保存
private var myWriter:SimpleFlvWriter;
private var timer:Timer;
private var bd:BitmapData;
private function onVideoSaveStart():void{
    var file:File = File.desktopDirectory.resolvePath(Math.random()+".flv");
    myWriter = SimpleFlvWriter.getInstance();
    myWriter.createFile(file, myUI.width , myUI.height,16, 240);
    timer = new Timer(16);
    timer.addEventListener(TimerEvent.TIMER , onVideoSaving );
    timer.start();
}
private function onVideoSaving(e:TimerEvent):void{
    bd = new BitmapData( myUI.width , myUI.height );
    bd.lock();
    bd.draw( myUI );
    bd.unlock();
    myWriter.saveFrame( bd );
}
private function onVideoSaveFinish():void{
    timer.stop();
    myWriter.closeFile();
}
]]>
</mx:Script>
<mx:UIComponent id="myUI" width="100%" height="100%" />
<mx:HBox>
    <mx:Button label="動画保存開始" click="onVideoSaveStart()"/>
    <mx:Button label="動画保存停止end" click="onVideoSaveFinish()"/>
    <mx:Button label="静止画保存" click="onSave()"/>
</mx:HBox>
</mx:WindowedApplication>