Skip to main content
Known Participant
September 10, 2011
Question

Switching not working in Playlist

  • September 10, 2011
  • 1 reply
  • 2212 views

So recently I have found issues with switching when playing playlists in a player we are developing. So to trouble shoot I built a simple application with buttons to manually switch. The first video in the stream switches just fine. When the player gets to to the second video in the the stream, switch does does not work either with or with out oldStreamName defined in the NetStreamPlayOptions. What happens is the the stream ends prematurely, a few seconds to a few minutes after the the button to switch is clicked. If I just let it pIay with out switching it plays out the whole stream as intended. I can't find any reason for this not to work, so I am wondering if there is an issue with the server. Any idea if this could be a server issue or am I missing something here?

Thanks,
Adam

Example is here.

Press button 1 to switch using OldStreamName, button 2 to switch not using OldStreamName, and button 3 to seek to the beggining of the second video in the playlist. There are messages being traced to the the stage so you can see whats happenning.

my AS:

package
{
    import Button;
    import Playtime; //for  netstreamtime to display
    import Tracer; //for tracing to sprite on stage
   
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.AsyncErrorEvent;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.NetStatusEvent;
    import flash.media.Video;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.net.NetStreamInfo;
    import flash.net.NetStreamPlayOptions;
    import flash.net.NetStreamPlayTransitions;
   
    [SWF(width='1280', height='720', backgroundColor='#000000', frameRate='30')]
   
    public class switchTester extends MovieClip
    {
        private var nc:NetConnection = new NetConnection();
        public var stream:NetStream;
        private var video:Video;
        public var tracer:Tracer = new Tracer();
        public var vid:Array = [];
        public var currentVid:Object = new Object;
        public var nextVid:Object = new Object;
        private var pt:Playtime = new Playtime();
       
        public function switchTester()
        {
            init();
        }
       
        private function init():void
        {
            this.addChild(tracer);
            nc.connect("rtmp://yj72wmv1w.rtmphost.com/test");
            nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
            nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncError);
        }

        private function netStatusHandler(e:NetStatusEvent):void
         {
             tracer.add("NetStatusEvent: " + e.info.code);
            
             if(e.info.code == "NetConnection.Connect.Success")
             {
                 stream = new NetStream(nc);
                 stream.bufferTime = 10;
                 stream.backBufferTime = 20;
                 stream.inBufferSeek = true;
                 var customClient:Object = new Object() ;
                 customClient['onPlayStatus'] = onPlayStatus;
                 stream.client = customClient;
                
                 video = new Video(1280,720);
                 video.attachNetStream(stream);
                 video.smoothing = true;
                 this.addChildAt(video,0);
                
                 var btnHolder:Sprite = new Sprite();
                
                 for (var i:int = 0; 3 > i; i++)
                 {
                     var btn:Button = new Button((i+1).toString());
                     btn.x = btn.width * 1.5 * i;
                     btn.addEventListener(MouseEvent.MOUSE_UP, onUp);
                     btnHolder.addChild(btn);
                 }
                
                 btnHolder.x = this.width - btnHolder.width - 10;
                 btnHolder.y = this.height - btnHolder.height - 10;
                 this.addChild(btnHolder);
                
                 addPlaylist();
             }
         }

        private function addPlaylist():void
        {

            for (var i:int = 0; 2 > i; i++)
            {
                var l:Object = new Object();
                var m:Object = new Object();
                var h:Object = new Object();


                l.quality = "low";
                m.quality = "med";
                h.quality = "high";
               
                var seg:Array = [l, m, h];
                vid.push(seg);
            }
           
            vid[0][0].path = "mp4:res_11-15lb_baby_01_500kbps.mp4";
            vid[0][1].path = "mp4:res_11-15lb_baby_01_1000kbps.mp4";
            vid[0][2].path = "mp4:res_11-15lb_baby_01_1800kbps.mp4";
           
            vid[1][0].path = "mp4:yog_e_8-12_baby_02_VO_v4_500kbps.mp4";
            vid[1][1].path = "mp4:yog_e_8-12_baby_02_VO_v4_800kbps.mp4";
            vid[1][2].path    = "mp4:yog_e_8-12_baby_02_VO_v4_1500kbps.mp4";
           
            stream.play(vid[0][0].path, 0, -1, false);
            stream.play(vid[1][0].path, 0, -1, false);
           
            currentVid = vid[0][0];
            tracer.add("first video is " + currentVid.path);
            tracer.add("second video is " + vid[1][0].path);
           
            pt.x = 1200;
            addChild(pt);
           
        }
        
         private function onPlayStatus(info:Object):void
         {
             tracer.add("onPlayStatus: " + info.code);
            
             if(info.code == "NetStream.Play.TransitionComplete") currentVid = nextVid;
         }
        
         private function asyncError(e:AsyncErrorEvent):void
         {
             tracer.add("asyncError: " + e.error);
         }
       
        private function onUp(e:MouseEvent):void
        {
            switch (e.target.id)
            {
                case "1":
                    switchWithOldStream();
                    break;
                case "2":
                    switchNoOldStream();
                    break;
                case "3":
                    stream.seek(592.828);
                    currentVid = vid[1][0];
                    break;
            }
        }
       
        private function switchNoOldStream():void
        {
            var nsi:String = String(stream.info);
            var arr:Array = nsi.split(" ");
            arr = arr[23].split("resourceName=")
            tracer.add("resourceName= " + arr[1]);
           
            setNextVid();
            var param:NetStreamPlayOptions = new NetStreamPlayOptions();
            param.streamName = nextVid.path;
            param.transition = NetStreamPlayTransitions.SWITCH;
            stream.play2(param);
            tracer.add("switchNoOldStream to: " + nextVid.path);
        }
       
        private function switchWithOldStream():void
        {
            var nsi:String = String(stream.info);
            var arr:Array = nsi.split(" ");
            arr = arr[23].split("resourceName=")
            tracer.add("resourceName= " + arr[1]);
           
            setNextVid();
            var param:NetStreamPlayOptions = new NetStreamPlayOptions();
            tracer.add("oldStreamName: " + currentVid.path);
            param.oldStreamName = "mp4:" + arr[1];
            param.streamName = nextVid.path;
            param.transition = NetStreamPlayTransitions.SWITCH;
            stream.play2(param);
            tracer.add("switchWithOldStream to: " + nextVid.path);
        }
       
        private function setNextVid():void   
        {
            for (var i:int = 0; vid.length > i; i++)
            {
                var m:int = i;
               
                for (var n:int = 0; vid.length > n; n++)
                {
                    var arr:Array = vid
                   
                    if(currentVid == arr)
                    {
                        var p:int;
                        if(n == arr.length-1) p = 0 else p = n+1;
                        nextVid = arr

;   
                    }
                }
            }
        }

    }
}

