开发者

Flex + buffer + live stream via RTMP = disaster

Can't get any love anywhere on this and it's pretty hard to believe. Live streaming and a buffer on a NetStream do not mix. Why? The docs don't say you can't do this.

The playback gets hosed. Buffer is supposed to fill to what you set it to before playing. Instead though, about half the time, the player starts playing right away and disregards the buffer time you've set. Then you get caught in short buffering and rebuffering cycles that degrades the playback experience.

Give it a shot yourself. Here is the simplest of live streaming video players. No frills. Just connect it to your live stream by changing the defaultURL string and stream name in the ns.play() statement.

Run it in Flex debug mode. It will check and print the ns.bufferLength property every second. The buffer is set to 20 secs currently. Last time I ran it, I never made it above 2 seconds in the buffer. Player started playing right away instead of buffering the full 20 secs first. Sometimes you get to the full 20 and sometimes not. Why? No idea.

Can you not buffer a live stream reliably or is there something wrong with the code?

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    initialize="init()">
    <mx:Script>
        <![CDATA[
            import flash.media.Video;
            import flash.net.NetConnection;
            import flash.net.NetStream;
            import mx.core.UIComponent;

            private var vid:Video;
            private var videoHolder:UIComponent;
            private var nc:NetConnection;
            private var defaultURL:String="rtmp://your_streaming_server_url_here";
            private var ns:NetStream;
            private var msg:Boolean;

            private var intervalMonitorBufferLengthEverySecond:uint;

            private function init():void
            {
                vid=new Video();
                vid.width=864;
                vid.height=576; 
                vid.smoothing = true;                            
                //Attach the video to the stage              
                videoHolder = new UIComponent();
                videoHolder.addChild(vid);
                addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
                this.addChild(videoHolder);
                connect();
            }

            public function onSecurityError(e:SecurityError):void
            {
                trace("Security error: ");
            }

            public function connect():void
            {
                nc = new NetConnection();
                nc.client = this;
                nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
                nc.connect(defaultURL);                 
            }

            public function netStatusHandler(e:NetStatusEvent):void
            {
                switch (e.info.code) {
                    case "NetConnection.Connect.Success":
                        trace("Connected successfully");
                        createNS();                 
                        break;
                    case "NetConnection.Connect.Closed":
                        trace("Connection closed");                 
                        connect();
                        break;  
                    case "NetConnection.Connect.Failed":
                        trace("Connection failed");                 
                        break;
                    case "NetConnection.Connect.Rejected":
                        trace("Connection rejected");                                   
                        break;  
                    case "NetConnection.Connect.AppShutdown":
                        trace("App shutdown");                                  
                        break;          
                    case "NetConnection.Connect.InvalidApp":
                        trace("Connection invalid app");                                    
                        break;                                                                                                      
                }           
            }

            public function createNS():void
            {
                trace("Creating NetStream");
                ns=new NetStream(nc);
                //nc.call("FCSubscribe", null, "live_production"); // Only use this if your CDN requires it
                ns.addEventListener(NetStatusEvent.NET_STATUS, netStreamStatusHandler);
                vid.attachNetStream(ns);

                //Handle onMetaData and onCuePoint event callbacks: solution at http://tinyurl.com/mkadas
                //See another solution at http://www.adobe.com/devnet/flash/quickstart/metadata_cue_points/
                var infoClient:Object = new Object();
                infoClient.onMetaData = function oMD():void {};
                infoClient.onCuePoint = function oCP():void {};         
                ns.client = infoClient; 
                ns.bufferTime = 20; 
                ns.play("your_stream_name");    
                ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
                function asyncErrorHandler(event:AsyncErrorEvent):void {
                    trace(event.text);
                }   
                intervalMonitorBufferLengthEverySecond = setInterval(monPlayback, 1000);
            }

            public function netStreamStatusHandler(e:NetStatusEvent):void
            {
                switch (e.info.code) {
                    case "NetStream.Buffer.Empty":
                        trace("Buffer empty: ");
                        break;
                    case "NetStream.Buffer.Full":
                        trace("Buffer full:");
                        break;
                    case "NetStream.Play.Start":
                        trace("Play start:");
                        break;                      
                }       
            }

            publ开发者_开发知识库ic function monPlayback():void {
                // Print current buffer length
                trace("Buffer length: " + ns.bufferLength);
            }

            public function onBWDone():void { 
                //Do nothing
            }           

            public function onFCSubscribe(info:Object):void {       
                // Do nothing. Prevents error if connecting to CDN.     
            }

            public function onFCUnsubscribe(info:Object):void {     
                // Do nothing. Prevents error if connecting to CDN.     
            }

        ]]>
    </mx:Script>    
</mx:Application>

My last run:

Connected successfully
Creating NetStream
Play start:
Buffer length: 0.001
Buffer full:  //Obviously the buffer is not full here.  Bogus.
Buffer length: 2.202
Buffer length: 2.369
Buffer length: 2.102
Buffer length: 2.402
Buffer length: 2.302
Buffer length: 2.369
Buffer length: 2.269
Buffer length: 2.269
Buffer length: 2.302
Buffer length: 2.369
Buffer length: 1.926
Buffer length: 2.336
Buffer length: 2.286
Buffer length: 2.336
Buffer length: 2.336
Buffer length: 2.403
Buffer length: 2.388
Buffer length: 2.402
Buffer length: 2.335
Buffer length: 2.369
Buffer length: 2.336
Buffer length: 2.339
Buffer length: 2.369
Buffer length: 2.402
Buffer length: 2.369
Buffer length: 2.396
Buffer length: 2.436
Buffer length: 2.336
Buffer length: 2.269


The AS3 reference explicitly states that you cannot do this:

Live content When streaming live content, set the bufferTime property to 0.

Given that, if you tell us what you're trying to achieve then perhaps we can suggest another solution.


More of a thought, but here goes: Flash Player's internal streaming clockwork might refuse to buffer any more of live streams than what it deems "necessary." The idea is that if you have a live stream, you have a live stream. In most situations, having delay due to a buffer (think one-on-one video chat) would be ridiculous and really frustrating.

These things may be actually controlled from the server, but I could be wrong on this. Hope you can find a good solution for the problem :-)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