Install Red5 server
- Download Java Linux RPM (32 or 64) and run it.
chmod a+x jre-<version>-rpm.bin
./jre-<version>-rpm.bin
rpm -iv jre-<version>.rpm
java -version - Install Red5
cd /usr/src
mkdir red5
cd red5
wget http://red5.nl/installer/red5-0.7.0.tar.gz
tar zxf red5-0.7.0.tar.gz
mkdir dist
cp red5.jar dist/
cp red5.sh dist/
cp -r conf/ dist/
cp -r lib/ dist/
cp -r webapps/ dist/
make install
make clean
cd /usr/lib/red5
./red5.sh
- Verify that Red5 start correctly and stop it (Ctrl-C). Create service startup file
nano /etc/init.d/red5 #!/bin/sh # # red5: Red 5 Server # # chkconfig: - 26 89 # description: Red 6 Stream Server. # # Source function library. . /etc/rc.d/init.d/functions [ -f /etc/sysconfig/network ] && . /etc/sysconfig/network [ "${NETWORKING}" = "yes" ] || exit 0 RED5_DIR=/usr/lib/red5 test -x $RED5_DIR/red5.sh || exit 5 start() { echo -n $"Starting Red5 Service: " cd $RED5_DIR daemon /bin/bash -c "$RED5_DIR/red5.sh >/dev/nul &" sleep 2 echo } stop() { echo -n $"Shutting down Red5" killall -q java sleep 2 echo } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart) stop start ;; *) echo $"Usage: $0 {start|stop|restart}" exit 1 esac chmod 755 /etc/init.d/red5
Change default ports
chkconfig --add red5
chkconfig --level 345 red5 on
service red5 start
service red5 stop
nano /usr/lib/red5/conf/red5.properties
# HTTP
http.host=0.0.0.0
http.port=80
#https.port=443
# RTMP
rtmp.host=0.0.0.0
rtmp.port=1935
rtmp.event_threads_core=16
rtmp.event_threads_max=64
# event threads queue: -1 unbounded, 0 direct (no queue), n bounded queue
rtmp.event_threads_queue=0
rtmp.event_threads_keepalive=60
rtmp.send_buffer_size=271360
rtmp.receive_buffer_size=65536
rtmp.ping_interval=5000
rtmp.max_inactivity=60000
rtmp.tcp_nodelay=true
# RTMPT
rtmpt.host=0.0.0.0
rtmpt.port=8088
rtmpt.ping_interval=5000
rtmpt.max_inactivity=60000
# MRTMP
mrtmp.host=0.0.0.0
mrtmp.port=9035
mrtmp.event_threads_core=4
mrtmp.event_threads_max=32
# event threads queue: -1 unbounded, 0 direct (no queue), n bounded queue
mrtmp.event_threads_queue=0
mrtmp.event_threads_keepalive=60
mrtmp.send_buffer_size=271360
mrtmp.receive_buffer_size=65536
mrtmp.ping_interval=5000
mrtmp.max_inactivity=60000
mrtmp.tcp_nodelay=true
# Debug proxy (needs to be activated in red5-core.xml)
proxy.source_host=127.0.0.1
proxy.source_port=1936
proxy.destination_host=127.0.0.1
proxy.destination_port=1935
- Create Files folder and configure it
mkdir /usr/lib/red5/webapps/Files
mkdir /usr/lib/red5/webapps/Files/WEB-INF
cd /usr/lib/red5/webapps/Files/WEB-INF
nano red5-web.properties
webapp.contextPath=/Files
webapp.virtualHosts=*, localhost:88, localhost, localhost:80, 127.0.0.1:80, 127.0.0.1:88
nano red5-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/red5-web.properties" />
</bean>
<bean id="web.context" class="org.red5.server.Context" autowire="byType" />
<bean id="web.scope" class="org.red5.server.WebScope"
init-method="register">
<property name="server" ref="red5.server" />
<property name="parent" ref="global.scope" />
<property name="context" ref="web.context" />
<property name="handler" ref="web.handler" />
<property name="contextPath" value="${webapp.contextPath}" />
<property name="virtualHosts" value="${webapp.virtualHosts}" />
</bean>
<bean id="web.handler" class="org.red5.server.adapter.ApplicationAdapter" singleton="true" />
</beans>
nano web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Video Library</display-name>
<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>
<context-param>
<param-name>locatorFactorySelector</param-name>
<param-value>red5.xml</param-value>
</context-param>
<context-param>
<param-name>parentContextKey</param-name>
<param-value>default.context</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/Files</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<mime-mapping>
<extension>flv</extension>
<mime-type>video/flv</mime-type>
</mime-mapping>
<mime-mapping>
<extension>jpg</extension>
<mime-type>image/jpeg</mime-type>
</mime-mapping>
</web-app>
Install samba server and configure to anonymous access (disable SELINUX). Use separate network share server (OpenFiler) to CommunityServer/Red5 farm.
yum -y install samba
nano /etc/samba/smb.conf
[global]
workgroup = WORKGROUP
netbios name = VIDEO
security = share
wins support = yes
[data]
comment = Data
path = /usr/lib/red5/webapps
force user = root
force group = root
read only = No
guest ok = Yes
chkconfig --level 345 smb on
service smb start
- Check access to network share \\VIDEO\data
Make changes in CommunityServer 2008 (CS2008.5_4.1.30912.2823)
- Change CommunityServer PostAttachment storage location to network share (communityserver.config)
<fileStore name="CommunityServer.Components.PostAttachments" basePath="~/filestorage/"
type="CommunityServer.Components.FileSystemFileStorageProvider, CommunityServer.Components"
...
to
<fileStore name="CommunityServer.Components.PostAttachments" basePath="\\VIDEO\data\Files"
type="Custom.Components.FileSystemFileStorageProvider, Custom.Components"
externalUrl="http://external_Red5_FQDN/Files"
...
or
<fileStore name="CommunityServer.Components.PostAttachments" basePath="\\ip_address\data\Files"
type="Custom.Components.FileSystemFileStorageProvider, Custom.Components"
externalUrl="http://external_Red5_ip_address/Files"
...
- Copy Custom.Components.dll to bin folder and restart IIS
- Try to upload file to MediaGallery and check it on network share (\\VIDEO\data\Files)
If you need convert video files to FLV format make conversion service on samba server (OpenFiler or Red5)
Install ffmpeg and flvtool2 from dag repository on Centos i386 and x86_64 platform.
- Add dag.repo to /etc/yum.repos.d
nano /etc/yum.repos.d/dag.repo
[dag]
name=Dag RPM Repository for Red Hat Enterprise Linux
baseurl=http://apt.sw.be/redhat/el$releasever/en/$basearch/dag
gpgcheck=0
enabled=1
- Install ffmpeg, flvtool2 and perl libwww package
yum -y install ffmpeg flvtool2 perl-libwww-perl
- Check ffmpeg and flvtool2
ffmpeg
flvtool2
- Create conversion service
nano /usr/sbin/flvconv.pl
#!/usr/bin/perl
use strict;
use LWP;
use File::Basename;
#
# Post processing statuses:
# 0 OK
# 1 unknown error during processing
# 2 file not exists
# 3 file not readable
# 4 ffmpeg fail
# 5 flvtool2 fail
# 6 ffmpeg fail on preview processing
# 7 ffmpeg fail on thumbnail processing
# 8 ffmpeg fail on small thumbnail processing
# 9 can't rename original file to xxxx.org file
my $retry_per_instance = 2; # request retry per instance
my $request_def = "http://#server#/api/ConversionService.aspx";
my $response_def = "http://#server#/api/ConversionService.aspx?Complete=&TaskID=#taskID#&PostID=#postID#&PostStatus=#status#";
my $size_def = "480x360"; # default video size
my $aspect_def = "4:3"; # default video aspect
my $thumbnail_def = "120x90"; # default thumbnail size or empty to disable generation
my $thumbnail_small_def = "60x45"; # default small thumbnail size or empty to disable generation
my $watermark_def = ""; # default watermark file
my $watermark_tmpl = "'/usr/lib/vhook/watermark.so -m 1 -t 000000 -f #image#'";
# my $watermark_tmpl = "'/usr/lib64/vhook/watermark.so -m 1 -t 000000 -f #image#'";
#
# site instances definition
#
my @instances_def = (
[
"cs_site_0", # servers list of this instance or cs_site_0;cs_site_1[;...]
$request_def, # template for server request
$response_def, # template for server response
"360x270", # video size
"120x90", # thumbnail size
"80x60", # thumbnail small size
"", # add watermark
$aspect_def, # ascept ratio
],
);
my $pathCS = '^\\\\\\\\VIDEO\\\\data\\\\'; # Windows network share (see communityserver.config CentralizedFileStorage section)
# or
# my $pathCS = '^\\\\\\\\ip_address\\\\data\\\\'; # ip_address = 10\.0\.0\.1
my $pathLocal = '/usr/lib/red5/webapps/'; # Linux path to files
my $pathDelimCS = '\\\\'; # Windows path separator \
my $pathDelimLocal = '/'; # Linux path separator /
#
# Build internal servers array from instances
#
my @instances = ();
foreach(@instances_def) {
next unless( $_ );
my @p = @{$_};
next unless( $p[0] );
my @srv = (
0,
[split(";", $p[0])],
($p[1] or $request_def),
($p[2] or $response_def),
($p[3] or $size_def),
($p[4] or $thumbnail_def),
($p[5] or $thumbnail_small_def),
($p[6] or $watermark_def),
($p[7] or $aspect_def)
);
push(@instances, \@srv);
}
@instances or die "No instances define.";
my $browser = LWP::UserAgent->new;
my $status = 0;
my $run = 1;
my $error;
my @args;
my $response;
my $url;
my $content;
my $original;
my $fileFlv;
my $url_request;
my $url_response;
my $video_size;
my $thumbnail_size;
my $thumbnail_small_size;
my $watermark;
my $aspect;
my $server;
while( $run ) {
foreach( @instances ) {
my $index = $_->[0];
my $retry = $retry_per_instance;
my $error = 0;
while(--$retry >= 0) {
my @srvs = @{$_->[1]};
$server = $srvs[$index]; # current server to request
$url_request = $_->[2];
$url_response = $_->[3];
$video_size = $_->[4];
$thumbnail_size = $_->[5];
$thumbnail_small_size = $_->[6];
$watermark = $_->[7];
$aspect = $_->[8];
if( $watermark ) {
my $ws = $watermark_tmpl;
$ws =~ s/#image#/$watermark/g;
$watermark = $ws;
}
$url = $url_request;
$url =~ s/#server#/$server/g; # prepare request url
$response = $browser->get( $url );
$error = 0;
unless( $response->is_success ) {
print "\nGet error. ".$url."\n\tresponse: ".$response->status_line."\n";
$error = 1;
if( @srvs > 1 ) { # if more servers presents for this instance then
$index++; # switch to next server and retry
$index < @srvs or $index = 0;
$_->[0] = $index; # store server index
next;
}
last; # only one server in instance - process next instance
}
unless( $response->content_type eq 'text/plain' ) {
print "\nNot a text/plain response -- ".$response->content_type."\n";
$error = 1;
if(@srvs > 1) {
$index++;
$index < @srvs or $index = 0;
$_->[0] = $index;
next;
}
last; # only one server in instance - process next instance
}
last; # process request
}
unless( $error ) {
$content = $response->content;
$content =~ s/\r//g;
foreach (split(/\n+/, $content)) { # convert response to lines array
next unless $_; # skip empty line
$status = 1;
my($taskID, $postID, $postType, $fileName) = split(/\t/, $_);
$fileName =~ s/$pathCS/$pathLocal/g; # change CS path to local path
$fileName =~ s/$pathDelimCS/$pathDelimLocal/g; # also change directory separator
$original = $fileName;
my $fileWoExt = $fileName;
$fileWoExt =~ s/\.[^.]*$//;
$fileFlv = $fileWoExt.".tmp";
print "Convert ".$original."\n to ".$fileFlv."\n";
while( $status == 1 ) {
if( $postType == 1 ) { # = 1 don't convert file - only thumbnail
unless( -e $original ) {
print "File not exist -- $original\n";
$status = 2;
last;
}
unless( -r $original ) {
print "File not readable -- $original\n";
$status = 3;
last;
}
print "Process file -- $original\n";
@args = ("flvconv", $original, $fileFlv, $video_size, $aspect); #, $watermark);
system(@args);
if( $? != 0 ) {
print "Fail ffmpeg: ",$?,"\n";
$status = 4;
last;
}
@args = ("flvtool2", "-U", $fileFlv);
system(@args);
if( $? != 0 ) {
print "Fail flv2tool: ",$?,"\n";
$status = 5;
last;
}
}
# make video thumbnail
@args = ("ffmpeg", "-y", "-i", $fileFlv, "-vframes", "1", "-ss", "00:00:01", "-an", "-s", $video_size, "-qmin", "1", "-f", "mjpeg", $fileWoExt.".jpg");
system(@args);
if( $? != 0 ) {
print "Fail ffmpeg (preview): ".$?." ".$fileFlv."\n";
$status = 6;
last;
}
if( $thumbnail_size ) {
@args = ("ffmpeg", "-y", "-i", $fileFlv, "-vframes", "1", "-ss", "00:00:01", "-an", "-s", $thumbnail_size, "-qmin", "1", "-f", "mjpeg", $fileWoExt."-".$thumbnail_size.".jpg");
system(@args);
if( $? != 0 ) {
print "Fail ffmpeg (thumbnail): ".$?." ".$fileFlv."\n";
$status = 7;
last;
}
}
if( $thumbnail_small_size ) {
@args = ("ffmpeg", "-y", "-i", $fileFlv, "-vframes", "1", "-ss", "00:00:01", "-an", "-s", $thumbnail_small_size, "-qmin", "1", "-f", "mjpeg", $fileWoExt."-".$thumbnail_small_size.".jpg");
system(@args);
if($? != 0) {
print "Fail ffmpeg (small): ".$?." ".$fileFlv."\n";
$status = 8;
last;
}
}
$status = 0;
last;
}
$url = $url_response;
$url =~ s/#server#/$server/g;
$url =~ s/#taskID#/$taskID/g;
$url =~ s/#postID#/$postID/g;
$url =~ s/#status#/$status/g;
if( $status ) {
print "Process Error $status -- ".$url."\n";
} else {
print "Success -- ".$url."\n";
}
$response = $browser->get( $url );
unless( $response->is_success ) {
print "Can't get $url -- $response->status_line\n";
next;
}
}
}
if(@instances == 1) {
sleep(5); # one instance, 5 sec. delay
} else {
sleep(1); # more instance, 1 sec. delay before next instance
}
}
$run = 0;
}
nano /usr/sbin/flvconv
#!/bin/bash
if [ -n "$5" ] ; then
ffmpeg -v 10 -y -i "$1" -acodec mp3 -ab 56k -ac 2 -ar 11025 -f flv -deinterlace -nr 500 -s $3 -aspect $4 -r 20 -b 400k -me_range 25 -i_qfactor 0.71 -g 500 "$2.tmp" 2>&1
ffmpeg -y -i "$2.tmp" -acodec copy -f flv -vhook '/usr/lib/vhook/watermark.so -m 0 -t 000000 -f /data/U2D/watermark.png' "$2" 2>&1
rm -f "$2.tmp"
else
ffmpeg -v 10 -y -i "$1" -acodec mp3 -ab 56k -ac 2 -ar 11025 -f flv -deinterlace -nr 500 -s $3 -aspect $4 -r 20 -b 400k -me_range 25 -i_qfactor 0.71 -g 500 "$2" 2>&1
fi
nano /etc/init.d/flvconv
#!/bin/sh
#
# flvconv: FLV convert
#
# chkconfig: 345 60 89
# description: FLV Convert
# processname: flvconv.pl
# pidfile: /var/run/flvconv.pid
# Source function library.
. /etc/rc.d/init.d/functions
FLVCONV_DIR=/usr/sbin
test -x $FLVCONV_DIR/flvconv.pl || exit 5
start()
{
echo -n $"Starting FLV Service: "
pid_length=`pidof -x flvconv.pl|awk '{print length($0)}'`
if [ "$pid_length" != "0" -a "$pid_length" != "" ]; then
RETVAL=1
else
daemon "$FLVCONV_DIR/flvconv.pl >/tmp/flvconv.log &"
RETVAL=$?
sleep 1
fi
[ ${RETVAL} -eq 0 ] && success || failure
echo
}
stop()
{
echo -n $"Shutting down FLV Service:"
killall -q flvconv.pl
[ $? -eq 0 ] && success || failure
sleep 1
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
- Add service
chmod 755 /etc/init.d/flvconv
chmod 755 /usr/sbin/flvconv.pl
chmod 755 /usr/sbin/flvconv
chkconfig -add flvconv
chkconfig -level 345 flvconv on
service flvconv start
Check correct conversion of previously uploaded file.
Conversion service change post status from 0 to 1 after successful conversion and to -1 on error.
Change CS pages to correct display post(s) with PostStatus.
Add pages to CS with live video stream (use link to Red5 server).
0 comment(s) so far