如何在ActionScript中同步多个视频流?

时间:2010-10-29 12:53:08

标签: flash actionscript-3 synchronization video-streaming

我正在尝试同时播放多个视频流。但是,我无法以同样的速度同步这些视频。

----详情--------

我有三个45秒的FLV格式视频,我使用flash.net.NetStream播放这些视频。我同时调用这些netstream的netstream.play()(通过使用for循环)。但是,即使所有视频文件都在我的本地计算机上,这些视频也是不同步的。

例如,当挂钟为第10秒时,第一个视频为第7秒,第二个视频为第10秒,最后一个视频为第5秒。

我认为流式传输时可能会受到不同抖动延迟的影响。但是,我仍然找不到解决这个问题的方法。

2 个答案:

答案 0 :(得分:1)

这是我的研究结果。 代码:

package
{
    public class Main extends Sprite 
    {
        private var zeroBG:Sprite;
        private var oneBG:Sprite;
        private var twoBG:Sprite;
        private var arr:Array = new Array();
        private var oldSchoolMC:MovieClip;
        public function Main():void 
        {
            oldSchoolMC = new MovieClip();
            addChild(oldSchoolMC);
            oldSchoolMC.x = 400;
            oldSchoolMC.y = 350;
            oldSchoolMC.buttonMode = true;
            addFrames();
            //the string below is just a way to get about +15% CPU load (on Intel Dual-Core T4400), comment it out if you don't need it
            oldSchoolMC.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            oldSchoolMC.addEventListener(MouseEvent.CLICK, onClick);
            zeroBG = new Sprite();
            oneBG = new Sprite();
            twoBG = new Sprite();
            oneBG.x = 350;
            twoBG.x = 700;
            addChild(zeroBG);
            addChild(oneBG);
            addChild(twoBG);

            genVideoSampleOnDefaultClasses(zeroBG);
            genVideoSampleOnDefaultClasses(oneBG);
            genVideoSampleOnDefaultClasses(twoBG);
        }
        private function onClick(e:MouseEvent):void {
            var secs:int = 0;
            if ((arr[0] as NetStream).time != 0 && (arr[0] as NetStream).time != (arr[arr.length - 1] as NetStream).time) {
                secs = Math.ceil((arr[0] as NetStream).time);
            }
            for (var i:int = 0; i < arr.length; i++) {
                var ns:NetStream = arr[i] as NetStream;
                if(ns.time == 0){
                    ns.play('res/ghost_in_the_shell.flv');
                    continue;
                }else {
                    trace('i = ' + i + ' time = ' + ns.time);
                    if (secs != 0) {
                        ns.seek(secs);
                    }
                }               
            }
        }

        private function addFrames():void {
            for (var i:int = 0 ; i < 0xffffff ; i+=100000) {
                oldSchoolMC.addChild(genColRect(i));
                if (oldSchoolMC.numChildren > 0) {
                    oldSchoolMC.getChildAt(oldSchoolMC.numChildren - 1).scaleX = (250 - oldSchoolMC.numChildren) / 250;
                    oldSchoolMC.getChildAt(oldSchoolMC.numChildren - 1).scaleY = (250 - oldSchoolMC.numChildren) / 250;
                }
            }

        }

        private function onEnterFrame(e:Event):void {
            for (var i:int = 0 ; i < oldSchoolMC.numChildren ; i++) {
                oldSchoolMC.getChildAt(i).rotation += (oldSchoolMC.numChildren - i);
            }        
        }

        private function genColRect(col:int = 0xffffff):Shape {
            var spr:Shape = new Shape();
            spr.graphics.beginFill(col);
            spr.graphics.drawRect( -50, -50, 100, 100);
            spr.graphics.endFill();
            return spr;
        }        

        private function genVideoSampleOnDefaultClasses(spr:Sprite):void {
            var vid:Video = new Video();
            var nc:NetConnection = new NetConnection();
            nc.connect(null);
            var ns:NetStream = new NetStream(nc);
            ns.client = new Object();
            ns.client.onMetaData = function(info:Object):void { };
            vid.attachNetStream(ns);
            spr.addChild(vid);
            arr.push(ns);
        }

    }
}  

