Record Live Stream With Red5 Media Server

Most commonly known modes of working in RTMP servers  are the live, record and append modes. However a most commonly required mode which is not provided in the flash API is the Live-Record mode. Each RTMP server has its own way of implementing it on the server side. Here we will see how to use flash client and Red5 to do live-record.

Red5 Server Application Code: – [ Goes into Application Class ]

/** {@inheritDoc} */
@Override
public boolean connect(IConnection conn, IScope scope, Object[] params) {
return true;
}

/** {@inheritDoc} */
@Override
public void disconnect(IConnection conn, IScope scope) {
super.disconnect(conn, scope);
}

@Override
public void streamPublishStart(IBroadcastStream stream)
{
try {
stream.saveAs(stream.getPublishedName(), false);
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void streamBroadcastClose(IBroadcastStream stream)
{
System.out.print("Broadcast Closed");
}

@Override
public void streamBroadcastStart(IBroadcastStream stream)
{
System.out.print("Broadcast Started");
}

In the above code you will see there are two events for handling BroadcastStart:  streamBroadcastStart and streamPublishStart. We will typically use streamPublishStart which is safer. The method saveAs takes two parameters: savefilename and append. When append is true Red5 will try to append new stream data to existing file , in which case it may throw exception if file was not existing. Thus we surround the statement by a  try… catch block to handle such situations.

Flash Client Sample:

In your flash client code you create a simple publisher and publish the stream as live stream. Red5 will automatically begin recording the stream at server end.

import flash.events.NetStatusEvent;
import flash.events.StatusEvent;
import flash.media.*;
import flash.system.*;
import flash.events.MouseEvent;
import fl.controls.Button;

var mic:Microphone;
var cam:Camera;
var micAllowed:Boolean = false;
var camAllowed:Boolean = false;
var nc:NetConnection = new NetConnection();
var ns:NetStream;

nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatus);
nc.connect("rtmp://localhost/customstreamer");

function onNetStatus(e:NetStatusEvent):void
{
switch(e.info.code)
{
case "NetConnection.Connect.Success":
initStream();
attachDevices();
break;
}
}

function onStreamStatus(e:NetStatusEvent):void
{
trace(e.info.code);
}

function initStream()
{
ns = new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS,onStreamStatus);
}

function attachDevices():void
{
mic = Microphone.getMicrophone();
cam = Camera.getCamera();
if(mic != null) configureMic();
if(cam != null) configureCam();
}

function configureMic()
{
mic.rate = 22;
mic.gain = 50;
mic.setLoopBack(true);
mic.setUseEchoSuppression(true);
mic.addEventListener(StatusEvent.STATUS, onMicStatus);
}

function configureCam()
{
cam.setLoopback(true);
cam.setMode(176,144,15);
cam.setKeyFrameInterval(5);
cam.setQuality(0,70);
cam.addEventListener(StatusEvent.STATUS, onCamStatus);
vid.attachCamera(cam);
}

function onMicStatus(s:StatusEvent):void
{
switch(s.code)
{
case "Microphone.Unmuted":
micAllowed = true;
break;

case "Microphone.Muted":
micAllowed = false;
break;
}

validateRecorder();
}

function onCamStatus(s:StatusEvent):void
{
switch(s.code)
{
case "Camera.Unmuted":
camAllowed = true;
break;

case "Camera.Muted":
camAllowed = false;
break;
}

validateRecorder();
}

function validateRecorder()
{
if(camAllowed || micAllowed)
{
btnStart.addEventListener(MouseEvent.CLICK,onStart);
btnStop.addEventListener(MouseEvent.CLICK,onStop);
}
}

function onStart(me:MouseEvent):void
{
ns.attachAudio(mic);
ns.attachCamera(cam);
ns.publish("demostream","live");
}

function onStop(me:MouseEvent):void
{
ns.close();
}

You will notice that in the above code we stream cam/mic data in live mode. And our server side code captures the live broadcast into a flv container.

Download FLA: (required Flash CS5)

last comments
Jorj
Jorj

Thank you so much! I've been searching for this functionality :)
adilfacron
adilfacron

Thank you for example. I have a queston. I tried your example, everything worked well but recorded flv contains nothing…
PJ
PJ

Thank you. Great example. I think Red5 is a great alternative to FMS & Wowza since its open…
oliver_vip
oliver_vip

thax alot! this is a thanksgiving letter from China!

Red5 – Online Application Generator


