Tutorial - Playing FLV video in plain AS3 - Part 3 (Updated)

Hi Everyone,

it's been a while.. a long while. I have been selling my time to Adobe, doing Flex work with a great team in NYC; we are working on the MediaStore for Verizon Wireless since July 21st? I forget.. NYC is nice, but not for me. I'm a nature lover!

A few people posted comments on the second part of this tutorial, kudos to you! You're partly to blame for this late evening blog post ;)

For those who didn't read them already, I strongly suggest starting by reading the first parts of this tutorial :

The Events

In part 2, pretty much all the functionality was covered, except the events class. I like to use custom events, which are derived from flash.events.Event
because then you are allowed to add custom properties to your events, which are easy to pick up by the listeners. For this particular case, I have identified 3 different types of events I would like to dispatch, based on the properties that are associated with each:

  • MediaEvent -- for basic events that don't require any data
  • MediaSizeEvent -- for events related to the size (in pixels) of the media playing
  • MediaTimeEvent -- for the events related to time (lenght, time position)

MediaEvent

Actionscript:
  1. package newcommerce.media
  2. {
  3.     import flash.events.Event;
  4.    
  5.     public class MediaEvent extends Event
  6.     {
  7.         // dispatched when the media has finished playing
  8.         public static const FINISHED_PLAYING:String = "finished_playing";
  9.  
  10.         // dispatched when the media has fully loaded
  11.         public static const FULLY_LOADED:String = "fully_loaded";
  12.  
  13.         // dispatched when there is an error playing the media
  14.         public static const ERROR:String = "error";
  15.  
  16.         // dispatched when the media has started playing
  17.         public static const STARTED_PLAYING:String = "started_playing";
  18.        
  19.         // text property is used to carry error text
  20.         protected var _text:String;
  21.         public function get text():String { return _text; }
  22.        
  23.         public function MediaEvent(type:String, text:String = "")
  24.         {
  25.             super(type);
  26.             _text = text;
  27.         }
  28.        
  29.         public override function toString():String
  30.         {
  31.             return "newcommerce.media.MediaEvent";
  32.         }
  33.     }
  34. }

MediaSizeEvent

Actionscript:
  1. package ca.newcommerce.media
  2. {
  3.     import flash.events.Event;
  4.    
  5.     public class MediaSizeEvent extends Event
  6.     {
  7.         // dispatched when we received the media size in the metadata so the UI can adapt to it
  8.         public static const SIZE:String = "media_size";
  9.        
  10.         // width and height properties contain the actual media size
  11.         protected var _width:Number;
  12.         protected var _height:Number;
  13.        
  14.         public function get height():Number { return _height; }
  15.         public function get width():Number { return _width; }
  16.        
  17.         public function MediaSizeEvent(type:String, width:Number, height:Number)
  18.         {
  19.             super(type);
  20.             _width = width;
  21.             _height = height;
  22.         }
  23.     }
  24. }

MediaTimeEvent

Actionscript:
  1. package newcommerce.media
  2. {
  3.     import flash.events.Event;
  4.    
  5.     public class MediaTimeEvent extends Event
  6.     {
  7.         // dispatched to update the listeners on the current position (media_time) of the playing media
  8.         public static const TIME:String = "media_time";
  9.  
  10.         // dispatched once we receive the media duration information (in the metadata)
  11.         public static const DURATION:String = "media_duration";
  12.  
  13.         // actual media time (position or total time depending on the event type used)
  14.         protected var _time:Number;
  15.  
  16.         // the percentage of the media that is currently loaded
  17.         protected var _loaded:Number;
  18.  
  19.         public function get time():Number { return _time; }
  20.         public function get loaded():Number { return _loaded; }
  21.  
  22.         public function MediaTimeEvent(type:String, time:Number, loaded:Number = -1)
  23.         {
  24.             super(type);
  25.             _time = time;
  26.             _loaded = loaded;
  27.         }
  28.     }
  29. }

