The ELC Community Blog
A knowledge exchange on Ruby on Rails and Agile Development
Tutorial - Red5, AS3, FC4, and Shared Fridge Magnets!
by Cary Dunn on January 25, 2008
Jargon...zZzZz
Red5 is an Open Source Flash Server written in Java that supports: Streaming Audio/Video (FLV and MP3), Recording Client Streams (FLV only), Shared Objects, Live Stream Publishing, Remoting”
Red5 is essentially an open source alternative to Adobe’s Flash Media Server. Both technologies leverage Adobe’s RTMP (Real Time Message Protocol) to stream small binary fragments in real time. The packets are multiplexed and therefore only one persistent connection is needed for each user. Objects are serialized via AMF (Action Message Format) which is what we will be using in this tutorial to create SharedObjects, which as the name suggests, are objects (in this case refrigerator magnets!) that are shared amongst all viewers of the application.
Red5 Boostrap
Download Red5
Once installed, navigate the Red5 root directory to get started.
Red5 Structure Rundown
Just the important stuff...
In the root Red5 directory you’ll find red5.jar which holds a pre-compiled jar holding the red5 java classes. You’ll use this later to compile your main application class.
The directory webapps is where you will be creating new Red5 applications. All new applications have a consistent structure which is laid out as a template for you in doc/templates
Red5 New Application Structure Rundown
Creating a new Red5 application is simple. We just create a new folder in webapps/
We will create an app called elcMagnets so we create a directory for it and now have webapps/elcMagnets. Red5 expects us to also have a directory inside our new application named WEB-INF/ so we create that as well, and now have webapps/elcMagnets/WEB-INF.
There are 4 default configuration files in doc/templates/myapp/WEB-INF that we will modify and use in our app, so we can copy those over to our elcMagnets directory. (log4j.properties, red5-web.properties, red5-web.xml, web.xml)
You can read up about all the properties and handlers specified in these files here.
For now, we only want to customize these files for our current app. We need to change the webapp.contextPath specified in red5-web.properties to reflect our newly created app. Take note of the virtualHosts parameter and remember to deal with it on deployment to a remote host.
webapp.contextPath=/elcMagnets webapp.virtualHosts=localhost, 127.0.0.1
The only other configuration file we will modify for now is red5-web.xml. For this we need to specify the handler that is invoked when users connect to the app. You can read up on handlers here.
For the purposes of this demo app we will only be creating a web.handler. We will end up writing Application.java as the web.handler inside the a package called package org.red5.server.webapp.elcMagnets so we will set our web.handler to org.red5.server.webapp.elcMagnets.Application.
<bean id=”web.handler” class=”org.red5.server.webapp.elcMagnets.Application” singleton=”true” />
Lastly we will comment out the sample service bean since we will not be using that in this demo.
<!-- <bean id=”myhandler.service” class=”the.path.to.my.ServiceHandler” singleton=”true” /> -->
Application.java
To keep things organized, we will create the directories lib/, classes/, src/ inside webapps/. Next we will create Application.java inside of src/.
As you recall, Application.java will serve as our web.handler, and therefore needs to extend ApplicationAdapter. (For more info on handlers, see the ‘HOWTO-NewApplications.txt’) In short, it allows you to stack functionality on top of existing events (connect, disconnect, join, leave, start, stop) or create your own.
Our example handler will be trivial, but illustrate calls to the Red5 server.
package org.red5.server.webapp.elcMagnets; import org.red5.server.adapter.ApplicationAdapter; public class Application extends ApplicationAdapter { public String high5Red5(int how_many) { String highFives = “”; if(how_many==0){ return “I dont like you anyways, bro.”; } for(int i=0;i<how_many;i++){ highFives += “*Smack*\n”; } return highFives; } }
Later, we can directly call this handler in ActionScript...
nc.call("high5Red5",nr,5); // Or more generally... netconnection.call("function",responder,arguments.....)
Compiling Application.java
What we want to end up with is a nicely packaged up elcMagnets.jar located in lib/
So from src/ we compile Application.java to the classes/ directory.
javac -classpath ../../../../red5.jar -d ../classes Application.java
Now lets create our jar file. First we need our MANIFEST.MF. If you aren’t familiar with it...
MANIFEST.MF
Manifest-Version: 1.0 Ant-Version: Apache Ant 1.7 Created-By: 1.5.0_06-b05 (Sun Microsystems Inc.) Class-Path: ../../../../red5.jar
(you can try yum/port install ant, but seem to remember building it)
Compiling elcMagnets.jar
jar -cmf MANIFEST.MF ../lib/elcMagnets.jar ../classes/org/red5/server/webapp/elcMagnets/Application.class
OK! Done with Red5.
You should now be able to start up your Red5 server and have it load up our new elcMagnets application.
Flash App
Next we will create an AS3 flash app to interact with our Red5 application and utilize SharedObjects.
Fridge.as (Document Class)
(I'm just going to post code, comment if you need any explanation.)
// ======================================= // Cary Dunn <cdunn@elctech.com> // ELC Technologies http://www.elctech.com // package { import flash.events.*; import flash.display.MovieClip; import flash.text.TextField; import flash.errors.IOError; import flash.system.Security; import caurina.transitions.Tweener; import flash.net.*; import com.elctech.Magnet; public class Fridge extends MovieClip { NetConnection.defaultObjectEncoding = ObjectEncoding.AMF0 ; private var nc:NetConnection = null; private var alphabet:Array = new Array; private const LETTERS:Array = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",",","!"] public function Fridge():void { nc = new NetConnection(); nc.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler); var nr:Responder = new Responder(onHighFives,null);; nc.connect("rtmp://localhost/elcMagnets"); nc.call("high5Red5",nr,5); } private function onHighFives(resp:String):void { trace(resp); } private function netStatusHandler(event:NetStatusEvent):void { trace(event.info.code); if(event.info.code == "NetConnection.Connect.Success") { createAlphabet(); } } private function createAlphabet():void { for(var i:uint = 0; i < LETTERS.length; i++) { var new_magnet:Magnet = new com.elctech.Magnet(LETTERS[i],nc,i); addChild(new_magnet); alphabet.push(new_magnet); } } } }
com.elctech.Magnet.as
// ======================================= // Cary Dunn <cdunn@elctech.com> // ELC Technologies http://www.elctech.com // package com.elctech { import flash.display.MovieClip; import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.geom.Rectangle; import flash.events.*; import flash.display.Stage; import flash.text.TextField; import flash.net.*; import flash.utils.Timer; import caurina.transitions.Tweener; public class Magnet extends MovieClip { private var _id:uint = 0; private var _so = null; private var _nc:NetConnection = null; private var _l:String = null; static internal var dragging:Boolean = false; static const MAGNET_COLORS:Array = [0xFF3333, 0x3399FF, 0x339966, 0x993399, 0xFF9933] static internal const ELASTICITY:Number = .5; static internal const FRICTION:Number = .5; private var ax:Number = 0; private var ay:Number = 0; private var vx:Number = 0; private var vy:Number = 0; public function Magnet(l:String, nc:NetConnection, i:uint):void { this.letter.text = l; this.letter.textColor = MAGNET_COLORS[Math.round(Math.random()*(MAGNET_COLORS.length-1))]; this.x = Math.round(Math.random()*390)+67; this.y = Math.round(Math.random()*260)+20; trace("New Magnet " + l); _l = l; _nc = nc; _id = i; _so = SharedObject.getRemote("letter_"+_id, _nc.uri, true); _so.addEventListener(SyncEvent.SYNC,syncEventHandler); _so.connect(_nc); this.buttonMode = true; this.addEventListener(MouseEvent.MOUSE_DOWN, function(evt:Event):void { dragging = true; stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging); evt.target.parent.addEventListener(Event.ENTER_FRAME, updatePosition); }); this.addEventListener(MouseEvent.MOUSE_UP, stopDragging); } private function stopDragging(evt:Event):void { this.removeEventListener(Event.ENTER_FRAME, updatePosition); stage.removeEventListener(MouseEvent.MOUSE_UP, stopDragging); dragging = false; } private function updatePosition(evt:Event):void { ax = (stage.mouseX-this.x+Math.random()*5)*ELASTICITY; ay = (stage.mouseY-this.y)*ELASTICITY; vx += ax; vy += ay; vx *= FRICTION; vy *= FRICTION; this.x += vx; this.y += vy; this.scaleX = (100-Math.abs(ax)*2)/100; this.scaleY = (100-Math.abs(ay)*2)/100; this.rotation = ax*3; _so.setProperty("currentPosition", {x: evt.target.x, y: evt.target.y}); } private function syncEventHandler(evt:SyncEvent):void { trace("Sync for letter "+_l); if(dragging){ return; } Tweener.addTween(this, {x:_so.data.currentPosition.x, y:_so.data.currentPosition.y, time:0.5, transition:"easeOutBack"}); } } }
Download Project Source
Installing Red5 on FC4
This section documents my trials and tribulations with installing Red5 on an Amazon EC2 instance running a standard FC4 image. This is a nasty (but working) implementation of this.
Some of the rpms are unnecessary, but some of the yum packages were failing on me. Anyways, this might help someone...
$ yum install gcc $ rpm -ivh ftp://rpmfind.net/linux/fedora/core/updates/4/i386/libstdc++-devel-4.0.2-8.fc4.i386.rpm $ rpm -ivh ftp://rpmfind.net/linux/fedora/core/updates/4/i386/gcc-c++-4.0.2-8.fc4.i386.rpm $ yum install fedora-rpmdevtools $ fedora-buildrpmtree $ cd /etc/yum.repos.d/ $ wget http://www.jpackage.org/jpackage.repo ---->>> download jdk 5.0 update .bin from <a href="http://java.sun.com/javase/downloads/index.jsp" target="_blank">sun</a>, scp it up to server (requires accepting of TOS) ---->>> cp jdk-....bin rpmbuild/SOURCES $ wget http://mirrors.dotsrc.org/jpackage/1.7/generic/non-free/SRPMS/java-1.5.0-sun-1.5.0.14-1jpp.nosrc.rpm $ rpmbuild --rebuild java-1.5.0-sun-1.5.0.14-1jpp.nosrc.rpm $ cd ~/rpmbuild/RPMS/i586/ $ (echo config gpgcheck 0; echo localinstall java-1.5.0-sun*.rpm; echo run) > yum-cmd $ yum shell yum-cmd $ rm yum-cmd $ cd ~/ wget http://archive.apache.org/dist/ant/binaries/apache-ant-1.7.0-bin.tar.gz $ cd /usr/local/ $ tar -zxf ~/apache-ant-1.7.0-bin.tar.gz $ mv apache-ant-1.7.0 ant $ vim /etc/profile PATH=$PATH:$HOME/bin:/usr/local/ant/bin export PATH $ source /etc/profile $ tar -zxvf red5-0.6.3.tar.gz $ cd red5-0.6.3 $ make $ make install $ /usr/lib/red5/red5.sh
At this point if you can hit http://{ip here}:5080 you are golden.
JRuby&Red5
Timeline
- USPS Package Tracking
- Setting up rmagick on Ubuntu
- Spec refactoring
- replaceaface.com beta ultra version 0.113 build 18.2
- Executing Shell Commands in Ruby
- Tutorial - Red5, AS3, FC4, and Shared Fridge Magnets!
- Setting up a Flash Media Server on EC2 (CentOS)
- AWS/S3 may cause rake task failed
- Refreshing Rails Generated Views
- Environment Scripts in merb
- Script Terminal with TermInit
Comments
Great post. Thank you for this!! exactly what I was looking for!
Thank you for this post!!! will try your post as soon as possible.
I’m setting up red5 video server but I can’t set the port or number of streams or bandwidth. it seems like this product is far from done? there seems to be no real management console. when I login it has a scopte but does not do anything. what I’m I doing wrong?
For now, we only want to customize these files for our current app. We need to change the webapp.contextPath specified in red5-web.properties to reflect our newly created app. Take note of the virtualHosts parameter and remember to deal with it on deployment to a remote host
- I dont have that in my red5-web file My web file reads:
webapp.context isn’t define in here
Awesome tutorial…very creative use of red5, it’s nice to see something other than chat tools…
I posted it on my blog http://www.red5world.com its a new community of red5 developers we are always looking for new stuff to post.
- Brendan
Hi. If you like big tits, big boobs – you must see it: http://bigtitsclip.net – big tits clips http://big-tit-videos.net – big tit videos
Thanks, Bye :)