Skip to content

Instantly share code, notes, and snippets.

@VCone
Created April 10, 2016 23:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save VCone/266ff5c7ce2c3ac7a64d8017125f8b0c to your computer and use it in GitHub Desktop.
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)
/*
//## 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