Scrubbing an FLV using the VideoDisplay control and a slider

In yet *another* post about the VideoDisplay control, this time we look at formatting playback times using the DateFormatter class/tag, creating a basic scrubber using an HSlider control, and applying a mildly annoying Zoom effect to the video.

Also, we tweak the slider control (or more accurately HSlider) and prevent users from clicking on the slider track (thanks to the allowTrackClick property, we set the liveDragging property to false to make sure we arent needlessly seeking around the video every time the slider thumb moves, and finally we invert the thumb arrow for no other reason than I didn’t know you could do that so easily.

Oh, and I also created a faux looping video by using the autoRewind property, and calling the play() method in the rewind event handler.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="top" backgroundColor="white">

    <mx:Script>
        <![CDATA[
            private function formatTime(item:Date):String {
                return dateFormatter.format(item);
            }

            private function videoDisplay_playheadUpdate():void {
                /* If playhead time is 0, set to 100ms so the DateFormatter doesnt return an empty string. */
                var pT:Number = videoDisplay.playheadTime || 0.1;
                var tT:Number = videoDisplay.totalTime;

                /* Convert playheadTime and totalTime from seconds to milliseconds and create new Date objects. */
                var pTimeMS:Date = new Date(pT * 1000);
                var tTimeMS:Date = new Date(tT * 1000);

                timeLabel.text = formatTime(pTimeMS) + " / " + formatTime(tTimeMS);
            }

            private function slider_thumbPress():void {
                videoDisplay.pause();
            }

            private function slider_thumbRelease():void {
                videoDisplay.playheadTime = slider.value;
                videoDisplay.play();
            }

            private function videoDisplay_ready():void {
                videoDisplay.visible = true;
                controlBar.visible = true;
            }
        ]]>
    </mx:Script>

    <!-- Only show minutes and seconds. -->
    <mx:DateFormatter id="dateFormatter" formatString="NN:SS" />

    <mx:Zoom id="zoom" />

    <mx:Panel title="{videoDisplay.source.split('/').pop()} ({videoDisplay.state})">
        <mx:VideoDisplay id="videoDisplay" visible="false" showEffect="{zoom}"
            playheadUpdate="videoDisplay_playheadUpdate()"
            ready="videoDisplay_ready()"
            rewind="videoDisplay.play()"
            source="http://www.helpexamples.com/flash/video/cuepoints.flv" />

        <mx:ControlBar id="controlBar" visible="false">
            <mx:HSlider id="slider" width="100%"
                allowTrackClick="false"
                invertThumbDirection="true"
                liveDragging="false"
                maximum="{videoDisplay.totalTime}"
                minimum="0"
                thumbPress="slider_thumbPress()"
                thumbRelease="slider_thumbRelease()"
                tickInterval="1"
                value="{videoDisplay.playheadTime}" />
            <mx:Label id="timeLabel" textAlign="right" />
        </mx:ControlBar>
    </mx:Panel>

</mx:Application>

View source enabled in the following example.

13 thoughts on “Scrubbing an FLV using the VideoDisplay control and a slider

  1. Sorry for the audio, it would appear my speakers were muted while I was building this. I’ll mute the audio stream in the FLV and republish the SWF when I get home.

    Update @ 8:23pm :: Fixed, volume muted.

  2. Player is great! Quick question. How hard do you think it would be to capture the playhead time into an xml file for captions?
    Thanks!

  3. SMackhead,

    It shouldn’t be hard at all. The only trick would be you would need to send the data to a server-side script to write out the XML data to a file remotely. Due to security reasons, Flash Player cannot create files on a user’s machine (unless you’re creating an Adobe AIR project).

    Peter

  4. Nice player!
    One question, though. What if I actually WANT “liveDragging”, meaning that I could scrub through the vid getting an update on what is to be seen while I´m dragging the thumb?

    I thought adding something like this should do the trick… but it doesn’t :(

    private function slider_thumbPress():void
    {
        videoDisplay.pause();
    }
    
    private function slider_thumbDrag():void
    {
        videoDisplay.playheadTime = slider.value;
    }
    
    private function slider_thumbRelease():void {
        videoDisplay.play();
    }
    

    and

    Any Ideas? The thumb just gets stuck at the first half of the flv and doesn’t move any more while the flv stops.

  5. SaltamonteZ,

    Are you sure the entire video has loaded? I assume you can’t scrub past a point in a video if it hasn’t loaded yet.

    Peter

  6. Hey peterd ,

    It has defects?

    I slidered the thumb on right, and I saw the title have updated to “cuepoints.flv(seeking)”. but the video doesn’t play anymore, it was stuck there.

    Any suggestion?

    Cheers

  7. Hi peter,

    Thanx for all the examples, great work!

    Regarding the scrubber, I noticed that after the slider_thumbRelease the slider jumps for a second back to the original slider_thumbPress position. How can this be avoided?
    …when I do a ‘trace(videoDisplay.playheadTime) after videoDisplay.playheadTime = slider.value in the slider_thumbRelease method, I get the time of the original location and NOT the new location.

    thanks again

  8. Hi Sam,
    the strange slider movement could be avoided.
    Put the following line

    slider.value = videoDisplay.playheadTime;
    

    as last line into the function:

    private function videoDisplay_playheadUpdate():void {
    

    and remove (delete)

    value="{videoDisplay.playheadTime}"
    

    from the attributes of HSlider slider in the MXML part.

    Thats it.

    Btw.: Thank you Peter for this nice example.

  9. Hi Peter,

    Thanks for the examples. Just playing around with it..

    The video time display is incorrect though. Since Flex creates new dates in the local time zone, if your timezone is not GMT, you will get incorrect time display. (It shows 30:01 for me instead of 00:01 since I am in GMT+530).

    Here’s a fix for that:

    In the videoDisplay_playheadUpdate() function:

    var tzOffset:Date = new Date();
    // This takes it one day in future minus the time zone offset
    var tzDiff:Number = (86400 - tzOffset.getTimezoneOffset()*60) *1000;
    var pTimeMS:Date = new Date(pT * 1000 + tzDiff);
    var tTimeMS:Date = new Date(tT * 1000 + tzDiff);
    

    HTH.

    :Nirav

  10. Nice example. I would like to make the slider move more smoothly as the video plays. Messing with the playheadUpdateInterval never gets it right. Does anyone know of any tricks people have done to make the scrollbar smoother?

  11. Hey petered this is a real nice example.
    I figured Out how to make the slider show the correct time (min, sec) when forwarding or rewinding the videos.

    Here is what you need to do.

    Create a function to handle the conversion.

    private function timeConversion(item:Object):String{
    var pT:Number = item.valueOf() || 0.1;
    var pTimeMS:Date = new Date(pT * 1000);

    return formatTime(pTimeMS);

    }

    add the following line to your HSlider component.
    dataTipFormatFunction=”timeConversion”

    Hope it Helps.

  12. Hello please urgent im playing 1:33:50 mins video it shows 12:33:50 for me instead of 00:00:01 since I am in GMT+530…
    Please Help me…

  13. Hi Guys!

    Great post I must say.

    I was just wondering if there is a way to increase granularity on Ms VideoDisplay control? Let’s say I want live dragging but I want it to update its playhead time in milliseconds instead of seconds? It passe 30 frames in 1 second which is not really live dragging :)

    Thanks.

Comments are closed.