Question

If you load up a FLVPlayback component in Flash or VideoDisplay in Flex and try to seek to a specific location or set playheadTime to a specific location, the movie always rounds up or down by very large amounts

In flash, drag a FLVPlayback component to stage and set source to http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/examples/assets/phone.flv Then try to video.seek(6) or video.playheadTime = 6;

It will just goto 10. Likewise if you use their built in scrubber the only intervals are 0, 5, or 10. So at most the scrubbing frame you see is 3

Here is an example of flex with the same result.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:media="com.synapsegroup.media.*">

    <mx:Script>
        <![CDATA[
            import mx.events.MetadataEvent;
            import mx.events.SliderEvent;
            import mx.events.VideoEvent;

            protected function scrubber_changeHandler(event:SliderEvent):void
            {               
                trace(event.value);
                video.playheadTime = event.value;
            }

            protected function video_playheadUpdateHandler(event:mx.events.VideoEvent):void
            {               
                //scrubber.value = event.playheadTime;
                //http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/examples/assets/phone.flv
            }

        ]]>
    </mx:Script>

    <mx:Panel>
        <mx:VideoDisplay id="video" source="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/examples/assets/phone.flv" minWidth="200" minHeight="200"
                         autoPlay="false"
                         />
        <mx:ControlBar>
            <mx:Button label="Play" click="video.play();"/>
            <mx:Button label="Stop" click="video.pause();"/>
            <mx:HSlider liveDragging="true" id="scrubber" minimum="0" maximum="11.5" change="scrubber_changeHandler(event)" thumbPress="video.pause();"/>
        </mx:ControlBar>
    </mx:Panel>

</mx:Application>

In both cases if you click play/pause fast enough you can pause on individual frames with much more granularity, but thats not a good UX

Is there something I'm missing to do this programatically?

I'd also say that the interval changes depending on the video length, something that was 3minutes long had 10 second intervals

Was it helpful?

Solution

The documentation for flash mentions that values for seek() are approximate. Part of the reason for this is how video is compressed. It is broken into chunks, with a keyframe, and a set of delta frames, that just contain data about what has changed. In this way, the overall file size for the video is much smaller than having every frame contain every pixel.

However, this also means that you can't just skip to any frame, because many frames do not actually exist. The playhead has to find the closest preceeding keyframe, then play forward from that.

To have a video that can stop and seek to any frame, you have to encode it with a keyframe distance of one. Try that and you will see that you file size is enourmouse, but you can now make it play smoothly backwards.

As for the scrub bar being inexact in seeking, yes. It is. Its kinda sloppy. Boo adobe and all that. But hey have to make a tradeoff between telling the player to seek on every mouse move, which could bog down the player as it computes keframe plus delta for every mouse move, versus actually being able to drag the bar.

Its not brilliant, but you can code your own from a netstream class and set a balance more to you liking. Most of the time I find their balance entirely servicable, even if it would be nice to be able to be more precise.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top