Дублирование видеопотока Actionscript 3

#actionscript-3 #video

#actionscript-3 #Видео

Вопрос:

Доброе утро,

я работаю над классом видео, используя CRTMP-сервер для потоковой передачи. Это работает нормально, но для моего решения мне нужно дублировать видеопоток (для некоторых эффектов).

Я поискал в Google дублирующиеся видеоролики и попытался дублировать видео следующим образом.

 import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.media.*;
import flash.system.*;
import flash.utils.ByteArray;

public class Main extends MovieClip
{
    public var netStreamObj:NetStream;
    public var nc:NetConnection;
    public var vid:Video;
    public var vid2:Video;
    public var streamID:String;
    public var videoURL:String;
    public var metaListener:Object;

    public function Main()
    {
        init_RTMP();
    }

    private function init_RTMP():void
    {

        streamID = "szene3.f4v";
        videoURL = "rtmp://213.136.73.230/maya";

        vid = new Video(); //typo! was "vid = new video();"
        vid2 = new Video();
        nc = new NetConnection();
        nc.addEventListener(NetStatusEvent.NET_STATUS, onConnectionStatus);
        nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
        nc.client = {onBWDone: function():void
        {
        }};
        nc.connect(videoURL);
    }

    private function onConnectionStatus(e:NetStatusEvent):void
    {
        if (e.info.code == "NetConnection.Connect.Success")
        {
            trace("Creating NetStream");
            netStreamObj = new NetStream(nc);

            metaListener = new Object();
            metaListener.onMetaData = received_Meta;
            netStreamObj.client = metaListener;

            netStreamObj.play(streamID);
            vid.attachNetStream(netStreamObj);
            //vid2.attachNetStream(netStreamObj); // wont work
            addChild(vid);
            // addChild(vid2); // wont work either

                //intervalID = setInterval(playback, 1000);
        }
    }

    private function asyncErrorHandler(event:AsyncErrorEvent):void
    {
        trace("asyncErrorHandler.."   "r");
    }





    private function received_Meta(data:Object):void
    {
        var _stageW:int = stage.stageWidth;
        var _stageH:int = stage.stageHeight;

        var _videoW:int;
        var _videoH:int;
        var _aspectH:int;

        var Aspect_num:Number; //should be an "int" but that gives blank picture with sound
        Aspect_num = data.width / data.height;

        //Aspect ratio calculated here..
        _videoW = _stageW;
        _videoH = _videoW / Aspect_num;
        _aspectH = (_stageH - _videoH) / 2;

        vid.x = 0;
        vid.y = _aspectH;
        vid.width = _videoW;
        vid.height = _videoH;

        vid2.x = 0;
        vid2.y = _aspectH  ;
    }
} 
  

Должна быть возможность дублирования видеопотока. 2 Экземпляра одного и того же видеопотока. Что я делаю не так?

Спасибо за помощь.

Комментарии:

1. самый простой из возможных способов — создать два экземпляра класса player

2. это означает, что я должен удвоить netstream. Это не то, чего я хочу. Я пытался это сделать, но видео не были синхронными. Есть еще идеи?

3. я попытался дублировать видео на Bitmap.clone. Но я получил нарушение песочницы. Есть идеи? Я пытаюсь исследовать самостоятельно… Но помощь действительно ценится 🙂

4. Вы можете синхронизировать два потока, остановив их на 0, а затем запустив. Вы также можете использовать BitmapData.draw()

5. спасибо www0z0k … они не запускаются точно в одно и то же время, но при воспроизведении с помощью seek выполняется синхронизация. Спасибо за этот совет. Спасибо большое

Ответ №1:

  • «Это означает, что я должен удвоить netstream. Это не то, чего я хочу «.
  • «Я пытался дублировать видео на Bitmap.clone . Но я получил нарушение песочницы «.

Вы можете попробовать обходной путь, предложенный здесь: Netstream Play(null) Bitmapdata Workaround