Integration inside of the code

In the preview part, I hadn't yet seperated the events to different classes in the code. So here is the updated source for FLVPlayer

Actionscript:
  1. package newcommerce.media
  2. {
  3.     import newcommerce.media.MediaSizeEvent;
  4.     import newcommerce.media.MediaTimeEvent;
  5.     import newcommerce.media.MediaData;
  6.     import newcommerce.media.MediaEvent;
  7.    
  8.     import flash.media.SoundTransform;
  9.    
  10.     import flash.net.NetConnection
  11.     import flash.net.NetStream;
  12.     import flash.media.Video;
  13.     import flash.display.Sprite;
  14.  
  15.     import flash.events.IOErrorEvent;
  16.     import flash.events.NetStatusEvent
  17.     import flash.events.SecurityErrorEvent;
  18.     import flash.events.AsyncErrorEvent;
  19.    
  20.     import flash.events.EventDispatcher;
  21.     import flash.utils.Timer;
  22.     import flash.events.TimerEvent;
  23.    
  24.     public class FLVPlayer extends EventDispatcher
  25.     {      
  26.         protected var _currentMedia:MediaData;     
  27.         protected var _stream:NetStream;
  28.         protected var _paused:Boolean = false;
  29.         protected var _playing:Boolean = false;
  30.         protected var _timer:Timer;  
  31.         protected var _soundTransform:SoundTransform;
  32.         protected var _lastVolume:Number = 1;
  33.         protected var _mute:Boolean = false;       
  34.         protected var _connection:NetConnection;       
  35.         protected var _mediaFinished:Boolean = false;      
  36.         protected var _streamStatus:Array;
  37.         protected var _lastPos:Number;
  38.         protected var _video:Video;
  39.                
  40.         public function set video(video:Video):void { _video = video; }
  41.         public function get video():Video { return _video; }       
  42.         public function get playing():Boolean { return _playing; }   
  43.         public function get paused():Boolean { return _paused; }       
  44.         public function get currentMedia():MediaData { return _currentMedia; }   
  45.         public function get volume():Number { return _lastVolume * 100; }  
  46.        
  47.         public function get position():Number
  48.         {
  49.             if(_stream != null)
  50.                 return _stream.time;
  51.             else
  52.                 return 0;
  53.         }
  54.        
  55.         public function get duration():Number
  56.         {
  57.             if(_currentMedia != null)
  58.             {
  59.                 return _currentMedia.duration;
  60.             }
  61.             else
  62.                 return -1;
  63.         }
  64.        
  65.         public function FLVPlayer()
  66.         {         
  67.             _soundTransform = new SoundTransform();
  68.  
  69.             _timer = new Timer(250);
  70.             _timer.addEventListener(TimerEvent.TIMER, doMediaTime);
  71.  
  72.             _streamStatus = [];
  73.         }
  74.        
  75.        
  76.         protected function pushStatus(status:String):void
  77.         {
  78.             _streamStatus.push(status);
  79.             while (_streamStatus.length> 3)
  80.                 _streamStatus.shift();
  81.         }
  82.        
  83.         public function reset():void
  84.         {
  85.             stop();
  86.             newStream();
  87.         }
  88.        
  89.         protected function newStream():void
  90.         {         
  91.             if(_stream != null)
  92.             {
  93.                 _stream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, doAsyncError);
  94.                 _stream.removeEventListener(NetStatusEvent.NET_STATUS, doStreamStatus);
  95.                 _stream.removeEventListener(IOErrorEvent.IO_ERROR, doIOError);
  96.                 _stream.close();
  97.             }
  98.        
  99.             if(_connection != null)
  100.             {
  101.                 _connection.removeEventListener(NetStatusEvent.NET_STATUS, doConnectionStatus);
  102.                 _connection.removeEventListener(IOErrorEvent.IO_ERROR, doIOError);
  103.                 _connection.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, doSecurityError);
  104.                 _connection.close();
  105.             }
  106.            
  107.             _connection = new NetConnection();
  108.             _connection.connect(null);
  109.             _connection.addEventListener(NetStatusEvent.NET_STATUS, doConnectionStatus);
  110.             _connection.addEventListener(IOErrorEvent.IO_ERROR, doIOError);
  111.             _connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, doSecurityError);
  112.            
  113.             _stream = new NetStream(_connection);
  114.             _stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, doAsyncError);
  115.             _stream.addEventListener(NetStatusEvent.NET_STATUS, doStreamStatus);
  116.             _stream.addEventListener(IOErrorEvent.IO_ERROR, doIOError);
  117.             _stream.client = this;
  118.            
  119.             _video.attachNetStream(_stream);
  120.  
  121.             _stream.bufferTime = 1;
  122.             _stream.receiveAudio(true);
  123.             _stream.receiveVideo(true);
  124.         }
  125.        
  126.         public function stop():void
  127.         {
  128.             if(!_playing)
  129.                 return;
  130.                
  131.             _stream.pause();
  132.             _playing = false;
  133.             _timer.stop();
  134.         }
  135.        
  136.         public function playMedia(media:MediaData):void
  137.         {
  138.             _mediaFinished = false;   
  139.             if(media == null)
  140.                 return;
  141.            
  142.             _currentMedia = media;
  143.             _streamStatus = [];
  144.            
  145.             play(true);
  146.         }   
  147.        
  148.         public function seek(seconds:Number):void
  149.         {
  150.             if (seconds <_currentMedia.duration-2 && _playing)
  151.             {
  152.                 _lastPos = _stream.time;
  153.                 _stream.seek(seconds);
  154.                 _stream.resume();
  155.             }
  156.         }
  157.        
  158.         public function pause():void
  159.         {         
  160.             _stream.pause();
  161.             _paused = true;
  162.             _timer.stop();   
  163.         }
  164.        
  165.         protected function doConnectionStatus(evt:NetStatusEvent):void
  166.         {
  167.             trace("connection: " + evt.info.code);
  168.         }
  169.        
  170.         protected function doStreamStatus(evt:NetStatusEvent):void
  171.         {         
  172.             trace("stream: " + evt.info.code);
  173.             if (evt.info.code == "NetStream.Seek.InvalidTime")
  174.             {
  175.                 _stream.seek(_lastPos);
  176.                 _stream.resume();
  177.             }
  178.             else
  179.             {
  180.                 pushStatus(evt.info.code);     
  181.                 analyzeStatus();
  182.             }
  183.         }
  184.        
  185.         protected function analyzeStatus():void
  186.         {
  187.             trace("analyzeStatus()");
  188.             var stopIdx:Number = _streamStatus.lastIndexOf("NetStream.Play.Stop");
  189.             var flushIdx:Number = _streamStatus.lastIndexOf("NetStream.Buffer.Flush");
  190.             var emptyIdx:Number = _streamStatus.lastIndexOf("NetStream.Buffer.Empty");
  191.            
  192.             var mediaFinished:Boolean = false;
  193.            
  194.             if (stopIdx> -1 && flushIdx> -1 && emptyIdx> -1)
  195.             {
  196.                 if (flushIdx <stopIdx && stopIdx <emptyIdx)
  197.                 {
  198.                     mediaFinished = true;
  199.                 }
  200.             }
  201.             else if (flushIdx> -1 && emptyIdx> -1)
  202.             {
  203.                 if (flushIdx <emptyIdx)
  204.                     mediaFinished = true;
  205.             }
  206.             else if (stopIdx> -1 && flushIdx> -1)
  207.             {
  208.                 mediaFinished = true;
  209.             }
  210.            
  211.             if (mediaFinished)
  212.             {   
  213.                 trace("finished playing");
  214.                 dispatchEvent(new MediaEvent(MediaEvent.FINISHED_PLAYING))
  215.                 while (_streamStatus.length> 0)
  216.                     _streamStatus.pop();
  217.             }         
  218.             else if (_streamStatus[_streamStatus.length-1] == "NetStream.Play.Start")
  219.                 dispatchEvent(new MediaEvent(MediaEvent.STARTED_PLAYING));
  220.            
  221.         }
  222.        
  223.         public function mute(muted:Boolean = true):void
  224.         {
  225.             _mute = muted;
  226.             if(_mute)
  227.             {
  228.                 _soundTransform.volume = 0;
  229.                 _stream.soundTransform = _soundTransform;
  230.             }
  231.             else
  232.             {
  233.                 _soundTransform.volume = _lastVolume;
  234.                 _stream.soundTransform = _soundTransform;
  235.             }
  236.         }
  237.        
  238.         public function setVolume(volume:Number):void
  239.         {      
  240.             _lastVolume = _soundTransform.volume = volume/100;
  241.            
  242.             if(!_mute)
  243.                 _stream.soundTransform = _soundTransform;                  
  244.         }
  245.  
  246.         public function play(forced:Boolean = false):void
  247.         {
  248.             if(_paused && !forced)
  249.             {
  250.                 _stream.resume();
  251.                 _paused = false;
  252.                 _timer.start();
  253.                 return;
  254.             }
  255.  
  256.             reset();
  257.  
  258.             _stream.play(_currentMedia.uri);
  259.  
  260.             setVolume(this._lastVolume*100);
  261.  
  262.             _playing = true;
  263.             _paused = false;
  264.             _timer.start();
  265.         }
  266.        
  267.         public function onMetaData(infoObject:Object):void
  268.         {
  269.             if (infoObject.duration != null)
  270.             {
  271.                 // dispatch a DURATION event
  272.                 dispatchEvent(new MediaTimeEvent(MediaTimeEvent.DURATION, infoObject.duration));
  273.             }
  274.  
  275.             var lclHeight:Number = infoObject.height;
  276.             var lclWidth:Number = infoObject.width;
  277.  
  278.             if(isNaN(lclHeight) || isNaN(lclWidth))
  279.             {
  280.                 lclWidth = 425;
  281.                 lclHeight= 320;
  282.             }
  283.  
  284.             // dispatch the size received event
  285.             dispatchEvent(new MediaSizeEvent(MediaSizeEvent.SIZE, lclWidth, lclHeight));
  286.  
  287.             if(!willTrigger(MediaSizeEvent.SIZE))
  288.             {
  289.                 var yDif:Number = (_video.height - lclHeight)/2;
  290.                 _video.y += yDif;            
  291.                 _video.height = lclHeight;     
  292.             }
  293.         }
  294.        
  295.         public function doMediaTime(evt:TimerEvent):void
  296.         {
  297.             var pct:Number = Math.round(_stream.bytesLoaded / _stream.bytesTotal * 100);
  298.            
  299.             // dispatch a MEDIA_TIME event
  300.             dispatchEvent(new MediaTimeEvent(MediaTimeEvent.TIME, _stream.time, pct));
  301.         }
  302.        
  303.         protected function doSecurityError(evt:SecurityErrorEvent):void
  304.         {
  305.             trace("AbstractStream.securityError");
  306.             dispatchEvent(new MediaEvent(MediaEvent.ERROR, evt.text));
  307.         }
  308.        
  309.         protected function doIOError(evt:IOErrorEvent):void
  310.         {
  311.             trace("AbstractScreem.ioError");
  312.             dispatchEvent(new MediaEvent(MediaEvent.ERROR, evt.text));
  313.         }
  314.        
  315.         protected function doAsyncError(evt:AsyncErrorEvent)
  316.         {
  317.             trace("AsyncError");           
  318.             dispatchEvent(new MediaEvent(MediaEvent.ERROR, evt.text));
  319.         }      
  320.        
  321.         protected function doNetStatus(evt:NetStatusEvent):void
  322.         {
  323.         }      
  324.     }
  325. }

