Building a basic controller for the VideoDisplay control

OK, this is probably one of my more elaborate samples on the site so far. It covers a few different areas which I probably haven’t covered (or covered well) up to this point. We look at things like embedding fonts (so we can use the fade effect on a nested text field), embedding images for button skins, and overlaying a simple set of buttons when you move your mouse cursor over a video (which I believe iTunes and many other video players do). Basically it lets you create a nice little video player that gets overlayed on the video so you don’t have additional space taken up by play/pause buttons.

Full code after the jump.

Download source (ZIP, 200K) | View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/08/05/building-a-basic-controller-for-the-videodisplay-control/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white">
 
    <mx:Style>
        @font-face {
            src:url("assets/arial.ttf");
            font-family: Arial;
        }
 
        .timeStyle {
            color: #FFFFFF;
            font-family: Arial;
            font-size: 12;
        }
 
        .playPauseStyle {
            /* play button skins */
            skin: Embed('assets/control_play.png');
            downSkin: Embed('assets/control_play_blue.png');
 
            /* pause button skins */
            selectedUpSkin: Embed('assets/control_pause.png');
            selectedOverSkin: Embed('assets/control_pause.png');
            selectedDownSkin: Embed('assets/control_pause_blue.png');
        }
 
        .stopStyle {
            skin: Embed('assets/control_stop.png');
            downSkin: Embed('assets/control_stop_blue.png');
        }
 
        .controllerStyle {
            bottom: 5;
            left: 5;
            right: 5;
            paddingBottom: 5;
            paddingLeft: 5;
            paddingRight: 5;
            paddingTop: 5;
            alpha: 0;
            background-color: #000000;
            background-alpha: 0.5;
        }
    </mx:Style>
 
    <mx:Script>
        <![CDATA[
            import mx.events.VideoEvent;
 
            private function showControls():void {
                fadeIn.play([controls]);
            }
 
            private function hideControls():void {
                fadeOut.play([controls]);
            }
 
            private function videoDisplay_playheadUpdate(evt:VideoEvent):void {
                var pTime:Date = new Date(videoDisplay.playheadTime * 1000 || 100);
                var tTime:Date = new Date(videoDisplay.totalTime * 1000);
                time.text = dateFormatter.format(pTime) + " / " + dateFormatter.format(tTime);
            }
 
            private function playPauseButton_click(evt:MouseEvent):void {
                if (videoDisplay.playing) {
                    videoDisplay.pause();
                } else {
                    videoDisplay.play();
                }
            }
 
            private function stopButton_click(evt:MouseEvent):void {
                videoDisplay.stop();
            }
        ]]>
    </mx:Script>
 
    <mx:Fade id="fadeIn" alphaFrom="0.0" alphaTo="1.0" />
    <mx:Fade id="fadeOut" alphaFrom="1.0" alphaTo="0.0" />
 
    <mx:DateFormatter id="dateFormatter" formatString="NN:SS" />
 
    <mx:Label text="Mouse over the VideoDisplay control below to show control buttons." />
    <mx:Canvas rollOver="showControls()" rollOut="hideControls()">
        <mx:VideoDisplay id="videoDisplay" source="http://www.helpexamples.com/flash/video/caption_video.flv" autoPlay="false" playheadUpdate="videoDisplay_playheadUpdate(event)" />
        <mx:HBox id="controls" styleName="controllerStyle" alpha="0.0">
            <mx:Button id="playPauseButton" styleName="playPauseStyle" toggle="true" selected="{videoDisplay.playing}" click="playPauseButton_click(event)" />
            <mx:Button id="stopButton" styleName="stopStyle" click="stopButton_click(event)" />
            <mx:Spacer width="100%" />
            <mx:Label id="time" styleName="timeStyle" />
        </mx:HBox>
    </mx:Canvas>
 
</mx:Application>

View source is enabled in the following example.

Icons are from the famfamfam.com “Silk” collection: http://www.famfamfam.com/lab/icons/silk/.