Я покажу краткую демонстрацию того, как это можно применить к вашему коду. В этом демонстрационном коде предполагается, что ваш холст имеет ширину = 550 и высоту = 400. При увеличении масштаба сохраняйте это соотношение.

 package 
{
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
    import flash.media.*;
    import flash.system.*;
    import flash.utils.ByteArray;

    import flash.geom.*;
    import flash.filters.ColorMatrixFilter;

    public class Main extends MovieClip
    {
        public var netStreamObj:NetStream;
        public var nc:NetConnection;
        public var vid:Video;

        public var streamID:String;
        public var videoURL:String;
        public var metaListener:Object;

        public var vid1_sprite : Sprite = new Sprite();
        public var vid2_sprite : Sprite = new Sprite();

        public var vid2_BMP : Bitmap;
        public var vid2_BMD : BitmapData;

        public var colMtx:Array = new Array(); //for ColorMatrix effects
        public var CMfilter:ColorMatrixFilter;


        public function Main()
        {
            init_RTMP();
        }

        private function init_RTMP():void
        {

            streamID = "szene3.f4v";
            videoURL = "rtmp://213.136.73.230/maya";

            vid = new Video();
            nc = new NetConnection();
            nc.addEventListener(NetStatusEvent.NET_STATUS, onConnectionStatus);
            nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);

            nc.client = { onBWDone: function():void { } };

            //nc.connect(null); //for file playback
            nc.connect(videoURL); //for RTMP streams

        }

        private function onConnectionStatus(e:NetStatusEvent):void
        {
            if (e.info.code == "NetConnection.Connect.Success")
            {
                trace("Creating NetStream");
                netStreamObj = new NetStream(nc);

                metaListener = new Object();
                metaListener.onMetaData = received_Meta;
                netStreamObj.client = metaListener;

                //netStreamObj.play("vid.flv"); //if File
                netStreamObj.play(streamID); //if RTMP

                vid.attachNetStream(netStreamObj);

           }
        }

        private function asyncErrorHandler(event:AsyncErrorEvent):void
        {
            trace("asyncErrorHandler.."   "r");
        }

        private function received_Meta(data:Object):void
        {
            trace("Getting metadata");

            var _stageW:int = stage.stageWidth;
            var _stageH:int = stage.stageHeight;

            var _videoW:int = data.width;
            var _videoH:int = data.height;
            var _aspectH:int = 0;

            var Aspect_num:Number;
            Aspect_num = data.width / data.height;

            //Aspect ratio calculated here..
            _videoW = _stageW;
            _videoH = _videoW / Aspect_num;
            _aspectH = (_stageH - _videoH) / 2;

            trace("_videoW : "   _videoW);
            trace("_videoW : "   _videoH);
            trace("_aspectH : "   _aspectH);

            vid.x = 0;
            vid.y = 0;
            vid.width = _videoW;
            vid.height = _videoH;

            setup_Copy(); //# Do this after video resize 
        }

        public function setup_Copy () : void
        {
            vid2_BMD = new BitmapData(vid.width, vid.height, false, 0);
            vid2_BMP = new Bitmap( vid2_BMD );

            vid1_sprite.addChild(vid);
            vid1_sprite.x = 0;
            vid1_sprite.y = 0;
            addChild( vid1_sprite );

            vid2_sprite.addChild( vid2_BMP );
            vid2_sprite.x = 0;
            vid2_sprite.y = vid.height   5;

            addChild( vid2_sprite );

            stage.addEventListener(Event.ENTER_FRAME, draw_Video);
        }

        public function draw_Video (evt:Event) : void
        {
            if ( netStreamObj.client.decodedFrames == netStreamObj.decodedFrames ) { return; } // Here we skip multiple readings

            //# Get bitmapdata directly from container of video
            if ( vid1_sprite.graphics.readGraphicsData().length > 0 ) 
            {
                vid2_BMD = GraphicsBitmapFill(vid1_sprite.graphics.readGraphicsData()[0]).bitmapData;
            }

            effect_BitmapData(); //# Do an effect to bitmapdata

        }

        public function effect_BitmapData ( ) : void
        {
            //# Matrix for Black amp; White effect
            colMtx = colMtx.concat([1/3, 1/3, 1/3, 0, 0]); // red
            colMtx = colMtx.concat([1/3, 1/3, 1/3, 0, 0]); // green
            colMtx = colMtx.concat([1/3, 1/3, 1/3, 0, 0]); // blue
            colMtx = colMtx.concat([0, 0, 0, 1, 0]); // alpha

            CMfilter = new ColorMatrixFilter(colMtx);
            vid2_BMP.bitmapData.applyFilter(vid2_BMD, new Rectangle(0, 0, vid.width, vid.height), new Point(0, 0), CMfilter);

        }


    } 
}