The Red5 Online Application Generator is a very simple but effective utility to generate Red5 application online. Do not worry if you don’t know Red5 or even Java. Generate streamer applications, with live broadcasting, streaming, recording and sharedObject capabilities in a single click. No compiling/editing needed. The generator creates red5 applications for you on the fly by injecting necessary information into pre-compiled red5 application templates and prepares them for hassle free use. (more…)

last comments ...
Simon
Simon

Yes please, could you update for red5 1.0 ? Thank you.
adilfacron
adilfacron

This is awesome, thank you. One little bug: I can not put a : character to paths, so fix…
Eyal
Eyal

please, please, please update it for red5 1.0...
Tincho
Tincho

Exelent app!
limes
limes

red5 v 1.0.1 pls update :)

Ready to use – Red5 streamer application

Following Red5 Developer series from Dominick Accattato, and a neat explaination from Red5.org on CustomFilenameGenerator, Here is a ready to use, fully capable pre-compiled Red5 application for anyone who wishes to set up Flash streaming with Red5 , but does not know where to start.

The application is tested on Red5 0.8. to use it in 0.9 you may have to remove the bandwidth-setting code in main Application class and recompile it.

How to configure Stream/Record paths:


1. Edit the file file red5-web.xml in the WEB-INF directory

2. Move down to the “streamFilenameGenerator” bean definition and adjust values of recordPath and playbackPath as you wish.

3. To use absolute paths, set “absolutePath” property as true.

Downloads:

Customstreamer_deployable_0.8

CustomStreamer_source_0.8

# Update : Customstreamer for Red5 0.9:

Customstreamer_deployable_0.9

CustomStreamer_source_0.9

# Update : Customstreamer for Red5 0.7: [Updated June 17 2010]

Customstreamer_deployable_0.7

*Try out the new Red5 application generator HERE

Note:  To compile source, use eclipse J2ee build.

Connecting Red5 and Amf-php

Its been a long goal for me to connect Red5 to amfphp. You will see frequent needs of interacting with MySQL database from red5. Many people suggest using JDBC. Although thats  valid suggestion, its more of a headache for a non Java developer and the server administrator. Many people also suggest using flash to amfphp direct., but mind it thats the most incorrect way of doing things, when you want it secure.

Here is how you actually get Java to talk to php, the modern style :).  First anf foremost grab a copy of amfphp 1.2 from Sourceforge. Note: download amfphp 1.2,  as amfphp 1.9 is not compatible with red5’s amf decoding.

Step 1.  Setup the amfphp gateway at your server root. Like so:

http://localhost/amfphp

See video on setting up amfphp

Step 2. Download and install red5, then setup a new application using red5plugin in eclipse. (i wont discuss how to setup red5 application here. you can refer to external links for that. Mainly: Red5 developer series videos)

Step 3.  Create a new amfphp service class like this and save as Red5Service.php in services folder of amfphp.

<?php
class Red5Service
{

function  Red5Service()
{
$this->methodTable = array(
"login" => array(
"description" => "login user -> returns true/false",
"access" => "remote",
"arguments" => array ("username","password")
),
"logout" => array(
"description" => "logout user -> returns nothing",
"access" => "remote",
"arguments" => array ("username")
)  
);
}  

function login($username,$password)
{
return true;
}

function logout($username)
{
return;
}
}
?>

Step 4. In your red5 application, connect method  place a call to your amfphp service,  as shown below:

/** {@inheritDoc} */
@Override
public boolean connect(IConnection conn, IScope scope, Object[] params)
{
try
{
RemotingClient client = new RemotingClient("http://localhost/amfphp/gateway.php");
Object[] args = new Object[]{'rajdeep','xyz123'};
Object result = client.invokeMethod("Red5Service.login", args);

if(!result.equals(true)) return false; 
}
catch (IOException e)
{
return false;
}
return true;   
}

As you will see when a user connects to red5 application, the connect handler makes a connection to amfphp gateway and sends the parameters ‘rajdeep’ and ‘xyz123’ as arguments. the amf service can then do its own computations as you want it to and return a boolean expression – true/false at the end. If the java RemotingClient receives a true it lets the connect method accepts the connection else reject it. Also note the try catch block.  also since we dont know what network situations may prevail, so need to be sure that if red5 cannot connect to amfphp it will reject the client connection anyways.

Thats all  for the basics to make things hotter try experimenting with params sent to red5 from flash and the database stuff 🙂