MediaData
and just in case you missed it in the other parts, here is the source for the MediaData class..

Actionscript:
  1. package newcommerce.media
  2. {
  3.     public class MediaData
  4.     {
  5.         protected var _uri:String;
  6.         protected var _title:String;
  7.         protected var _duration:Number;
  8.         protected var _image:String;
  9.         protected var _width:Number;
  10.         protected var _height:Number;
  11.        
  12.         public function set uri(uri:String):void { _uri = uri; }
  13.         public function get uri():String { return _uri; }
  14.         public function set image(image:String):void { _image = image; }
  15.         public function get image():String { return _image; }
  16.         public function set title(title:String):void { _title = title; }
  17.         public function get title():String { return _title; }
  18.         public function set duration(duration:Number):void { _duration = duration; }
  19.         public function get duration():Number { return _duration; }
  20.         public function get width():Number { return _width; }
  21.         public function set width(value:Number):void { _width = value; }
  22.         public function get height():Number { return _height; }
  23.         public function set height(value:Number):void { _height = value; }
  24.        
  25.         function MediaData(uri:String = "", title:String = "", duration:Number = 120,  image:String = "", width:Number = 320, height:Number = 200)
  26.         {         
  27.             _uri = uri;
  28.             _title = title;
  29.             _duration = duration;
  30.             _image = image;
  31.             _width = width;
  32.             _height = height;
  33.         }
  34.     }
  35. }