我可以提到两个同步问题:

    开始时
  • 无论我是使用for循环还是硬编码3行((arr[0] as NetStream).play('res/ghost_in_the_shell.flv'); - 这样)第二次点击时的输出(播放后) )是这样的(第二次和第三次点击的痕迹):
    点击N 2
    i = 0时间= 5.251
    i = 1次= 5.251
    i = 2次= 5.538
    点击N 3
    i = 0时间= 37.721
    i = 1次= 37.721
    i = 2次= 37.721
    第一个和第二个流都没问题,但第三个流总是晚287毫秒(这取决于onClick功能代码,以前版本总是给出183ms延迟)
  • 经过600 - 800秒:流的时间有一个不确定的增量(通常约为100毫秒),下次点击次数为2的痕迹:
    点击N 4
    i = 0时间= 756.44
    i = 1次= 756.558
    i = 2次= 756.558
    点击N 5
    i = 0时间= 4466.965
    i = 1次= 4466.965
    i = 2次= 4466.965


和截图(第一部分是在第一次点击后(任何同步之前)拍摄的,第二部分是在点击N 4 之后拍摄的):

alt text

flv大小约为207mb btw

UPD:我为视频添加了5个精灵,为统计信息添加了一个文本字段,还有一个计时器(间隔为1000毫秒)来调用onClick函数,该函数修改如下:

    private function onClick(e:Event):void {
        tf.text = '';
        var secs:int = 0;
        if ((arr[0] as NetStream).time != 0 && (arr[0] as NetStream).time != (arr[arr.length - 1] as NetStream).time) {
            secs = Math.ceil((arr[0] as NetStream).time);
            trace(counter++ + ' : time = ' + secs);
        }
        for (var i:int = 0; i < arr.length; i++) {
            var ns:NetStream = arr[i] as NetStream;
            if(ns.time == 0){
                ns.play('res/ghost_in_the_shell.flv');
                if (i == arr.length - 1) {
                    streamTimer.start();
                }
                continue;
            }else {
                tf.appendText('# ' + i + ' [' + ns.time + ']\n');
                if (secs != 0) {
                    ns.seek(secs);
                }
            }               
        }
    }

它每100秒有大约20个同步问题(跟踪,而不是我能看到的问题),因为它使用了大量的系统资源,但即使有关于搜索的痕迹,视频对象也能够流畅地播放。
这是图片: alt text

答案 1 :(得分:1)

Oups ....没有看到它是2岁......

我认为您应该尝试在每个播放器实例中预加载文件,等待加载完成然后,您可以启动视频。依赖于NetStream事件并不是那么好(几次相同的通知,或者根据播放的文件缺少通知......)但它应该可以工作。

function Preload() : void {
    aNet              = new NetConnection();
    aNet.connect(null);
    stream                = new NetStream( aNet );
    stream.client     = this;
    stream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus, false, 0, true );
    stream.addEventListener(IOErrorEvent.IO_ERROR, errSnd, false, 0, true );
    stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError, false, 0, true );
    stream.play("your file");
}


// Here you wait for the load notification, and then pause the video.
private function onNetStatus( e : NetStatusEvent ) : void {
     switch( e.info.code ) {
      case "NetStream.Buffer.Full" :    
               if (bNotified) return;
               stream.pause();
               // Store that the file is loaded
               bNotified = true;
               // Dispatch an event
               dispatchEvent( new Event("VIDEO LOADED") ); 
       break;               
    }
}

private function errSnd(e: IOErrorEvent ) : void {
// error handling   

}

private function onAsyncError(e: AsyncErrorEvent ) : void {
    // Error handling
}
相关问题