27 thoughts on “Building a basic controller for the VideoDisplay control

  1. Real nice! Code also looks nice and simple. I am just getting started with video. The zip file for source code is invalid. Can you please kindly post a valid zip file?. Thanks.

  2. Rehana Rahman,

    I recreated the project in Flex Builder 3 and reuploaded the files. Let me know if you still have any problems downloading the files.

    Peter

  3. Hi

    I am working in flex Action Script.

    I am able to load video from local drives. but now i need to play a video as my desire time frame. like

    Assume video file is 10 sec long, now i need to play video file from 3 sec to 7 sec.

    i hope u ppl get it.

    and Flex supports other video files formats like *.DAT, *.MPEG etc or it only supports *.FLV file.

    Please have look on this topic

    Thanks in Advance
    Niks

  4. Niks,

    For the 10 second video question… that’s a little tricky. I think the best way to do it (apart from re-editing the videos) would be to embed cue points in the FLV directly. Since I’m not sure if that is possible (and either requires third-party tools such as FLVTool2 (see http://blog.inlet-media.de/flvtool2/) or possibly reencoding the videos and embedding the cue points — at which point you may as well trim the video anyways), you can also create ActionScript cue points dynamically and add them to the video at runtime. This last method (dynamically adding ActionScript cue points) does have its caveats though. ActionScript cue points aren’t exactly accurate, and (I believe) depend on the FLV files keyframe intervals. I made a “simple” example below which should maybe, hopefully, do what you’re looking for, but you can see that it doesn’t always seek exactly to 3 seconds and stop exactly at 7 seconds. It may all just depend on your video and whatever encoding settings were used.

    As for your second question (DAT, MPEG vs FLV). Currently the VideoDisplay (and other video classes such as NetStream, NetConnection, and Video) only support FLV files, to my knowledge. There is currently a Flash Player in beta which will support other formats such as FLV, MP4 and MOV files. For more information, see the following blog posts:
    http://blogs.adobe.com/rgalvan/2007/08/flash_player_will_support_h264.html (Richard Galvan is the technical Product Manager for the Flash Authoring tool)
    http://weblogs.macromedia.com/emmy/archives/2007/08/big_day_for_web.cfm (Emmy Huang is the Product Manager for Adobe Flash Player)
    http://www.kaourantin.net/ (Tinic Uro is an Adobe Flash Player engineer and his site has lots of great, and detailed, information)

    There are probably a lot more posts out there, but those were the first three I found.

    Hopefully that helps. Large code dump below!

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml&quot;
            layout="vertical"
            verticalAlign="middle"
            backgroundColor="white">
    
        <mx:Script>
            <![CDATA[
                import mx.events.ResizeEvent;
                import mx.events.CuePointEvent;
                import mx.events.VideoEvent;
    
                private function videoDisplay_ready(evt:VideoEvent):void {
                    addVideoCuePoints();
                }
    
                private function videoDisplay_resize(evt:ResizeEvent):void {
                    /* Create a reference to the VideoDisplay control on the
                       display list. */
                    var vd:VideoDisplay = VideoDisplay(evt.currentTarget);
                    /* Make sure the VideoDisplay control's total time is
                       numeric. The first time this event is dispatched the
                       value is NaN, but the second time seemingly gets
                       dispatched after the "ready" event, and contains the
                       correct length. */
                    if (!isNaN(vd.totalTime)) {
                        var cuePoint:Object = vd.cuePointManager.getCuePointByName("start");
                        /* Make sure the named cue point was found, otherwise
                           you get an RTE. */
                        if (cuePoint != null) {
                            videoDisplay.playheadTime = cuePoint.time;
                        }
                    }
                }
    
                private function videoDisplay_cuePoint(evt:CuePointEvent):void {
                    switch (evt.cuePointName) {
                        case "start":
                            // do nothing
                            break;
                        case "end":
                            videoDisplay.pause();
                            break;
                    }
                }
    
                private function addVideoCuePoints():void {
                    var cpArr:Array = [];
                    cpArr.push({name:"start", time:3});
                    cpArr.push({name:"end", time:7});
                    /* Add the array of cue points to our video display. */
                    videoDisplay.cuePointManager.setCuePoints(cpArr);
                }
            ]]>
        </mx:Script>
    
        <!-- URL of the video file to load. -->
        <mx:String id="VIDEO_URL">
            <![CDATA[http://www.helpexamples.com/flash/video/caption_video.flv]]>
        </mx:String>
    
        <mx:NumberFormatter id="numberFormatter" precision="3" />
    
        <mx:VideoDisplay id="videoDisplay"
                autoPlay="false"
                source="{VIDEO_URL}"
                cuePointManagerClass="mx.controls.videoClasses.CuePointManager"
                ready="videoDisplay_ready(event);"
                resize="videoDisplay_resize(event);"
                cuePoint="videoDisplay_cuePoint(event);" />
    
        <mx:Label text="total: {numberFormatter.format(videoDisplay.totalTime)}" />
        <mx:Label text="currn: {numberFormatter.format(videoDisplay.playheadTime)}" />
    
        <mx:Button label="play" click="videoDisplay.play();" />
    
    </mx:Application>
    

    Happy Flexing!
    Peter

  5. Hi,

    I am working on VC , I have two problems in my project.
    one is how to automatically play a progress bar control and the other is how to terminate a thread which is used to cal a dialog box containing progress bar control. Indicating a waiting task.
    So please help me in this regard.

    Thanks in advance.

  6. Hi,

    I am working on Visual C , I have two problems in my project.
    one is how to automatically play a progress bar control and the other is how to terminate a thread. Created thread is used to cal a dialog box containing progress bar control, waiting for some task to happen.
    So please help me in this regard.

    Thanks in advance.

  7. Hey Peter — Good articles/blog/stuff. A comment and a question.

    The cuepoint example you give a couple comments up seems to imply that you can use cues as a way to start from the middle of a video. Jumping to the cue point only works if the video is loaded up to that point (or if you’re running a media server, I suppose). If you set the cues in your example to 10 and 17, it just sits at 0.

    While it seems you have moved on from VideoDisplay, I am wondering if there are any techniques or resources for optimizing playback. I’m just playing a single video, but the video and audio chop and jump every so often. The video jump alone wouldn’t be too terrible, but the audio pop makes it really disruptive.

    I’ve bound a couple actions to the playhead position. It’s really light stuff, but that is the only bit of the code that seems immediately suspicious.

    Any suggestion would be tremendously appreciated.

    Thanks,
    rob@fuzzwich.com

  8. May be that’s a most nice video display component. I look may be everithing but only this one is looking perfectly.

    Thank You!

  9. lovely simple and elegant solution, thanx! – i’ll try to make my playhead just as sweet (!) Funny, i had “change ‘skin’ to ‘upSkin’ to display it properly.” as did Tomek (your first commenter)… i *also* need to add overSkin to the styles.

    p.s. i love the famfamfam icons… great to see them here too :)

  10. Hi,
    I was making a player based on yours but i’m facing a problem :
    The files I’m playing are really big (like 30 Mbytes).
    So the player takes some time to load it, wich is not the problem.
    The problem is when I use the player in my HTML page, when a movie is loading, all the other HTML links are useles in my page.
    If I click on a link, it will only “resolve” when the video file has finished loading.
    Whould you have any idea if there was a way of avoiding that?
    Is there a way of detecting if the user is trying to navigate?
    (Sorry for my bad english)
    (Ho and by the way thank you for all those nice examples !)

  11. Hi again,
    Finally I found out where the problem was.
    It had almost nothing to do with the player.
    I was using a php uploading script and had issues with start_session().
    (Basically, when i clicked on a link, the link worked but the php file i was calling was stalling when calling session_start(), probably because my upload script, where i was calling session_start() too, had not completed.)

    Sorry if I gave anny doubts on this player wich works really fine.

  12. Hi,
    I am a newbie to flex world. I have to build a video player something like what you have built. I have just downloaded the code but I couldn’t compile and run it.
    It would be very kind of you, if you send me details about steps to compile it and run it.
    Please include details about folder structure, what command to run to compile it, any environment variable to set. Any steps to importing it in to flex builder

    Thanking you in advance,

    Regards,
    Krishna
    (A newbie to Flex world, but want to learn more within sort time)

  13. Hi

    Excellent blog, always checks this site out before doing anything new in flex.

    I have tried building a videoplayer witch uses the videodisplay component but I cant get the scrubber to work in a good way. I use streaming and FMS and for some reason using the timeheadTime dosent work any good. And I think its becouse of the buffertime being to long and commands being stored.

    anyway I have desided to build my own videodisplay, now what Im wondering is should I build it on the video class or the videoplayer class? What is smartest?

    Many thanks
    /Erik

  14. Hi ,I could successfully run the above video player ………….
    But when I am trying to run videos from my webserver, they are not running.
    I am using XAMPP package and all my flv and swf files are stored inside this :
    ” /…………./drupal/sites/default/files/Untitled.flv ”
    Can anyone tell me how can I play my files .

  15. vinni July 10, 2009 at 11:53 pm
    Hi ,I could successfully run the above video player ………….
    But when I am trying to run videos from my webserver, they are not running.
    I am using XAMPP package and all my flv and swf files are stored inside this :
    “/…………./drupal/sites/default/files/Untitled.flv”
    Can anyone tell me how can I play my files .

    It’s in the Flex code. If you’ve copied and pasted everything correctly, it should be line 85

    <mx:VideoDisplay id="videoDisplay" source="accesscreatingsubform.flv" autoPlay="false" playheadUpdate="videoDisplay_playheadUpdate(event)" />

    The problem that I am having is that it thinks my video is an hour long.

  16. Hello,

    I wanted to add a progress (time) bar to my video, so the user can choose what time of the video he wants to go.
    Just like YouTube has.
    Do you know if that´s possible?

  17. Peter,
    Thanks a lot for your code and sharing.
    I have added the seekbar feature and shared the code below.
    ============================

    @font-face {
    src:url(“assets/arial.ttf”);
    font-family: Arial;
    }

    .timeStyle {
    color: #FFFFFF;
    font-family: Arial;
    font-size: 12;
    }

    .playPauseStyle {
    /* play button skins */
    skin: Embed(‘assets/control_play.png’);
    downSkin: Embed(‘assets/control_play_blue.png’);

    /* pause button skins */
    selectedUpSkin: Embed(‘assets/control_pause.png’);
    selectedOverSkin: Embed(‘assets/control_pause.png’);
    selectedDownSkin: Embed(‘assets/control_pause_blue.png’);
    }

    .stopStyle {
    skin: Embed(‘assets/control_stop.png’);
    downSkin: Embed(‘assets/control_stop_blue.png’);
    }

    .controllerStyle {
    bottom: 5;
    left: 5;
    right: 5;
    paddingBottom: 5;
    paddingLeft: 5;
    paddingRight: 5;
    paddingTop: 5;
    alpha: 0;
    background-color: #000000;
    background-alpha: 0.5;
    }

    ============================

Comments are closed.