Monday, December 8, 2008

QuickTime Player in Internet Explorer

I've recently been working on getting QuickTime player to work in Internet Explorer (and Firefox and Safari), and as you might expect there are some catches to getting a rich QuickTime UI to work with IE. By rich QuickTime UI, I mean a UI you've built yourself that embeds a QuickTime window. Furthermore, to keep your UI updated to the state of the player, you're using DOM events. I thought I'd do a brain dump to refresh my own memory and potentially help some others. So here we go:

Question 1: Why don't my DOM events work in Internet Explorer?

Answer: They work, but they don't work properly, that's for sure. The Apple documentation provides an example the just doesn't work. QuickTime DOM events won't get sent unless you add a [relatively simple] hack, the essence of which requires you to reload the clip you're playing. Pseudocode looks like this (in javascript):

load clip in QuickTime
wait until plugin status is loaded (or complete )

// begin hack
quicktimeMovie.SetResetPropertiesOnReload(false);
quicktimeMovie.setURL(movieURL);
registerDOMEvents(quicktimeMovie);
// end hack

So essentially, you have to generate your object/embed code, load the quicktime player once (by setting innerHTML somewhere), and then do a setURL with the same clip before registering for DOM Events. If you don't do the setURL, you won't get DOM events.

Note that for other browsers you don't have to do this. So I suggest you wrap this code up in an if(IE) block.

Question 2: With the hack above (in IE), why does my app hang when loading long (15 minutes plus) clips?

Answer: Your app is hanging because the QuickTime plugin didn't get time to stabilize before you called setURL. I didn't find a way around this, but a solid solution is to use a dummy clip (1 or 2 seconds of black) that you load up before loading your real clip. Once you've got DOM events registered, you can use setURL to switch to other clips. Pseudocode looks something like this:

function initQuickTime()
{
[code from answer 1 loading a dummy clip]
}

function loadClip(clip)
{
if(firstLoad)
{
initQuickTime();
}
quicktimeMovie.setURL(clip);
}

And you're good to go. setURL can be used from here on in if you need to switch clips.

Other Notes:

1. You can't resize the QuickTime window without reloading the clip. I really want to be wrong about this, but if you need to change the size of the video window, you have to redo your object/embed code. Kind of a pain, but resizing has to be done almost never, so it's workable.

2. If you're writing debug code, make sure all your test clips are on your http server. I made this mistake and wasted a couple hours. If, for example, you're working my pseudocode in question 2 and your dummy clip is on your PC, but your app accesses clips on an http server somewhere, it just won't work. QuickTime player has some initialization in it that defaults to either local files or http files (I don't really know the details).

That's about it. Overall I really like QuickTime player. Compared to the directshow work I've done, it's a lot easier to use. There are a lot less corner cases you have to deal with (if you're trying to get frame accuracy, for example). The compatibility issues in diffferent browsers come with the turf, and they're realtively easy to deal with elegantly if you know what you're up against.