Wednesday, February 4, 2009

Stopping FLVPlayback's Progressive Download

Ran across a pesky problem in one of the websites I have been burning the midnight oil on. Basically the site has 6 main pages, one of which contains a video gallery. Everything was working just fine and dandy. Then we decided to add a "trailer" on the homepage to welcome users to the site. This page also worked fine and dandy... until I clicked on the video gallery. The addition of this trailer on the homepage prevented the movies in the gallery from playing for a few minutes. Damn it.

Is the movie still playing after you leave the home page? Maybe the gallery is not playing until the trailer is finished. I went back and triple ensured the trailer was stopped on page exit... it did not help, there was still a delay. ugh.

Well maybe the trailer is still loading even though it is stopped since it is a progressive download. That makes sense, and the time it takes to load is about the time these videos are waiting to play in the movie gallery. This makes more sense to me... Flash should be able to play two videos at once anyways. Not sure what I was thinking above.

Ok, no biggie. I will just remove the flv from the stage and set it to null and let the garbage handler take it... NOPE, not so easy. That probably wasn't the best idea in hind sight since the garbage handler only runs when it feels like it. Plus, since the video is still loading there could be a reference somewhere keeping it from being collected.

Hmmm. Lets crack open the API. flvPlayBack.closeVideoPlayer(activeVideoPlayerIndex). Perfect! That should do the trick..... NOPE AGAIN. Had I read the fine print I would have realized that this only works when you have multiple videos in the flvPlayback. You can't close the default index, it will throw an error (which it did). Well crap.

With some digging, however, you can close the VideoPlayer if you have direct access to it. In order to gain access you need to call: flvPlayback.getVideoPlayer(activeVideoPlayerIndex). Once you have the videoPlayer you can call videoPlayer.close(). Viola! The stream is closed and the video gallery can start immediately upon opening. Perfecto!

One thing to note: Check the Flv's source to make sure it is not an empty string before you get the video player. If the flv's source has not been set then getVideoPlayer() will throw an error.

Hopefully someone finds this helpful and saves them time. Sorry for the long-windedness of the article... I could have explained the solution in one paragraph but I tend to learn better through mistakes (as you can see). Hopefully including the logic, or lack of logic, is a good learning tool.

22 comments:

Tink said...

I would suggest a try and catch when using getVideoPlayer().

Also on a side note you can invoke garbage collection with System.gc().

Ickydime said...

Hey Tink, thanks for the post.

Good advice on the invoke garbage collection. I had read they added that feature in the 9.0.115, but hadn't tested it. Will have to check that out.

As for the try, catch. I usually try to stay away from those. I was under the impression they were slower. (altho in hindsight, this call is only going to happen when they leave the page, so a few milliseconds are not going to change anything). I guess try catch is cleaner and prevents me from forgetting to check for an unknown cases. What are your thoughts?

Appreciate the feedback Tink

maliboo said...

I supppose, that most users don't have debug-player? ;)

--
public static function gc():void
Language Version: ActionScript 3.0
Runtime Versions: AIR 1.0 Flash Player 9.0.115.0

Forces the garbage collection process.

For the Flash Player debugger version and AIR applications only.

Ickydime said...

Great catch maliboo! Fine print will get you every time ;)

maliboo said...

But.. You can always count on National Guard;)

http://blogs.eyepartner.com/adrian/flex/flex-tip-6-garbage-collection-in-flex/

Anonymous said...

Hi,

I've been trying to use the code you provided in order to stop the FLVPlayback on a video.
The actual FLVPlayback Component is placed in another swf, but the navigation buttons, however, are placed in the main page that loads the video component page.

So my question is, "where" to do i put the script? And how do i set the FLV's source?

The problem i'm encountering is that if i click on another navigation button, the video's sound continues to play in the background...

Thanx in advance.

Ickydime said...

This post is about stopping a video from downloading... not playing.

But to stop your flvPlayback from playing, you just need to call "stop". And to set the source you can either call flvPlayback.source = "source" or if you could set it when you started playing: flvPlayback.play("source");

The easiest way for your navigation to reach this flvPlayback that is housed in another swf is by making the flvPlayback a public variable. If you make it public and your swf is called "videoHolder" then you would just call something like this: videoHolder.flvPlayback.stop().

And you should be good to go.

Igghera said...

I love you! :-*

Anonymous said...

Thanks a lot- I was close to the solution, but this post gave me the last step.

Chip Lay said...

