Monitoring video recording on RED5 Video Server

Jul 31, 2015   /  

red5-recorder

“Red5 is an Open Source Flash Server written in Java that
supports:

·        
Streaming Video
(FLV, F4V, MP4, 3GP)

·        
Streaming Audio
(MP3, F4A, M4A, AAC)

·        
Recording Client
Streams (FLV and AVC+AAC in FLV container)”

 

You can check it on red5-server.

 

In this blog we will try implementing a
simple logic to limit the size of recorded video files with Red5. If a video
file grows exceeding 100MB in recoding, we should stop recording and notify
client side.

 

Red5 Server is built on top of an
embedded Tomcat Server. It has a hierarchy of different “scopes”. The
applications running on RED5 Server are supposed to be packaged as Java Web
applications with web.xml declaration and declare its “scope” to plug into Red5’s
scopes.

 

web.xml (Since the RED5 1.0.5 version
uses Tomcat 7. It can support Servlet 3.0)

<?xml version="1.0"
encoding="ISO-8859-1"?>

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
>

 

    <display-name>video_app</display-name>

 

    <filter>

        <filter-name>encodingFilter</filter-name>

        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

        <init-param>

            <param-name>encoding</param-name>

            <param-value>UTF-8</param-value>

        </init-param>

        <init-param>

            <param-name>forceEncoding</param-name>

            <param-value>true</param-value>

        </init-param>

    </filter>

    <filter-mapping>

        <filter-name>encodingFilter</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

    <context-param>

        <param-name>globalScope</param-name>

        <param-value>default</param-value>

    </context-param>

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>/WEB-INF/red5-*.xml</param-value>

    </context-param>

<!—other configurations–>

</web-app>

 

Red5 is also a Spring Application;
Developers can extend/weave business logics into Red5 Server using Spring.

We can utilize the spring libs shipped
with Red5 server. Like adding this into our pom.xml in Maven project
(supposedly)

 

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-context</artifactId>

            <version>4.0.8.RELEASE</version> <!–  for red5 1.0.5
–>

            <scope>provided</scope>

</dependency>

 

Therefore the web.xml refers to
red5-*.xml that are actually Spring configuration xml
files, which would be recognized and launched by Red5 Server.

 

<?xml version="1.0"
encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

   
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns:lang="http://www.springframework.org/schema/lang"

        xmlns:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

       
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-3.1.xsd

       
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd"
>

 

<!–

Context – Each context must have a unique
name assigned since all the

contexts exist within a single Spring application context. The root web

context is named web.context,
additional contexts suffix this base name

with their web application name; for example
video_app would be named

web.context.video_app. A context is specified in the
web context file as

shown below.

 –>

    <bean id=" web.context.video_app" class="org.red5.server.Context"
autowire="byType">

        <property name="clientRegistry" ref="global.clientRegistry" />

       

        <!– Interface for
objects that execute service calls (remote calls from client). –>

        <!– Makes remote calls, invoking services, resolves service handlers
–>

        <property name="serviceInvoker" ref="global.serviceInvoker" />

       

        <!–

         Basic mapping strategy implementation.
This one uses slash as filesystem path
separator,

         ‘.service’ postfix for services
naming, ‘.handler’ for handlers naming and ‘default’ string as

         default
application name. –>

    </bean>    

   

    <bean id="video_app.handler" class="your.app.handler.Application"/>

    <!–A scope bean has the following properties:

        1.
server – This references the server red5.server

        2.
parent – The parent for this scope is normally global.scope

        3.
context – Context for this scope

        4.
handler – Handler for this scope, which is similar to a main.asc
in

        FMS.

        5.
contextPath – The path to
use when connecting to this scope.

        6.
virtualHosts – A comma separated list of host names
or IP

        addresses this scope listens on. In the war version we do
not

        control
the host names, this is accomplished –>

    <bean id="web.scope" class="org.red5.server.scope.WebScope">

        <!– The interface that
represents the Red5 server.    
–>

        <property name="server"
