I have setup RED5 1.0 Final on my Windows 8 system and I am trying to get recording to work correctly. A tutorial I read said to buffer the data on the client side ( in Flash) and then once the buffer is empty close the connection.
The issue I am having is that when I begin recording the buffer immediately reports that it is empty (NetStream.Buffer.Empty). I have had it work once or twice where the buffer does actually fill up but for some reason it stopped working that way.
I can see that the client is still sending data to the server even after I detach the camera from the netstream because the file on the server side continues to grow. My solution at the moment is to wait 60 seconds after recording has stopped before closing the connection.
One thing of interest is that when there is no more packets to be sent, I see on the server side that the file switches from mystream.ser to mystream.flv and stops growing in size. I was thinking of writing some code on the server side to wait for this event to happen and then let the client know that it can close the stream.
This is my first foray into action script so I may be doing something completely wrong here. Please let me know.
EDIT Here's the client code
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:ns1="*"
minWidth="955" minHeight="600" applicationComplete="init()" >
<fx:Script>
<![CDATA[
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.NetStatusEvent;
import flash.media.Camera;
import flash.media.H264Level;
import flash.media.H264Profile;
import flash.media.H264VideoStreamSettings;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
var cam:Camera = Camera.getCamera();
var mic:Microphone = Microphone.getMicrophone();
var nc:NetConnection = new NetConnection();
var activeStream:NetStream;
private var bufferCheckTimer:Timer;
var recordHalted:Boolean = false;
protected function init(): void{
recordButton.enabled = false;
stopButton.enabled = false;
nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
nc.connect("rtmp://localhost/oflaDemo");
nc.client = this;
}
public function onMetaData(info:Object):void {
trace("playback called onMetaData");
}
public function onBWDone(... rest) : void {
// have to have this for an RTMP connection
trace('onBWDone');
}
public function onBWCheck(... rest) : uint {
trace('onBWCheck');
//have to return something, so returning anything :)
return 0;
}
protected function onNetStatus(event:NetStatusEvent):void{
trace(event.info.code);
if(nc.connected)
{
SetupCameraAndMic();
recordButton.enabled = true;
stopButton.enabled = true;
}
}
protected function SetupCameraAndMic(): void{
activeStream = new NetStream(nc);
activeStream.bufferTime = 60;
activeStream.client = this;
activeStream.addEventListener(NetStatusEvent.NET_STATUS, handleStreamStatus,false,0,true);
var h264Settings:H264VideoStreamSettings = new H264VideoStreamSettings();
h264Settings.setProfileLevel(H264Profile.BASELINE, H264Level.LEVEL_2);
activeStream.videoStreamSettings = h264Settings;
cam.addEventListener(StatusEvent.STATUS, handleCameraStatus, false, 0, true);
mic.addEventListener(StatusEvent.STATUS, handleMicrophoneStatus, false, 0, true);
cam.setMode(320,240, 15);
cam.setQuality(0, 80);
cam.setKeyFrameInterval(7);
mic.rate = 44;
mic.gain = 75;
mic.setSilenceLevel(0);
mic.setUseEchoSuppression(true);
activeStream.attachCamera(cam);
activeStream.attachAudio(mic);
videoContainer.attachCamera(cam);
}
private function handleCameraStatus(e:StatusEvent):void {
trace("handleCameraStatus - " + e.code);
switch(e.code) {
case 'Camera.muted':
// Show a message
break;
case 'Camera.Unmuted':
//finishCamAndMicSetup();
break;
}
}
private function handleMicrophoneStatus(e:StatusEvent):void {
trace("handleMicrophoneStatus - " + e.code);
switch(e.code) {
case 'Microphone.Muted':
// Show a message
break;
case 'Microphone.Unmuted':
//finishCamAndMicSetup();
break;
}
}
private function handleStreamStatus(e:NetStatusEvent):void {
switch(e.info.code) {
case 'NetStream.Buffer.Empty':
trace("NetStream.Buffer.Empty");
break;
case 'NetStream.Buffer.Full':
trace("NetStream.Buffer.Full");
break;
case 'NetStream.Buffer.Flush':
trace("NetStream.Buffer.Flush");
break;
}
}
protected function recordButton_clickHandler(event:MouseEvent):void
{
if(activeStream == null)
{
SetupCameraAndMic();
}
if(activeStream != null){
var tempDate:Date = new Date();
var uniqueFileName:String = "RecordME_" + String(tempDate.getMinutes()) + String(tempDate.getMilliseconds());
bufferLabel.text = ""+ activeStream.bufferTime;
activeStream.publish(uniqueFileName, "record");
bufferCheckTimer = new Timer(100);
bufferCheckTimer.addEventListener(TimerEvent.TIMER, handleBufferCheck, false, 0, true);
bufferCheckTimer.start();
}
}
private function handleBufferCheck(e:TimerEvent):void {
if(activeStream != null) {
trace("Buffer: " + activeStream.bufferLength);
statusLabel.text = "Buffer: " + activeStream.bufferLength;
if (recordHalted == true) {
if ( activeStream.bufferLength == 0 ) {
activeStream.close();
activeStream = null;
bufferCheckTimer.stop();
bufferCheckTimer.removeEventListener(TimerEvent.TIMER, handleBufferCheck);
bufferCheckTimer = null;
// OK - playback time
//doRecordingPlayback();
}
}
if (bufferCheckTimer != null) {
bufferCheckTimer.reset();
bufferCheckTimer.start();
}
}
}
protected function stopButton_clickHandler(event:MouseEvent):void
{
activeStream.attachCamera(null);
activeStream.attachAudio(null);
videoContainer.attachCamera(null);
recordHalted = true;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:VideoDisplay id="videoContainer" x="158" y="53" width="640" height="480"
chromeColor="#3C2020" />
<s:Button id="recordButton" x="396" y="546" label="Record"
click="recordButton_clickHandler(event)"/>
<s:Button id="stopButton" x="491" y="546" label="Stop Recording"
click="stopButton_clickHandler(event)"/>
<s:Label id="statusLabel" x="158" y="555" width="207"/>
<s:Label x="14" y="408" text="Buffer Set to:"/>
<s:Label id="bufferLabel" x="91" y="408" text="0"/>
</s:Application>
Thanks