That's it folks!
I have used these classes in many projects so far, they work great! With each project they got refined a bit, so the version in this tutorial is actually the latest, which I fine-tuned for ZooToo PetWars widget. They are also used for all the work I did for Music Nation, and I am sure I will re-use them again and again. Hope you enjoyed, I will put the source .zip file up here in a few days.

[2009.12.10] UPDATE -- SOURCE CODE
Due to popular request, and although I believe I shouldn't do this, here is the source code.

Thanks!

Martin



Related posts (automatically generated):

  1. Tutorial - Playing FLV video in plain AS3 - Part 1
  2. Tutorial - Playing FLV video in plain AS3 - Part 2
  3. Tutorial - Playing FLV video in plain AS3 - Part 4 - Sample Usage


26 Responses to “Tutorial - Playing FLV video in plain AS3 - Part 3 (Updated)”

  1. Andy says:

    Excellent tutorial, looking forward to getting all the bits together and playing around with it! Thanks again :)

  2. Sven says:

    Hi,

    This is great stuff, I’m sure (I get no errors when referencing the classes). But I’m having a little hard time finding out how to implement it so that I can actually get a video to play (anywhere. On stage or another MC instance).

    Do I have to create an instance of a video component of some sort first to get it to work, or? It all seem a bit abstract to me (yes, fairly new to OOP concepts. But learning though).

    Will there be a chance to see a (simple) tutorial on how to implement this thing?

  3. Sven says:

    OK, this is what I try to do. So you may get why I’m off in the wrong direction:

    (first I reference the classes in my class using the import statement), then:

    var myMediaData = new MediaData(”some.flv”, “some title”, 234, “some.jpg”, 508, 169);
    var myFLVPlayer = new FLVPlayer();
    myFLVPlayer.playMedia(myMediaData);

    But when I dispatch an event from a thumbnail (movieclip) to play a given flv file, I get an Error #1009: Cannot access a property or method of a null object reference.

    Any idea what I’m missing?

  4. Andy says:

    Ok, i’ve got it working, having a few problems with the aspect ratio (but i’m sure that’s a small issue)

    You need to create an instance of the Video class and then set that to the video instance for the FLVPlayer to use.

    So something like this…

    var myMediaData = new MediaData(“videos/test.flv“, “some title“, 234, “image.jpg“, 320, 200);

    var myFLVPlayer = new FLVPlayer();

    var video:Video = new Video(320, 200);

    myFLVPlayer.video = video;

    myFLVPlayer.playMedia(myMediaData);

    stage.addChild(video);

    Hope that helps!

    Andy

  5. Marti Legris says:

    very good!

    As for the aspect ratio, you want to catch the “MediaSizeEvent”, and adapt accordingly:

    [as]
    // add this before the call to playMedia
    myFLVPlayer.addEventListener(MediaSizeEvent.SIZE, doMediaSize);

    // then add this function
    function doMediaSize(evt:MediaSizeEvent):void
    {
    // make sure the “video” variable is available in this scope
    video.width = evt.width;
    video.heigth = evt.height;
    }
    [/as]

    If my memory serves well, this should do the trick!

  6. Sven says:

    Hi (again)

    Martin, you should post a complete tutorial on using this :).

    I can’t seem to get the MediaTimeEvent to work.

    I have added a simple class that stretches according to a percentage recieved. I’ve added an eventListener to this, that listen for MediaTimeEvent. But it doesn’t seem to hear anything. When I simply run trace within the attached handler it never gets called. I’ve tried to enable bubbles but that didn’t seem to help.

    Would you be able to show a simple example of how to set this up?

  7. Sven says:

    Correction ‘listen for MediaTimeEvent.TIME’

  8. Rob Thomson says:

    Very nice piece. Well done.

    Just a quick note tho incase someone did a cut n paste, you spelt height wrong in your September 29th, 2008 at 11:18 am comment :P

    ie
    video.heigth = evt.height;

  9. steve says:

    Great tutorial! Does this code also work with RTMP using either FMS or Red5? If not, any chance for an updated tutorial with the additional code required?

  10. tillkee says:

    Great tutorial,

    anyone knows, how you can assign buttons to different video files, so the video plays only when you click a button. lets say i have 5 different movies, and 5 buttons assigned to them. by clicking a button, the asigned video starts to play…
    can i use the netconnect method? anyone knows how?

    would be great to get some help

  11. Anar says:

    It seems like a very useful tutorial, but I don’t have much time now to inspect the code now.
    Could you please, tell me, if this media player gives the opportunity to stream video from the middle of it. I mean, before it downloaded 100%, lets’s say it has only downloaded 20% of the video, and if the user moves the pointer to 60% on bar, will it start downloading the video from the 60% of the it or it will continue from 20%?
    Thanks in advance.

  12. pushp says:

    hi, very nice tutorial, it helps me a lot. Thank u very much.

  13. Jk_ says:

    Great tutorial! It has been very helpful.

    Thanks for sharing your knowledge.

  14. Flv Player says:

    Thanks for given this great post…

  15. Jack says:

    Hey,

    I was wondering why you dont override the Clone function and the toString functions as required by the documentation?

    Thanks in advance

  16. simone says:

    Hi Martin,

    but there isn’t the “source.zip” file???

    Thanks

  17. David says:

    Hi Martin.

    A quick ‘thank you!’ for writing this article. I’m new to ActionScript and thirsty for well written, object-oriented code - your work is really helping me to understand.

    Again, thank you!

  18. Acts7 says:

    I took the aspect ratio on with a different method.
    I defined a variable for the width - and then used scaleX scaleY to maintain proper proportions.

    //
    var vWidth:Number = new Number(350);
    var vHeight:Number = new Number(178);
    //
    //““`~~~~~~“““

    private function doMediaSize(e:MediaSizeEvent):void {

    // make sure the “video” variable is available in this scope

    // If I want to use the default size of the media - do it this way
    //video.width = e.width;
    //video.height = e.height;

    // If I want to specify a size and constrain to that spec / dimension - do it this way:
    video.width = vWidth;
    video.scaleX = video.scaleY;

    }

  19. Edwin Rios says:

    Nice tutorial!!!
    Would you mind to publish the zip file?

    Thanks

  20. corbanb says:

    hey marti, not sure why but your RSS feed and your homepage http://blog.martinlegris.com are not updating correctly. I am only seeing posts from July? Some how stumbled on this post via google.

  21. John says:

    Hello Mr. Legris,

    thank you very much for your tutorial on how to create own flv player.

    I am trying to find a way how to add subtitles feature to your implementation. Please may you point me in right direction ? I am just beginner of AS (but have some programming skills from other languages).

    I was thinking of adding textbox over player, parse XML TimedText subs format amd register ASCuePoints (for every single line of subs), than display text from CUEPoint when it is reached (OnCuePoints event) in textbox…

    Is it doable ? Is there any easier solution ? (FLVCaptioning component seems not to work for me). I am using pseudo streaming throught xmoov PHP script, so I guess I need to re-register all the subtitles cuePoints every time user seeks to different time…

    XML TText subs do not work with any major FLV player on net (e.g. JWplayer/Flowplayer etc.). So I guess I need to implement it myself :-)

    Thank you very much for any tip & info you want to share!

    Have a great day!

    John

  22. Chris Miller says:

    Hi,

    I am having a problem I wonder if anyone can help with.

    I’ve used the player as so:

    var myMediaData = new MediaData(”videos/”+videoToPlay, “title”, 234, “image.jpg”, vidWidth, vidHeight);
    myFLVPlayer = new FLVPlayer();
    var video:Video = new Video(vidWidth, vidHeight);
    myFLVPlayer.video = video;
    myFLVPlayer.playMedia(myMediaData);
    addChild(video);

    in a function.

    the first time I call the function it plays video A with sizes 640 x 360,
    I then have function which removes the video object
    and re-runs the above function with a new video to play with a new size of: 1024 x 576

    The first video is removed successfully, and the second video is loaded and added to the stage, the problem is, it has the wrong sizes.
    The second video object has the same height and width of the original video object. The actual video on the stage though, has the correct height, but the old width. Seems very strange.

    is there a better to way to play back another video of a different size?

    Many thanks
    Chris

  23. mlegris says:

    @Chris, you need to listen to the event MediaSizeEvent from the FlvPlayer.. so
    [as]
    myFlvPlayer.addEventListener(MediaSizeEvent.SIZE, doMediaSize);

    // then…
    protected function doMediaSize(evt:MediaSizeEvent):void
    {
    // use evt.width & evt.height to adjust your video object.. or force a certain width/height on it
    }
    [/as]

    Otherwise, in FLVPlayer.as on the function “onMedaData” I do this:

    [as]
    if(!willTrigger(MediaSizeEvent.SIZE))
    {
    var yDif:Number = (_video.height - lclHeight)/2;
    _video.y += yDif;
    _video.height = lclHeight;
    }
    [/as]

    which means if the FLVPlayer doesn’t trigger a MediaSizeEvent, there is a default behavior which is probably not what you want at this time..

    Hope this helps.. Martin

  24. mlegris says:

    @all who want a ZIP file..

    it is not hard to copy paste this code somewhere. In the process you will learn things; I am all about learning and understand and not so much about mindless integration of other people’s code.. If you want a zip file, just send me a request by email and I will package it for you.

  25. Justin says:

    Hi. I was greatly appreciate it if you sent me a package of your “Playing FLV video” file. Thanks.

    Justin

  26. plumpNation says:

    Thanks so much for this buddy, I’d written out 80% of this beforehand but you’ve out-eleganced me by miles with these custom events. Really appreciate the tutorial format too, it forces me to read through before the trial and error begins. I read something about over-riding the clone and the toString functions in the custom events, so have done that, but not sure if it is necessary - I know that it’s not always the case. The issue I always had with the NetStream technique was the lack of onComplete when dealing with progressive download. I think you’ve got that sorted though…not there yet.

Leave a Reply