I have a swf with two flv playback components on stage - one is the main movie - the second is a Picture-in-picture type effect that shows a second smaller movie while the first is paused. I don't want to close out the first clip, because the user will return to the same spot once the second clip finishes. My issue is the same though - if the first movie is still downloading, the second wont start to download until the first finishes.

So my question: Is it possible to switch download priority? But the first video on hold and focus bandwidth resources on the second?

www.pogo-i.com/fedexkinkos/

Thanks!

Ickydime said...

@Chip-Lay
That is a tricky situation. I don't see anything in the API that would allow that... however, that doesn't mean its not there.

I can think of 2 hacks though.
1. load your small videos first in your pre-loader. I don't know how many videos you have or if this even makes sense... If the user doesn't have to view the small ones it wouldn't make sense to force them to download it...

2. sooo hack number 2. Even if you close your stream, I am wondering if the browser would cache the video for you. You could close the stream and save the position and then restart the stream and seek to the position once the video was done. If closing the stream sets the video to black, you could always grab the pixels out of the video and drop the image there. Hack-tastic, for sure. But it could achieve the result you are looking for.

Chip Lay said...

Thanks for the ideas! I think #1 is probably out of the question with the number of small video options. But #2 is interesting - I'll have to give that a shot and see what happens. I have no idea how to "grab" the pixels out of the video and the other issue could be seeing back to the same spot - I have a feeling flv keyframes will come into play, but we shall see. Thanks again!

Anonymous said...

After 2 hours of research, I finally found an answer. Thanks greatly!! Glad you posted this.

Flv Player said...

Thank you for given this nice post....

panofish said...

I have been trying to stop the progressive download for my flvplayback video, but I can't seem to get your suggested code to work.
Here is the AS3 code I have tried, but the video still buffers?
Any help would be awesome!

var temp = myvideo.getVideoPlayer(0);
temp.close();

Ickydime said...

@panofish

The code looks good at first glance.

I feel as though something outside of those two lines must be misplaced.

Some things to consider:
When you trace myvideo, is it the correct FLVPlayback?

When you trace temp, is it a video player?

Are you using multiple videos or multiple FLVPlayers?

Do you change the source or load any new videos after you call the close? (that would restart the buffer automatically)

Hopefully one of those questions helps you narrow down the hiccup.

panofish said...

Thanks Ickydime, but I'm not having any luck. I put my fla and flv file into a zip so you (and anyone else interested) could see my simple code and maybe it will be easier to debug. http://www.panofish.net/pics/video.zip

Ickydime said...

I think it has something to do with you trying to close it immediately. You may want to play around with waiting 1 frame or a certain amount of time.

I added the following:
setTimeout(temp.close, 5* 1000);

This made it close after 5 seconds. However, you can't play it again until you set the source.

This helps if you are changing sources and don't want the previous source to be buffering while you the user is waiting on the next source.

However, if you just don't want the video to be downloading until the user hits play... then don't set a source. Leave the component inspector's source as blank. You can fake it so that it appears to be ready to play by taking the first frame of the video and overlaying it on top of the video... similar to the play button you have now.

Hope that helps.

panofish said...

Just thought I'd update you on what I did to solve my problem. I gave up trying to control my blog video with my own flash swf. I discovered that site I use to host my videos has a decent flash player which doesn't halts the progressive download until you press play. My blog pages with multiple video clips now loads much faster. See for yourself at http://www.panofish.net THANKS for your help!

chad said...

You said: "The easiest way for your navigation to reach this flvPlayback that is housed in another swf is by making the flvPlayback a public variable. If you make it public and your swf is called "videoHolder" then you would just call something like this: videoHolder.flvPlayback.stop()."

Can you give more details on this?
I did not think it was possible to access a loaded swf by using the swf name. Also what would the declaration of the public property look like?

mdchase said...

A favorite trick of mine to kill a buffering video is to tell the player to load (not play) a very tiny dummy .flv file. The one I use is around 8k.

Jason Frazier said...

Hey Mark,

Just read your article on stopping the progressive FLVPlayback download ---- I tried to do as you suggested, but was unable to get it to work for my situation...

I have a site up at:

http://www.jasonfrazier.net

Only one of the sections, REEL, contains a video clip. When you naviagte AWAY from that section, I'd like the video stream to be killed.

The is one main INDEX.fla ---- and a UI Loader loads in all of the sections (ABOUT, REEL, etc.) from external SWFs. The FLVPlayback component for the video is inside the reel.fla file.

You can see the site files here:

http://ww.jasonfraziercreativedesign.com/outbox/site_files.zip

Where should I put the AS to get this to function properly?

Thanks for any help or insight,
Jason :)