FLVRecorder for Adobe AIR
About
When I was researching earlier this year whether or not I could capture a webcam feed and save it to the Flash Video Format, I stumbled on a guys blog called Zero Point Nine. He made a class that could save frames (BitmapData objects) passed to it as an FLV.
This was nice, but not very performant, as the parsing of the BitmapData to ByteArrays took way too long and was extremely CPU intensive and your app froze up, I decided to adjust the class and make it usable within an Adobe AIR app without losing a single frame, or freezing the app. For this, I started out with a new class, only copied the algorithms for writing an FLV and started building my own api.
The main target of developing this FLV-recorder was performance on the CPU and RAM side.
FLVRecorder
The purpose of this revolutionary new class is to record a stream of BitmapData to a FLV-file, because writing directly, and especially the converting-BitmapData-to-ByteArrays-with-byteshifting-part, made everything run shaky. I solved that issue by saving the BitmapData to a temporary file on the system. This to protect your RAM from overloading, and when done recording, the class converts that temporary file to an FLV-file.
For developing comforts, I build in a few events as well, when recording starts and stops, and an event while saving, with an indication of your progress.
The class offers the user to record via inputting BitmapData, Bitmaps and even your custom components, Flex component, like your VideoDisplay and also Flash components, like the FLVPlayBack or your custom Sprites and MovieClips.
The class does not yet support adding sound to the flv-file, this is the next step of development, to enable sound recording and add sound to the flv-file.
AirCam
As a proof-of-concept, I built a small application that enables you to record your webcam and saved it on your desktop as an flv-file.
Download the AirCam installer here.
To view the source used in this project, right-click somewhere, and choose view source.
The FLVRecorder and all related classes are open source, they are not fully tested and may contain bugs.
I’m happy to share it with the community, use them, play with them and certainly enhance them!
These classes are NOT FOR COMMERCIAL USE and property of BoulevArt nv.
Download the source.
API
The class offers the developer an API to easy implement this in your app.
You should respect a certain flow:
1. Make an instance of the class, it’s a singleton class, so just ask for the instance:
var recorder:FLVRecorder=FLVRecorder.getInstance()
2. Define the target FLV-file’s properties, the file instance to your flv-file, width & height, framerate and the systemManager instance, that’s a Flash internal declared variable and the optional duration in seconds:
file=File.desktopDirectory.resolvePath(“recording.flv”);
recorder.setTarget(file,640,480,fps,systemManager, durationInSeconds)
the duration is optional, it will be automaticly filled in when left blank.
3. Insert some bitmaps, bitmapdatas or a screenshot of a component into the flv-file:
recorder.captureComponent(vidDisplay) //DisplayObject, takes a screenshot from that component
recorder.saveFrame(bmpdata) //Bitmapdata, does nothing with it
recorder. saveSmoothedBitmapFrame(bmp) //Bitmap, smooths before saving
recorder. saveSmoothedFrame(bmpdata) //Bitmapdata, smooths bitmapdata before saving
4. To stop recording, simply command the class to stop, it will start to convert your saved data to the flv-file
recorder.stopRecording()
It will throw 3 events, when saving starts, when savings stops and one while saving to pass on the savings progress
FLVRecorderEvent.FLV_START_CREATION
FLVRecorderEvent.FLV_CREATED
FLVRecorderEvent.PROGRESS //event contains progress property, is a value between 0-1 to indicate progress
5. All done, that’s how simple things can be in life.
6. Test it, use it and give me feedback of your experiences!
How–to-use code example
private var tmr:Timer
private var recorder:FLVRecorder
private var file:File
private function startRecording():void{
if(recorder==null){
recorder=FLVRecorder.getInstance()
}
file=File.desktopDirectory.resolvePath(“recording.flv”);
recorder.setTarget(file,640,480,fps,systemManager)
if(tmr==null){
tmr=new Timer(1000/fps)
}
tmr.addEventListener(TimerEvent.TIMER,record)
tmr.start()
}
private function record(e:TimerEvent):void{
recorder.captureComponent(vidDisplay) //DisplayObject
//recorder.saveFrame(bmpdata) //Bitmapdata
//recorder. saveSmoothedBitmapFrame(bmp) //Bitmap
//recorder. saveSmoothedFrame(bmpdata) //Bitmapdata
}
private function stopRecording():void{
tmr.stop()
//when saving is done
recorder.addEventListener(FLVRecorderEvent.FLV_CREATED,fileMade)
//when saving starts
recorder.addEventListener(FLVRecorderEvent.FLV_START_CREATION,startCreatingFLV)
recorder.stopRecording()
}
private function startCreatingFLV(e:FLVRecorderEvent):void{
recorder.addEventListener(FLVRecorderEvent.PROGRESS,onFLVCreationProgress)
}
private function onFLVCreationProgress(e:FLVRecorderEvent):void{
//e.progress: percent complete (0 to 1)
//pbSaving: ProgressBar component in Flex
pbSaving.setProgress(e.progress,1)
}
Downloads
Contact!
Share your opinion with us, leave a comment!
Also tell me if you’re using the class, what you wanted to see different, share your enhancements!
Don’t forget to show me what apps you made with these classes!
You can always reach me:
just leave a comment!
*UPDATE 1*
Thanks for your feedbacks, I’ve updated the classes to help out a few of you.
What is new:
An enableCompression property: will compress the captured image with the JPGEncoder
Warning! Using this property will slow you application down.
Codecs:
Pick a codec. You can find the available codecs in the FlvRecorderCodecs class.
Pausing & Resuming recordings:
You can pause & resume recordings.
If you stop feeding the class frames, and not call the stopRecording() function, and after a while, feeding it some frames again, it will add those frames to the current movie.
*UPDATE 2*
Because I am using a Pseudo-Threading class that is using a specific Flex class, and a lot of you are Flash-only developers, I have released a library for Flash (AS3) on Google Code.
Here is a link.
Hey. Just rewrite the library http://www.zeropointnine.com/blog/updated-flv-encoder-alchem/. Stalknulsya problem with the file size. I think this question asked before. Need to record a video size of 640×480 with minimum 15fps.
But the problem stalknulsya file size. He is very big. It does not push to the server. RED5 in my case is not appropriate. It is necessary that 60 seconds of the video does not exceed a threshold of 20-30 megabytes.
Thank you in advance.
I just like to mention again to others who may have some question like me:
—>how to deal with SystemManager ERROR and setpixel EOF !
1.SystemManager is the class only in Flex.(using flash-builder and Fex-SDK is not mean your AS3 project equal to Flex project!!)
2.Joris also provides a library for Flash use.
3.open the FLVRecorder.as,you will see function “setTarget”‘s parameter is “stage” now.(in Flex library is systemManager.)
4.in you Main.as just pass stage into setTarget function(ex: recorder.setTarget(file,640,480,30,stage))
5.note your DisplayObject being recorded should has same scale as you pass to setTarget function (ex:640,480,other wiese you will have EOF error)
and
6.download AirCam.app and install it,after launch you can right click on the window and see the “source code” that how Joris build it.
Thanks Joris!
Dear Joris:
is this possible to mention people about this blog and threads on you google project page.
I just found out the discussions here is very helpful.
Video (FLV) files over HTTP or from the local file system. For more information, see the NetConnection class and NetStream class entries.
hi there,
thanks for the code, it really helped understanding a lot – but, as a newbie, i have still problems understanding the PseudoThread class (or the systemmanager).
It needs two arguments and i have no idea. please help!
Hello,
I have achieved this feature in my app using flash player instead of AIR, no probs with that.
What I want now is to reduce the size of my video presently a 30 secs video is 20MB which too huge.
Can you suggest what should I do??
Any suggestion will also help.
Thanks
I have been studying your code and playing with the project and I have a few questions for you. I was wondering if Action Script 3.0 can create a buffer either in memory / disk to create a video delay system using a webCam as input. Your project looks very close to what I want to do. Do I need to encode the buffered stream? Should I use memory or disk to create the buffer. I’d like to be able to scrub through the saved stream frame by frame. Do I need to use FMS to save the buffered stream or can I just write it to my laptop?
Thank you so much for sharing your expertise so openly.
Found more of the pieces of your code. I have been tying to use your FLVRecorder class. I keep getting a compile error – Line 102, Col 33 – the function targetSet.
“1046: Type was not found or was not a compile-time constant: File”
Sorry, I found my own error. Thanks.
Hi,
I want to use this class for video recording without fms server. is it possible? In this class what to use instead of viddisplay object. Please explain me.
HI,
I got below error when i’m trying to recapture the video
Error #2044: Unhandled IOErrorEvent:. text=Error #3013: File or directory is in use.