In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

tVideo

Simple flash video player for control from JS
Get Adobe Flash player
by dmitry.ern 22 Aug 2013
    Embed
/**
 * Copyright dmitry.ern ( http://wonderfl.net/user/dmitry.ern )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/6gNK
 */

// Treds Video Player
// forked from ProjectNya's FLVPlayer Test (1)

package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.system.Security;
    import org.libspark.betweenas3.BetweenAS3;
    import org.libspark.betweenas3.tweens.ITween;
    import org.libspark.betweenas3.events.TweenEvent;
    import org.libspark.betweenas3.easing.*;
    import flash.net.URLRequest;
    import flash.external.ExternalInterface;
    import flash.trace.Trace;
    import flash.events.ProgressEvent;
    import flash.external.ExternalInterface;

    [ SWF( backgroundColor = '#000000', width = '1280', height = '720', frameRate = '50' ) ] // Почему параметры width и height нужны? Зачем они? В какое значение их лучше всего поставить? Я же их после переопределяю. Странно всё это :)

    public class Main extends Sprite
    {
        private var listener:String = ''; // js слушатели
        public var videoHeight:int = 720;
        public var videoWidth:int = 1280;
        private var player:FLVPlayer;
        private var seekBar:SeekBar;

        public function Main()
        {
            Security.loadPolicyFile( "https://t.treds.net/crossdomain.xml" ); // Сделать выбор домена, откуда брать crossdomain.xml
            Security.allowDomain( '*' );
            Security.allowInsecureDomain( '*' );
            
            // JS callbacks
            listener = root.loaderInfo.parameters.listener;
            //ExternalInterface.addCallback("loaded", loaded);
            
            // Create player
            player = new FLVPlayer( videoWidth, videoHeight, onReady, onPlaybackProgress, onLoadedProgress, onDataLoaded, onPlaybackComplete);

            // Flash callbacks for JS callbacks
            ExternalInterface.addCallback( 'play', player.play );
            ExternalInterface.addCallback( 'pause', player.pause ); 
            ExternalInterface.addCallback( 'stop', player.stop );
            ExternalInterface.addCallback( 'volume', player.volume );
            ExternalInterface.addCallback( 'position', player.seek );
            ExternalInterface.addCallback( 'getTime', player.getTime );
            ExternalInterface.addCallback( 'getDuration', player.getDuration );
                        
            // Configure player
            addChild(player); 
            controller(); 
            seekBar.initialize();
            player.seekBar = seekBar;
            
            //player.autoPlay = true;
            player.addEventListener(Event.INIT, initialize, false, 0, true);
            try {
                player.source = encodeURI(root.loaderInfo.parameters.url);
            }
            catch (e:Error) { 
            }
        }
        private function initialize( evt:Event ):void
        {
            player.removeEventListener(Event.INIT, initialize);
            player.start();//fade();
        }
        /*private function fade( ):void
        {
            var itween:ITween = BetweenAS3.to(loading, {alpha: 0, visible: 0}, 0.8, Linear.easeNone);
            itween.addEventListener(TweenEvent.COMPLETE, faded, false, 0, true);
            itween.play();
        }
        private function faded( evt:TweenEvent ):void
        {
            evt.target.removeEventListener(TweenEvent.COMPLETE, faded);
            removeChild(loading);
            loading = null;
            player.start();
        }*/
        private function controller( ):void
        {
            // Create interface
            seekBar = new SeekBar();
        }
        
        // JS callbacks //
        private function call(method:String, arg:*, arg2:* = null, arg3:* = null):void {
            ExternalInterface.call(listener + '.' + method, arg, arg2, arg3);
        }
        
        // Flash callbacks to JS //
        // When the player is ready
        public function onReady():void
        {
            var videoData:Object = new Object();
                videoData.duration = player.getDuration();
            call( "onReady", videoData );
        }
        
        public function onDataLoaded(duration:* = null, width:* = null, height:* = null):void
        {
            var videoData:Object = new Object();
                videoData.duration = duration;
                videoData.width = width;
                videoData.height = height;

            call( "onDataLoaded", videoData );
        }
        
        private function onPlaybackProgress():void {
            var time:int = player.getDuration() * player.percent;//player.getTime();
            call("onPlaybackProgress", time, player.percent);
        }
        
        private function onLoadedProgress(loaded:Number):void {
           var loaded:Number = loaded * 100;
           call("onLoadedProgress", loaded);
        }
        
        private function onPlaybackComplete():void {
            call("onPlaybackComplete", null);
        }
    }
}



//////////////////////////////////////////////////
// FLVPlayer
//////////////////////////////////////////////////
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Bitmap;
import flash.events.Event;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.events.SecurityErrorEvent;
import flash.events.AsyncErrorEvent;
import flash.external.ExternalInterface;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;

class FLVPlayer extends Sprite {
    public var id:uint;
    private var _connection:NetConnection;
    private var _stream:NetStream;
    private var _client:StreamClient;
    private var flvPath:String;
    private var vw:uint;
    private var vh:uint;
    private var _video:Video;
    private var _seekBar:SeekBar;
    private var initialized:Boolean = false;
    private var duration:Number = 0;
    private var _percent:Number = 0;
    private var completed:Boolean = false;
    private var readyCallback:Function;
    private var playbackProgress:Function;
    private var loadedProgress:Function;
    private var dataLoaded:Function;
    private var playbackComplete:Function;
    private var tryToPlay:Boolean = false; // Флаг попытки проигрыша, устанавливается для проигрыша на более позднем этапе, если изначально проиграть не получилось из-за того что видео не загрузилось. Хак или вроде того @dmitry
    private var streamClosed:Boolean = false;
    private var playing:Boolean = false;
    
    public function FLVPlayer(w:uint, h:uint, onReadyCallback:Function, onPlaybackProgress:Function, onLoadedProgress:Function, onDataLoaded:Function, onPlaybackComplete:Function) {
        vw = w;
        vh = h;
        readyCallback = onReadyCallback;
        playbackProgress = onPlaybackProgress;
        loadedProgress = onLoadedProgress;
        dataLoaded = onDataLoaded;
        playbackComplete = onPlaybackComplete;
        init();
    }

    private function init():void {
        _video = new Video(vw, vh);
        addChild(_video);
        _video.smoothing = true;
        _connection = new NetConnection();
        _connection.addEventListener(NetStatusEvent.NET_STATUS, ncNetStatus, false, 0, true);
        _connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError, false, 0, true);
        //_connection.connect(null);
    }
    public function set seekBar(bar:SeekBar):void {
        _seekBar = bar;
    }
    public function set source(path:String):void {
        flvPath = path;
        _connection.connect(null);
    }
    private function ncNetStatus(evt:NetStatusEvent):void {
        switch (evt.info.code) {
            case "NetConnection.Connect.Success" :    //接続成功
                initialize();
                break;
            case "NetConnection.Connect.Failed" :    //接続失敗
                break;
            case "NetConnection.Connect.Rejected" :    //接続拒否
                break;
            case "NetConnection.Connect.Closed" :    //接続(正常)切断
                break;
        }
    }
    private function securityError(evt:SecurityErrorEvent):void {
        trace(evt.text);
    }
    private function initialize():void {
        _client = new StreamClient();
        _client.addEventListener(Event.INIT, onMetaData, false, 0, true);
        _stream = new NetStream(_connection);
        _stream.bufferTime = 5;
        _stream.addEventListener(NetStatusEvent.NET_STATUS, nsNetStatus, false, 0, true);
        _stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncError, false, 0, true);
        _stream.client = _client;
        _video.attachNetStream(_stream);
        load();
    }
    private function onMetaData(evt:Event):void {
        duration = evt.target.duration;
        dataLoaded(evt.target.duration, evt.target.width, evt.target.height);
        setup();
    }
    private function load():void {
        _stream.receiveAudio(false);
        _stream.play(flvPath);
        _stream.pause();
        addEventListener(Event.ENTER_FRAME, progress, false, 0, true);
    }
    private function progress(evt:Event):void {
        var loaded:Number = _stream.bytesLoaded/_stream.bytesTotal;
        _seekBar.progress = loaded;
        if (loaded >= 1) {
            removeEventListener(Event.ENTER_FRAME, progress);
        }
        if (loaded > 0) {
            loadedProgress(loaded);
        }
    }
    private function nsNetStatus(evt:NetStatusEvent):void {
        switch (evt.info.code) {
            case "NetStream.Buffer.Full" :
                break;
            case "NetStream.Buffer.Flush" :
                break;
            case "NetStream.Buffer.Empty" :
                break;
            case "NetStream.Play.Start" :
                setup();
                break;
            case "NetStream.Play.Stop" :
                complete();
                break;
            case "NetStream.Play.StreamNotFound" :
                break;
            case "NetStream.Pause.Notify" :
                break;
            case "NetStream.Seek.Notify" :
                break;
            case "NetStream.Seek.InvalidTime" :
                break;
        }
    }
    private function asyncError(evt:AsyncErrorEvent):void {
        trace(evt.text);
    }
    private function setup():void {
        if (duration > 0) {
            if (!initialized) {
                initialized = true;
                dispatchEvent(new Event(Event.INIT));
                readyCallback();
            }
        }
    }
    public function start():void {
        stop();
        _stream.receiveAudio(true);
        if (tryToPlay) play();
    }
    private function playPause(evt:MouseEvent):void {
        if( playing == false )
        {
            play( );
        }
        else
        {
            pause( );
        }
    }
    public function play( ):void
    {
        tryToPlay = true;// Видео может ещё не до конца загрузиться, а JS может запросить проигрыш. В этом случае нужно сохранить флаг "играть видео, когда появится такая возможность". Не хочу делать на одном флаге с autoplay во избежании возможных конфликтов.
        playing = true;
        if( streamClosed == true )
        {
            _stream.play( flvPath );
            streamClosed = false;
        }
        else
        {
            _stream.resume( );
        }
        addEventListener(Event.ENTER_FRAME, update, false, 0, true);
    }
    public function pause():void {
        removeEventListener(Event.ENTER_FRAME, update);
        playing = false;
        _stream.pause();
    }
    public function stop():void {
        pause();
        makeThumbnail();
        _stream.close();
        streamClosed = true;
        _video.clear();
    }
    // Создание картинки-заглушки на основе текущего кадра
    public function makeThumbnail():void
    {
        
        var thumbnailData:BitmapData = new BitmapData( vw, vh, false, 0x000000 );
        try{
            thumbnailData.draw( _video as DisplayObject );z
        } catch(error:Error){ ExternalInterface.call('console.log', error);}
        var thumbnail:Bitmap = new Bitmap( thumbnailData );
        //addChild( thumbnail );
    }
    public function volume(v:Number):void {
        _stream.soundTransform = new SoundTransform( v / 100 );
    }
    public function complete():void {
        removeEventListener(Event.ENTER_FRAME, update);

        playing = false;
        percent = 1;

        playbackComplete();
    }
    public function seek(seconds:Number):void {
        _stream.seek(seconds);
        percent = seconds * duration / 100;
    }
    
    public function update(evt:Event):void {
        percent = _stream.time/duration;
    }
    public function getTime():int {
        return _stream.time;
    }
    public function getDuration():int {
        return duration;
    }
    public function getPercent():Number {
        return percent;
    }
    public  function press(evt:Event):void {
        removeEventListener(Event.ENTER_FRAME, update);
        _stream.pause();
    }
    /*private function drag(evt:Event):void {
        percent = _seekBar.percent;
        playbackProgress();
    }*/
    private function release(evt:Event):void {
        seek(percent = _seekBar.percent);
        if (playing == false) {
            play(); 
        } else {
            pause();
        }
    }
    public function get percent():Number {
        return _percent;
    }
    public function set percent(param:Number):void {
        _percent = param;
        if (_percent >= 1) {
            _percent = 1;
            completed = true;
        } else {
            completed = false;
        }
        _seekBar.percent = _percent;
        playbackProgress();
    }

}


