apache-flex - Flex + 缓冲区 + 通过 RTMP 进行直播 = 灾难

标签 apache-flex flash actionscript-3 video-streaming flash-media-server

在这方面找不到任何爱,这很难相信。实时流媒体和 NetStream 上的缓冲区不能混合。为什么?文档并没有说你不能这样做。

播放被中断。缓冲区应该填充到您在播放之前设置的值。但相反,大约一半的情况下,玩家会立即开始玩游戏,而忽略您设置的缓冲时间。然后您就会陷入短暂的缓冲和重新缓冲周期,从而降低播放体验。

你自己试试吧。这是最简单的直播视频播放器。没有多余的装饰。只需更改 ns.play() 语句中的 defaultURL 字符串和流名称即可将其连接到您的直播流。

在 Flex Debug模式下运行它。它会每秒检查并打印 ns.bufferLength 属性。当前缓冲区设置为 20 秒。上次我运行它时,缓冲区中的时间从未超过 2 秒。玩家立即开始玩游戏,而不是先缓冲整整 20 秒。有时你会达到满 20 个,有时则不会。为什么?不知道。

您无法可靠地缓冲直播流还是代码有问题?

<?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;                      
                }       
            }

            public 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>

我上次运行:

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

最佳答案

AS3 reference明确指出您不能这样做:

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

鉴于此,如果您告诉我们您想要实现的目标,那么也许我们可以建议另一个解决方案。

关于apache-flex - Flex + 缓冲区 + 通过 RTMP 进行直播 = 灾难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2149446/

相关文章:

android - Android 版 Adob​​e AIR (Flex 4.6.0) 中前置摄像头、视频和视频显示的显示错误

actionscript-3 - AS3 : How to know if dataprovider or its content(s) is changed

apache-flex - DataProvider 更新时 DataGrid 刷新

actionscript-3 - ActionScript 库项目与 Flex 库项目

ios - 在设备上调试 iOS/AIR 内容

actionscript-3 - "Definition mx.utils:Base64Encoder could not be found"在 Flex Builder 3 中

apache-flex - 如何仅在 flex 中设置一个组件的工具提示延迟?

php - Javascript - 在包含的页面上查找 swfobject 并调用 javascript 函数

apache-flex - 如何检查Flash Player缓存的内容?

javascript - 如何从 Flash 导出的 HTML 和 JS 中删除背景图像或颜色