ref="red5.server" />

       

        <!– org.red5.server.scope.BasicScope.parent –>

        <!– Parent scope.
Scopes can be nested. –>

        <property name="parent"
ref="global.scope"
/>

       

        <!– The current context, this object basically wraps the Spring
context

            or in the case of the .Net version, any similar system.
–>

        <property name="context"
ref="video_app.context"
/>

       

        <!–

        The
scope handler controls actions performed against a scope object,

        and also is notified of all events. Gives fine grained
control over

        what actions can be performed with the can* methods.

        Allows
for detailed reporting on what is happening within the scope with the on*
methods.

        This
is the core interface users implement to create applications.

        The
thread local connection is always available via the Red5 object within these
methods

         –>

        <property name="handler"
ref="video_app.handler"
/>

        <property name="contextPath" value="/video_app" />

        <property name="virtualHosts" value="*"
/>     

       

    </bean>

 

    <bean id="clientBroadcastStream"
class="your.app.YourClientBroadcastStream"
lazy-init="true"
scope="prototype">

        <property name="sizeLimit"
value="104857600" />

        <!– 100MB –>

    </bean>

</beans>

 

In order to monitor flash video
recording, we can create a sub-class of

 

/**

 * Represents live stream broadcasted
from client. As Flash Media Server, Red5 supports

 * recording mode for live streams, that
is, broadcasted stream has broadcast mode. It can be either

 * "live" or
"record" and latter causes server
side application to record broadcasted stream.
*/

org.red5.server.stream.ClientBroadcastStream

 

In the sub class, we can implement the
logic to check the size of received data.

 

Your.app.YourClientBroadcastStream

public class YourClientBroadcastStream
extends ClientBroadcastStream
{

    public final static String NS_RECORD_STOP_OVERSIZE = StatusCodes.NS_RECORD_STOP + ".oversize";

    public YourClientBroadcastStream()
{

        log.info("\n\tYourClientBroadcastStream()");

    }

   

    private long sizeLimit = -1;

    public long getSizeLimit() {

        if (sizeLimit <= 0) {       // if the limit
value isn’t set

            sizeLimit = 104857600L; // default limit
would be 100MB

        }

        return sizeLimit;

    }

    //the size limit property can be set in red5-web.xml by spring

    public void setSizeLimit(long sizeLimit) {

        this.sizeLimit = sizeLimit;

    }

 

    private static final Logger log = LoggerFactory.getLogger(YourClientBroadcastStream.class);

    //Data of video stream goes through this method wrapped in IEvent Object.

    public void dispatchEvent(IEvent
event) {

        super.dispatchEvent(event);

        if (super.closed || !super.isRecording()) return;

           

        if (super.getBytesReceived() > sizeLimit) { //if received data exceeds the limit of
size

            log.info(String.format("\n%s (%d) exceeds size limit of
%s\n"
, super.getSaveFilename(), super.getBytesReceived(), sizeLimit));

           

            sendRecordStopNotifyForOversize(); //send a message to notify the client
side.

            log.info(String.format("\n\toversize is sent for video: %s", super.getSaveFilename()));

           

            super.stop(); // stop recording

            log.info(String.format("\n\trecording for video: %s has been
stopped due to oversize: %d"
, super.getSaveFilename(), super.getBytesReceived()));

        }

    }

   

    private void sendRecordStopNotifyForOversize() {

        Status
stopStatus = new Status(NS_RECORD_STOP_OVERSIZE);

        stopStatus.setClientid(getStreamId());

        stopStatus.setDetails(getPublishedName());

 

        StatusMessage stopMsg = new StatusMessage();

        stopMsg.setBody(stopStatus);

        pushMessage(stopMsg);

    }

}

 

 

Bind the sub class with name "clientBroadcastStream" in red5-web.xml.

That is it. But not only monitoring the
size of video file, there would be many features can be implemented with Red5
Server.

Scan the QR code with WeChat.

Scan the QR
code with WeChat.