Search code examples
actionscript-3flashvideovideo-processingframe-rate

ActionScript 3.0 Switching Video by pressing a key


I'm writing a simple program that switch from a video to another when I press two different key. If I press the key F it will be displayed the video1 if I press the key 2 it will be displayed the video 2. While the video1 or the video2 are displayed if I press the key F or 2 I switch between the two video. I have a problem. If I press quickly 2 and F the fps start to drop and after some quick press of 2 and F the .swf crash. I think that it's a problem of my code cause it'isnt optimized. The base idea is that everytime that the user press F or 2 key while a video is displayed I close the stream of that video and I start to stream the other video and so on. This is the code:

package {
import flash.display.MovieClip;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.AsyncErrorEvent;
import flash.media.Video;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.utils.getTimer;


public class MainDisplayDifferentVideoOnCLick extends MovieClip {

    public function MainDisplayDifferentVideoOnCLick() {
        keyPressed();
        fpsNumber();

    }
    public function keyPressed(): void {
        stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        function onKeyDown(myKey: KeyboardEvent): void {
            if (myKey.keyCode == 70) {
                playVideo1();
            }
            if (myKey.keyCode == 50) {
                playVideo2();
            }
        }
    }

    function playVideo1(): void {
        var networkConnection: NetConnection = new NetConnection();
        networkConnection.connect(null);
        var networkStream: NetStream = new NetStream(networkConnection);
        networkStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler);
        networkStream.play("Damiani.mp4");
        function errorHandler(error1: AsyncErrorEvent): void {
            // ingoro l' evento
        }
        var myVideo1: Video = new Video();
        myVideo1.attachNetStream(networkStream);
        myVideo1.width = 1920;
        myVideo1.height = 1080;
        addChild(myVideo1);
        stage.addEventListener(KeyboardEvent.KEY_DOWN, on2Down);
        function on2Down(ev: KeyboardEvent): void {
            if (ev.keyCode == 50) {
                networkStream.close();
            }
        }

    }
    function playVideo2(): void {
        var networkConnection: NetConnection = new NetConnection();
        networkConnection.connect(null);
        var networkStream: NetStream = new NetStream(networkConnection);
        networkStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler);
        networkStream.play("Sfelab.mp4");
        function errorHandler(error1: AsyncErrorEvent): void {
            // ingoro l' evento
        }
        var myVideo2: Video = new Video();
        myVideo2.attachNetStream(networkStream);
        myVideo2.width = 1920;
        myVideo2.height = 1080;
        addChild(myVideo2);

        stage.addEventListener(KeyboardEvent.KEY_DOWN, onFDown);
        function onFDown(ev: KeyboardEvent): void {
            if (ev.keyCode == 70) {
                networkStream.close();
            }
        }
    }
    public function fpsNumber(): void {
        var frames: int = 0;
        var prevTimer: Number = 0;
        var curTimer: Number = 0;

        this.addEventListener(Event.ENTER_FRAME, performFrameTest);

        function performFrameTest(e: Event): void {
            frames += 1;
            curTimer = getTimer();
            if (curTimer - prevTimer >= 1000) {
                trace("FPS: ");
                trace(Math.round(frames * 1000 / (curTimer - prevTimer)));
                prevTimer = curTimer;
                frames = 0;
            }
        }
    }
}

}

Do you have any advice? Thank you!


Solution

  • If you want two things doing the same thing in your program. Don't just copy-paste the code that works for single thing. For example you can use single video instance for any number of videos you want.

    It's not clear if you really want to close video and then start again from beginning once it's chosen back or just switch on the fly between your playbacks. Below code do second thing but I hope it's clear how to modify it. Certainly you don't need to stop the stream imminently after choosing another one if you want to have functionality to move back to it.

    package adnss.projects.tchqs 
    {
        import flash.display.MovieClip;
        import flash.events.KeyboardEvent;
        import flash.media.Video;
        import flash.ui.Keyboard;
    
        public class Main extends MovieClip {
    
            /**List of all video streams that suppose to played.**/
            private var vids:Vector.<VideoPlayback> = Vector.<VideoPlayback>(
            [new VideoPlayback("AlexD.mp4", Keyboard.F),
             new VideoPlayback("Nike AIR.mp4", Keyboard.NUMBER_2)]);
    
            /**Current video playback. Should be one of "vids" items.**/
            private var currVid:VideoPlayback;
            /**Common Video view used to display stream on stage.**/
            private var _video:Video = new Video();
    
            public function Main() {
                prepareVideoView(1680, 1050);
                stage.addEventListener(KeyboardEvent.KEY_DOWN, onKDown);
            }
    
            /**Hangles switching between videos accordingly to key that was pressed.**/
            private function onKDown(e:KeyboardEvent): void {
                for each (var vp:VideoPlayback in vids) {
                    if (vp.keyCode != e.keyCode) continue; //not our key
                    if (vp == currVid) return; //the video of hited key is already playing - not need to change.
                    if (currVid) currVid.stream.pause(); //If you stat fist video by default, you can remove if(...)
                    if (!vp.stream) vp.openStream(); //open stream if not oppened already.
                    _video.attachNetStream(vp.stream); //change stream of our video view.
                    vp.stream.resume(); //I hope it's clear what "vp" is...
                    currVid = vp; return;  
                }
            }
    
            /**
             * Setup _video:Video view and adds it to stage.
             * @param   w width of video view.
             * @param   h height of video view.
             */
            private function prepareVideoView(w:Number, h:Number) {
                _video.width = w;
                _video.height = h;
                stage.addChild(_video);
            }
    
        }
    
    }
    import flash.events.AsyncErrorEvent;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    
    /**
     * This class define particular video playback - bind video address to shortcut key,
     * and opens unique stream for it if necessary. 
     */
    class VideoPlayback {
        private var _adrs:String;
        private var _kCode:uint;
        private var _s:NetStream;
    
        public function VideoPlayback(adress:String, keyCode:uint) {
            _adrs = adress;
            _kCode = keyCode;
        }
    
        /**Open NetStream for this playback accordingly to video adress passed in constructor.
         * Until this method is called "stream" property is not available.**/
        public function openStream() {
            var c: NetConnection = new NetConnection();
            c.connect(null);
            _s = new NetStream(c);
            _s.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler);
            _s.play(_adrs);
            function errorHandler(error1: AsyncErrorEvent): void {
                // ingoro l' evento
            }
        }
    
        public function get adress():String{return _adrs;}
    
        public function get keyCode():uint{return _kCode;}
    
        public function get stream():NetStream{return _s;}
    }
    

    Notice that VideoPlayback class is outside the package. It will work fine in one file but you may want to move it to separate file just to have things more organized.