Created
April 10, 2016 23:28
-
-
Save VCone/266ff5c7ce2c3ac7a64d8017125f8b0c to your computer and use it in GitHub Desktop.
Use AS3 code to transfer bitmapData to an FFmpeg video frame (dynamically generated video frames via code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
//## DYNAMIC VIDEO USING AS3 AND FFMPEG (as native AIR application) | |
A quick code example for using AS3 to transfer a bitmap object to an FFmpeg video frame. | |
In others word: Create video dynamically from pixel grabs of a displayObject (Sprite, MC, Bitmap etc). | |
> Inspired by : http://stackoverflow.com/a/13777166 | |
> See example result : http://blog.vcone.co.uk/2016/04/10/dynamic-video-test-1/ | |
*/ | |
//# The function setups a new NativeProcess() and has related functions. You can setup eventListener functions if you them. | |
public function do_NativeProcess_FFMPEG () : void | |
{ | |
//# FFMPEG Video Convert | |
trace("Doing Encode via FFmpeg"); | |
//# set Start Up info | |
NP_StartupInfo = new NativeProcessStartupInfo(); | |
var Args_FFMPEG:Vector.<String> = new Vector.<String>(); | |
//##### NOTES : FFmpeg process will exit with "code 1" if there is a wrong settings line | |
//# For example pushing a wrong codec setting etc would jam the process and gives "EXIT code 1" | |
//## 1) INPUT settings (what you send to FFmpeg) | |
Args_FFMPEG.push('-y'); //# overwrite (if existing filename) needed if you re-encode etc.. | |
Args_FFMPEG.push("-f", "rawvideo"); | |
Args_FFMPEG.push("-pix_fmt", "argb"); | |
Args_FFMPEG.push("-s", "624x336"); | |
Args_FFMPEG.push("-r", "24"); | |
Args_FFMPEG.push("-i", "-"); //works same as "pipe:0" | |
//## 2) VIDEO settings | |
Args_FFMPEG.push("-c:v", "libx264"); //libx264 | |
//Args_FFMPEG.push("-profile:v", "baseline"); | |
//Args_FFMPEG.push("-level:v", "3"); | |
Args_FFMPEG.push("-b:v", "2500"); | |
//## 3) AUDIO settings | |
Args_FFMPEG.push("-an"); //# no audio (is pixels only) | |
//## 4) OUTPUT settings | |
Args_FFMPEG.push("tempData8.h264"); //# Seems needed for side-data?? (Gives blocky image) | |
Args_FFMPEG.push("VC_DynamicVideo8.h264"); // .h264 works to give AVC codec | |
NP_StartupInfo.executable = File.applicationDirectory.resolvePath("ffmpeg.exe"); | |
NP_StartupInfo.arguments = Args_FFMPEG; | |
process = new NativeProcess(); | |
process.addEventListener(ProgressEvent.STANDARD_INPUT_PROGRESS, on_STDIn_WriteData); | |
//process.addEventListener(IOErrorEvent.STANDARD_INPUT_IO_ERROR, on_STDIn_IOError); | |
//process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, on_STD_OutputData); | |
//process.addEventListener(IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, onIOError); | |
//process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, on_STD_ErrorData); | |
//process.addEventListener(IOErrorEvent.STANDARD_ERROR_IO_ERROR, onIOError); | |
//process.addEventListener(NativeProcessExitEvent.EXIT, on_NativeProcess_Exit); | |
//# start processes | |
process.start( NP_StartupInfo ); //function "on_FFMPEG_OutputData" will handle this part | |
//# Test Frame | |
write_STDIn_Data(); | |
} | |
public function write_STDIn_Data () : void | |
{ | |
//# Method v1 : Do funtion whenever frame data is ready... | |
//# Run this function each time to add a frame to FFmpeg video file | |
makeVideoFrame (); //remove this line, if using Method v2 | |
//# Method v2 : Use timer/EnterFrame to record a container object | |
//# can be TIMER event or ENTER_FRAME event | |
//addEventListener(Event.ENTER_FRAME, update); //remove this line, if using Method v1 | |
} | |
private function update(e:Event) : void | |
{ | |
//# 1) Do something visual in this function code | |
// YOUR EFFECTS CODE HERE... (will become INPUT in "makeVideoFrame" function) | |
//# 2) now write the visual effect as a frame | |
makeVideoFrame (); | |
} | |
public function makeVideoFrame () : void | |
{ | |
//# Encodes an AS3 Bitmap as FFmpeg video frame | |
snapShot_BMD.draw( InputSource ); //# INPUT is displayObject (ie: MC, Sprite, Bitmap etc) | |
frame_BMP.bitmapData = snapShot_BMD; //update "frame to be encoded" bitmap | |
if ( process.running == true ) | |
{ | |
ba_Pixels = frame_BMP.bitmapData.getPixels( frame_BMP.bitmapData.rect ); | |
process.standardInput.writeBytes(ba_Pixels); //# Send data to FFmpeg for frame encode | |
//trace("ba_Pixels length : " + ba_Pixels.length); | |
ba_Pixels.clear(); //# empty for re-use with next frame | |
} | |
} | |
public function on_STDIn_WriteData (evt : ProgressEvent):void | |
{ | |
if (process.running == true) | |
{ | |
trace("Writing IMAGE data to STD Input..."); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment