feedback
Nov 4 2007

Yet Another Coverflow using Papervision

by John Dyer

UPDATE: Now uses Papervision 2.0 Alpha (GreatWhite). 

There are a million Apple Coverflow knockoffs (blitz, doug mccune, antti kupila, weber design) and now there are a million and one. This one is made using Papervision3d and Tweener and includes keyboard and scrollwheel support. Here are two uses, one pulling from a friend's Flickr photo stream, and the other pulling from DTS's recent media items:

 



This uses the Phunky GreatWhite branch of Papervision (1.9 or so 2.0 Alpha). Here's the setup:

var coverFlowData:Array = [{title: "item title", clickUrl:"http://mysite.com/target", imageUrl:"http://mysite.com/image.jpg"}];
var coverFlow = new CoverFlow(stage, camera, scene, coverFlowData); 

And here's the project (for Flash CS3): coverflow.zip (16.21 kb)

Nov 1 2007

Flash Streaming with Akamai in AS3

by John Dyer

We use Akamai (formerly ninesystems) for all of our video streaming (media page, online education, grad stories, etc.) and we tend to use the FLVPlayback component for our various video players. When we hit an Akamai stream URL (http://dts.edgeboss.net/xxxxx.flv), it is an XML file with information on servers based on the user's location. This XML must be parsed in order to construct a stream URL to play. Ninesystems provided a sample player, but it used Flash 7 style coding which is very hard to manage. I've developed a little AS3 class that encapsulates all the functionality.

Here is the usage (assuming an FLVPlayback component called: flvPlayback);

using edu.dts.video.AkamaiPlayer;
var akamaiPlayer:AkamaiPlayer = new AkamaiPlayer(flvPlayback);
akamaiPlayer.playStream("http://edgeboss.net/xxxxx.flv");

That's it. The full source code is below:

package edu.dts.video
{
    
    import flash.display.MovieClip;

    import flash.events.EventDispatcher;
    import flash.events.Event;
    import flash.events.TimerEvent;

    
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    
    import flash.utils.Timer;
    import fl.video.FLVPlayback;
    import fl.video.VideoEvent;    
    
    public class AkamaiPlayer extends EventDispatcher
    {
        private var _player:FLVPlayback;
        
        private var _protocols_array:Array = [
            {protocol:"rtmp", port:1935}, 
            {protocol:"rtmp", port:80} 
        ];
        private var _connections_array:Array = new Array();

        private var _duration:Number = 0;    

        private var _connectionIndex:Number = 0;
        private var _connectTimeout = null;

        private var _akamaiUrl:String = "";
        private var _akamaiConn:String = "";
        private var _connTimeout = 10000;        
        
        private var _streamXml:XML;

        private var _timer:Timer;
        
        public var connectionFailure:Function;
            
        public function AkamaiPlayer(player:FLVPlayback)
        {
            _player = player;
            _player.addEventListener(VideoEvent.READY, playerReady);
        }
        
        public function playStatic(flvUrl:String) {
            trace("AkaimiPlayer playing " +  flvUrl);
            _player.play(flvUrl);
        }
        
        public function playStream(akamaiUrl:String) {
            trace("AkaimiPlayer playing " +  akamaiUrl);
            
            // check for XML version (xmlvers)
            
            if (akamaiUrl.indexOf("?") == -1) {
                akamaiUrl += "&xmlvers=2";
            } 
            else
            {
                if (akamaiUrl.indexOf("xmlvers=2") == -1) {
                    akamaiUrl += "&xmlvers=2";
                }                
            }
            
            
            _akamaiUrl = akamaiUrl;
            _akamaiConn = "";
        
            if (_player.playing)
                _player.stop();
        
            var xmlLoader:URLLoader = new URLLoader();
            xmlLoader.addEventListener(Event.COMPLETE, loadComplete);
            xmlLoader.load(new URLRequest(_akamaiUrl));
        }
        
        private function loadComplete(event:Event):void {
            trace("FLV XML is Loaded");
            
            // get XML data
            _streamXml = new XML(event.currentTarget.data);
            
            // clear out existing data
            _connectionIndex = 0;
            _connections_array = new Array();
            
            // find //             
            var entries:XMLList = _streamXml.stream.entry;
        
        
            var item_xml:XML;
            
            // loop through the array of matching XMLNodes and remap the child nodes into an tempObject
            for each (item_xml in entries) {
                var tempObj:Object = new Object();
                var node:XML;
                for each (node in item_xml.children()) {
                    tempObj[node.localName()] = node.text();
                }
                
                // create connection string array entries
                for ( var i = 0; i < _protocols_array.length; i++ ) {
                    var connString:String = 
                        _protocols_array[i].protocol + "://" + 
                                tempObj["serverName"] + ":" + _protocols_array[i].port + "/" + 
                                tempObj["appName"]+  "/" + tempObj["streamName"];
                    _connections_array.push( connString );
                    
                    trace("added: " + connString);
                }                                                            
            }
            
            _timer = new Timer(_connTimeout);
            _timer.addEventListener("timer", timerHandler);
            _timer.start();
        
            tryNextConnection();

        }
        
        private function tryNextConnection():void {

            var connString:String = _connections_array[_connectionIndex];
            
            if (_connectionIndex == _connections_array.length ) {
                
                // make sure to reset to last connection
                connString = _connections_array[_connectionIndex-1];
                 _timer.stop();
                 
                if (connectionFailure != null)
                    connectionFailure();
                 
                trace("tried all protocols with no luck");
                return;
            }
                    
            // just in case it happens to start playing from another source
            if (_player.playing)
                return;
                    
            trace("connecting to " + (_connectionIndex+1).toString() + " of " + (_connections_array.length).toString() + ": " + connString + " ; count: " + _timer.currentCount.toString());
            _player.autoPlay = true;
            _player.play(connString);
        
            
            // iterate the connection so that if it fails, we go to the next one
            _connectionIndex++;            
        }
                
        private function timerHandler(event:TimerEvent):void {
            tryNextConnection();                    
        }
        
        private function stopConnectionAttempts():void {
            _timer.stop();
        }        
        
        private function playerReady(event:VideoEvent):void {
            // successful play
            stopConnectionAttempts();
        }        
    }    
}
Web Statistics