Message was edited by: Adam Ashby

    This topic has been closed for replies.

    1 reply

    calmchessplayer
    Inspiring
    September 10, 2011

    when i swtich videos I close the netstream then reopen it with a new name I usually use a timestamp so that the new name is always unique. keep in mind you will see multiple streams in the FMS admin console but if you have properly closed and terminated a stream then those old unused streams should be GC at some point. I have only experimented this with successful results however I have never used it in a production environment so I don't know how the server really reacts such as memory consumption.

    Known Participant
    September 10, 2011

    I'm talking about using NetStreamPlayTransitions.SWITCH to play different bitrate versions of the same video used in dynamic streaming. I built this simple app to check if the switch is working by using a button click to initiate the switch. I have no problem with the stream playing the videos in the playlist one after another. Its when it playing any video after the first in the playlist and I intiate a swicth to a different bitrate when I have problem. The transition doesn't happen and the stream ends prematurely. Even when all the NetStreamPlayOptions.oldStreamName is correct. I dont think using a new stream in an option here we need one seemless and continuous stream.

    calmchessplayer
    Inspiring
    September 10, 2011

    I didn't see a server side script thats why I was confused. I do believe you have to switch bitrate on the server side as its the only thing that can detect the clients bandwidth. I'm only going on a bit of information that I know about this so If I'm wrong or you are actually clicking a  button  on the client to play a low medium high quality bitrate then maybe you aren't switching to the right file or you don't know you need to encode the videos at diffrent bitrates. Please tell me if you think I've wrapped my head around your problem. If i haven't then I won't waste anymore of your time with 1/2 the information and exsperience needed to solve this problem.