//////////////////////////////////////////////////
// StreamClient
//////////////////////////////////////////////////

import flash.events.EventDispatcher;
import flash.events.Event;

class StreamClient extends EventDispatcher {
    public var info:Object;
    public var duration:Number;
    public var width:Number;
    public var height:Number;

    public function StreamClient() {
    }

    public function onMetaData(metaData:Object):void {
        info = metaData;
        duration = info.duration;
        width = info.width;
        height = info.height;
        dispatchEvent(new Event(Event.INIT));
    }

}


//////////////////////////////////////////////////
// PlayPauseBtnクラス
//////////////////////////////////////////////////

/*import flash.display.Sprite;
import flash.display.Shape;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;

class PlayPauseBtn extends Sprite {
    public var id:uint;
    private var _playing:Boolean = false;

    public function PlayPauseBtn() {
        init();
    }

    private function init():void {
        playing = false;
    }
    public function get playing():Boolean {
        return _playing;
    }
    public function set playing(param:Boolean):void {
        _playing = param;
    }
}*/

//////////////////////////////////////////////////
// SeekBar
//////////////////////////////////////////////////

import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;

class SeekBar extends Sprite {
    public var id:uint;
    private var _progress:Number = 0;
    private var _percent:Number = 0;
    private var _enabled:Boolean = true;

    public function SeekBar() {
        init();
    }

    private function init():void {
        progress = 0;
        percent = 0;
    }
    public function initialize():void {
        init();
    }
    public function get progress():Number {
        return _progress;
    }
    public function set progress(param:Number):void {
        _progress = param;
    }
    public function get percent():Number {
        return _percent;
    }
    public function set percent(param:Number):void {
        _percent = param;
    }

}