If you do not consider the security factor (anyone can connect FluorineFx for video recording without logon authentication), the server does not need to write a line of code, you only need to create a subdirectory under the apps directory as an application, and configure the rtmp Channel in the services-config.xml.
The following as3 code of the flash client is modified from the official Flash AS2 example of FluorineFx (of course, there are many optimizations in the details)
Package {import fl. controls. button; import fl. controls. label; import fl. controls. textInput; import fl. controls. checkBox; import flash. display. sprite; import flash. utils. timer; import flash. events. activityEvent; import flash. events. timerEvent; import flash. events. mouseEvent; import flash. events. netStatusEvent; import flash. events. statusEvent; import flash. media. camera; import flash. media. microphone; import flash. Net. netConnection; import flash.net. netStream; import flash. media. video; public class VideoRecord extends Sprite {private var _ btnRecord: Button; private var _ btnPlay: Button; private var _ btnConnect: Button; private var _ txtVideoFileName: TextInput; private var _ chkAppend: CheckBox; private var _ txtServerUrl: TextInput; private var _ lblResult: Label; private var _ nc: NetConnection = null; private var _ nsPublish: Net Stream = null; private var _ nsPlay: NetStream = null; private var _ ncPlay: NetConnection = null; private var _ camera: Camera; private var _ microphone: Microphone; private var _ videoRecord: Video; private var _ videoPlay: Video; private var _ videoIsWorked = false; private var _ timer: Timer; public function VideoRecord () {init ();} private function init (): void {this. _ btnRecord = this. btnRecord; this. _ txtVideoFileName = t His. videoFileName; this. _ chkAppend = this. chk1; this. _ chkAppend. label = "APPEND"; this. _ btnPlay = btnPlay; this. _ btnConnect = btnConnect; this. _ txtServerUrl = this.txt ServerUrl; this. _ lblResult = lblResult; this. _ btnRecord. enabled = false; this. _ btnRecord. label = "Recording"; this. _ txtVideoFileName. enabled = false; this. _ chkAppend. enabled = false; this. _ btnPlay. enabled = false; this. _ btnPlay. label = "play"; this. _ btnConnec T. label = "Connect"; this. _ txtServerUrl. text = "rtmp: // localhost/VideoRecording"; this. _ videoRecord = videoRecord; this. _ videoPlay = videoPlay; this. _ btnConnect. addEventListener (MouseEvent. CLICK, doConnect) ;}// connect to the server; private function doConnect (e: MouseEvent): void {if (this. _ nc = null) {this. _ nc = new NetConnection; this. _ nc. addEventListener (NetStatusEvent. NET_STATUS, ncNetStatus);} this. _ nc. connect (this. _ txtSe RverUrl. text); this. _ lblResult. text = "connecting to the server... ";}// close the connection to the server. private function doCloseConn (e: MouseEvent): void {if (this. _ nc! = Null) {if (this. _ nsPublish! = Null) {this. _ nsPublish. attachCamera (null);} this. _ videoRecord. attachCamera (null); this. _ videoRecord. attachNetStream (null); this. _ videoRecord. clear (); this. _ nc. close (); this. _ btnConnect. label = "Connect"; this. _ btnRecord. enabled = false; this. _ txtVideoFileName. enabled = false; this. _ chkAppend. enabled = false; this. _ videoRecord. clear (); this. _ btnConnect. removeEventListener (MouseEvent. CLICK, doCloseConn); this. _ btnCo Nnect. addEventListener (MouseEvent. CLICK, doConnect); stopPublish () ;}// check the status change of the conn object private function ncNetStatus (e: NetStatusEvent): void {// trace (e.info. code); if (e.info. code = "NetConnection. connect. success ") {// connection successful this. _ lblResult. text = "the server is connected! "; This. _ btnConnect. label = "disconnected"; this. _ btnConnect. removeEventListener (MouseEvent. CLICK, doConnect); this. _ btnConnect. addEventListener (MouseEvent. CLICK, doCloseConn); this. _ camera = Camera. getCamera (); if (_ camera = null) {this. _ lblResult. text = "no camera is installed! "; Return;} _ camera. addEventListener (StatusEvent. STATUS, cameraStatusHandler); _ camera. addEventListener (ActivityEvent. ACTIVITY, cameraActivityHandler); this. _ videoRecord. attachCamera (this. _ camera); // click "Disconnect" and then click "Connect" again; if (_ videoIsWorked) {// restore control availability; this. _ txtVideoFileName. enabled = true; this. _ chkAppend. enabled = true; this. _ btnRecord. enabled = true; if (this. _ txtVideoFileName. text = "") {// this. _ txtVideoF IleName. text = Math. round (Math. random () * 10000 ). toString (); this. _ txtVideoFileName. text = "demo";} this. _ btnRecord. label = "Recording"; this. _ btnRecord. removeEventListener (MouseEvent. CLICK, prepareStopRecord); this. _ btnRecord. addEventListener (MouseEvent. CLICK, startRecord) ;}} else if (e.info. code = "NetConnection. connect. closed ") {this. _ lblResult. text = "the server connection is closed! ";} Else {this. _ lblResult. text =" error-server connection failed! ";}}// Function cameraStatusHandler (e: StatusEvent): void {// trace (e); if (e. code = "Camera. muted ") {this. _ lblResult. text = "you are not allowed to use the camera! ";} Else if (e. code = "Camera. unmuted ") {this. _ lblResult. text = "getting the camera video... "; _ timer = new Timer (); // checks the camera status every Ms. A total of 20 cameraActivityHandler (null );}} // private function cameraActivityHandler (e: ActivityEvent): void {// trace ("cameraActivityHandler is called when the camera is active! "); If (! _ VideoIsWorked) {if (_ timer! = Null) {_ timer. addEventListener (TimerEvent. TIMER, checkCamera); _ timer. addEventListener (TimerEvent. TIMER_COMPLETE, checkCameraComplete); _ timer. start (); // trace ("_ timer started! ") ;}}// Timer callback function, used to check whether the camera device is correct. function checkCamera (e: TimerEvent): void {this. _ lblResult. text = "getting the camera video... "; if (this. _ camera. currentFPS> 0) {_ timer. stop (); _ videoIsWorked = true; this. _ lblResult. text = "the camera is working properly"; // restore the control availability; this. _ txtVideoFileName. enabled = true; this. _ chkAppend. enabled = true; this. _ btnRecord. enabled = true; if (this. _ txtVideoFileName. text = "") {// this. _ txtVideoFileName. text = Math. roun D (Math. random () * 10000 ). toString (); this. _ txtVideoFileName. text = "demo";} this. _ btnRecord. addEventListener (MouseEvent. CLICK, startRecord) ;}}// start recording private function startRecord (e: MouseEvent): void {// trace ("Start recording, _ nsPublish =", _ nsPublish ); if (this. _ nsPublish = null) {// trace ("re-create ns"); _ nsPublish = new NetStream (this. _ nc);} this. _ nsPublish. attachCamera (this. _ camera); this. _ nsPublish. publish (this. _ txtVideoF IleName. text, this. _ chkAppend. selected? "Append": "record"); this. _ nsPublish. addEventListener (NetStatusEvent. NET_STATUS, nsPublishNetStatus); // buffer for 20 seconds; this. _ nsPublish. bufferTime = 20;} private function nsPublishNetStatus (e: NetStatusEvent): void {// trace (e.info. code); if (e.info. code = "NetStream. play. streamNotFound "| e.info. code = "NetStream. play. failed "| e.info. code = "NetStream. publish. badName ") {this. _ lblResult. text = "Push failed, cause:" + e. Info. code;} else if (e.info. code = "NetStream. record. start "| e.info. code = "NetStream. buffer. empty ") {// recording starts this. _ btnRecord. removeEventListener (MouseEvent. CLICK, startRecord); this. _ btnRecord. addEventListener (MouseEvent. CLICK, prepareStopRecord); this. _ lblResult. text = "recording... "; this. _ btnRecord. label = "stop"; // playback of this is prohibited during recording. _ btnPlay. enabled = false; // this. _ btnPlay. label = "play"; this. _ btnPlay. removeEv EntListener (MouseEvent. CLICK, this. doStopPlay); this. _ btnPlay. addEventListener (MouseEvent. CLICK, this. doPlay) ;}} private function nsPlayNetStatus (e: NetStatusEvent): void {// trace (e.info. code); // if (e.info. code = "NetStream. play. streamNotFound "| e.info. code = "NetStream. play. failed ") {} else if (e.info. code = "NetStream. play. start ") {}} private function doStopPlay (e: MouseEvent): void {if (this. _ nsPlay! = Null) {this. _ videoPlay. attachNetStream (null); this. _ videoPlay. clear (); this. _ ncPlay. close (); this. _ ncPlay = null; this. _ nsPlay. close (); this. _ nsPlay = null; this. _ btnPlay. label = "play"; this. _ btnPlay. removeEventListener (MouseEvent. CLICK, doStopPlay); this. _ btnPlay. addEventListener (MouseEvent. CLICK, doPlay); // trace ("stopped! ") ;}} Function doPlay (e: MouseEvent): void {if (this. _ ncPlay = null) {this. _ ncPlay = new NetConnection (); this. _ ncPlay. addEventListener (NetStatusEvent. NET_STATUS, ncPlayNetStatus); this. _ ncPlay. connect (this. _ txtServerUrl. text) ;}} private function ncPlayNetStatus (e: NetStatusEvent): void {if (e.info. code = "NetConnection. connect. success ") {if (this. _ nsPlay = null) {// trace ("_ nsPlay has been created! "); This. _ nsPlay = new NetStream (this. _ ncPlay); this. _ nsPlay. addEventListener (NetStatusEvent. NET_STATUS, nsPlayNetStatus); var _ client: Object = new Object (); _ client. onMetaData = nsPlayOnMetaData; _ client. onPlayStatus = nsPlayOnPlayStatus; this. _ nsPlay. client = _ client; this. _ nsPlay. bufferTime = 5; this. _ nsPlay. play (this. _ txtVideoFileName. text); this. _ videoPlay. attachNetStream (this. _ nsPlay); this. _ btnPlay. la Bel = "stop"; this. _ btnPlay. removeEventListener (MouseEvent. CLICK, doPlay); this. _ btnPlay. addEventListener (MouseEvent. CLICK, doStopPlay) ;}} private function nsPlayOnMetaData (e: Object): void {trace ("onmetaData:" + e. duration);} private function nsPlayOnPlayStatus (e: Object): void {trace ("onPlayStatus:" + e. code); if (e. code = "NetStream. play. complete ") {trace (" playback stopped "); this. _ videoPlay. attachNetStream (null); this. _ VideoPlay. clear (); this. _ btnPlay. label = "play"; this. _ btnPlay. removeEventListener (MouseEvent. CLICK, doStopPlay); this. _ btnPlay. addEventListener (MouseEvent. CLICK, doPlay); this. _ ncPlay. close (); this. _ ncPlay = null; this. _ nsPlay. close (); this. _ nsPlay = null ;}}// prepare to stop recording private function prepareStopRecord (e: MouseEvent) {this. _ nsPublish. attachCamera (null); var _ bufferLength = this. _ nsPublish. bufferLength; // must wait for the Current Buffer If (_ bufferLength> 0) {this. _ btnRecord. label = "Wait... "; this. _ lblResult. text = "saving... please wait... "; // check every 0.1 seconds _ timer = new Timer (100); _ timer. addEventListener (TimerEvent. TIMER, doWait); _ timer. start ();} else {// trace ("Stop! "); StopPublish () ;}// stop publishing (recording) private function stopPublish (): void {if (this. _ nsPublish! = Null) {this. _ nsPublish. removeEventListener (NetStatusEvent. NET_STATUS, nsPublishNetStatus); this. _ nsPublish. close (); this. _ nsPublish = null;} this. _ btnRecord. label = "Recording"; this. _ lblResult. text = ""; this. _ btnRecord. removeEventListener (MouseEvent. CLICK, prepareStopRecord); this. _ btnRecord. addEventListener (MouseEvent. CLICK, startRecord); // allows playback; this. _ btnPlay. enabled = true; this. _ btnPlay. label = "play"; this. _ btnPlay. removeEventListener (MouseEvent. CLICK, doStopPlay); this. _ btnPlay. addEventListener (MouseEvent. CLICK, doPlay);} // wait until all the data in the recorded video buffer is saved to the server. private function doWait (e: TimerEvent) {var _ bufferLength = this. _ nsPublish. bufferLength; if (_ bufferLength <= 0) {_ timer. removeEventListener (TimerEvent. TIMER, doWait); _ timer. stop (); _ timer = null; stopPublish () ;}} function checkCameraComplete (e: TimerEvent): void {this. _ lblResult. text = "unable to use the device (may be occupied)"; _ timer. removeEventListener (TimerEvent. TIMER, checkCamera); _ timer. removeEventListener (TimerEvent. TIMER_COMPLETE, checkCameraComplete); _ timer = null ;}}}
Interface:
Sample source code download: http://cid-2959920b8267aaca.office.live.com/self.aspx/Flash/VideoRecording.rar