Detecting Streaming Media Players and Connection Speed Tutorial - Part One


By Larry Bouthillier, Streaming Media Consultant, eMedia Communications Strategies

(Back to Detecting Streaming Media Players and Connection Speed Tutorial home page)

Wouldn't we all love a world in which all streaming video content could be played with any streaming video player? Sure ... just like any browser can render any HTML page, right? Unfortunately, the reality we deal with is one in which the three major streaming media systems are largely incompatible with each other. What's more, your users will be using a variety of operating systems, browsers, media players, and types of internet connections. One solution to this problem is to choose a single streaming format to support. This can be a good option if you can control the configuration of your viewers' computers, as in many corporate or educational settings. If you can do this, it certainly is a very cost-effective approach.

But if you're like many of us, you'll need to support multiple streaming media formats to make your content easily available to as many users as possible. Well, roll up your sleeves, because we're going to get our hands dirty with some code that will let you determine which players your users have installed, and what bandwidth they have available on their Internet connection to stream your content. Then you can let users choose which of their players they'd like to use to view your content and stream to them a version appropriate for their connection.  In the process, we'll start to lay out the framework for a simple streaming video content management and delivery management system which can provide load balancing, fault tolerance, video search and other advanced streaming media management features.

For now, we'll focus on player detection and user choice. There are three parts to this that we'll cover in a short, weekly series of articles. The solution we'll implement here is illustrated in Figure 1. Flowchart of video detection application

First, we'll use client-side code in the browser to determine which players are installed and what the connection speed is. This example requires no server-side software - it all happens in the browser.  We'll set the results in a browser cookie that our server-side code can read. (detectPlugin.jsp)  

In part two of this series, we'll use that information to offer the users a choice about which player they would prefer to use. This will also be set in a cookie. (selectPlayer.jsp)

Finally, in part three, we'll honor user's choice by generating a metafile (.ram for RealSystem, .asx for WindowsMedia, .smi for QuickTime). This will launch the correct media player and direct it to the server where the content lives. (playVideo.jsp, using PlayerDataObject.java)

All the server-side code for these articles is written in Java/JSP. I've chosen JSP because it's simple, powerful, and available on any platform and for any Web server. Of course, the concepts here could easily be implemented using Perl CGI, ColdFusion, or other server-side Web application environments. The example source code download page includes instructions on how to set up the free Apache Tomcat JSP engine to run the examples.

So, enough of that. Let's get down to business! There are two major approaches required for determining which media players (or other plugins) a user has installed: one for browsers that use plugins and another for browsers that use ActiveX controls.

Browsers that use plugins: Opera, Netscape Navigator/Communicator, IE on Macintosh, and any browser not on Windows

Browsers that use ActiveX: IE on Windows

Let's walk through the client-side code that lets us deal with each of these possibilities. First we'll look at detecting plugins. Listing 1 shows a fragment of JavaScript code that you can place in your HTML page. Browsers store information about the installed plugins in an array of plugin objects that's accessible from JavaScript. First, on Line 15, we double check to see that we are not on IE on Windows. Then, starting on line 18, we begin to check the name of each of the plugins in our plugins array. You'll notice that we have to know exactly what the plugins are named in order to detect them. You can see these by typing "about:plugins" in the Location field of your browser. If we find a match for any plugin, we add a short name for it to our 'playerString' variable (lines 22, 25 and 28).

Once you've checked all the plugins, you'll want to store the results somewhere useful. This is what cookies are made for — storing small bits of data on a user's computer for future use. A cookie is saved with the host site's domain name, so only the site that originated the cookie can read it. This means no other sites can take advantage of the information you're storing here — it's just between you and your user.

So, line 32 calls the setCookie() function, storing the playerString in a cookie named "MediaPlayers." If you don't provide an expiration date for your cookie, it will go away when the user closes the browser. Here, we've arbitrarily chosen to set our cookie to expire in 365 days. If you have all three major media players installed, your playerString will look something like this: "REAL,QT,QT,QT,WMP."   Try it!  Use the links under Client-side only Code Examples.

We don't care about the order of the names here. Yours may vary, depending on the order in which your browser loaded its plugins.  You may also notice that if you use Internet Explorer 5.5 SP2 or 6.x on Windows, you may not see the QuickTime control listed, even though you know you have QuickTime installed.  Microsoft recently discontinued support for browser plugins in these products, in favor of their own proprietary ActiveX control architecture (must be “good for consumers”, huh?).  If you use one of these browsers, or if you've recently updated IE5.5, Apple's QuickTime plugin no longer functions.  To circumvent this change, Apple has released an ActiveX version of the QuickTime player.

Listing 2 lets you do the same thing for users of IE on Windows. Here on lines 21 through 23 we try to create ActiveX instances of each player using VBScript. We simply check to see if each attempt was successful. The same JavaScript functions we used for the plugin example set the cookie value.

Bandwidth Detection

It's possible to detect the bandwidth of an internet connection using Javascript code in the browser.  Let's examine how this detection is done.  The short version is this: get the current time when the page begins to load. Then, load a bunch of data to the page.  Finally, get the time again.  You can see this in the code listings at  Listing 1 on lines 52-66.  

Notice that the data lines (58-60) are not text, but are binary bits put into comment lines.  Using binary data here eliminates two complications.  First, the browser does not try to render and format the text, which keeps the speed of the  your user's computer or browser from becoming as much of a factor affecting the load time for the data.  Secondly, if their modem uses data compression, it will not be applied to streaming video content which is already highly compressed.  The binary data I pasted here is from a highly compressed file (I happened to use a JPG), which will have similar network compression characteristics to streaming video.

Next, we have to do some simple math to get a value in kbps (kilobits per second).  Our calcThroughput() function, on lines 41 through 50, handles this.  Since we provided the block of data, we know the number of kilobits we transferred.  If we subtract the beginning time from the ending time, we also know the number of seconds it took to load.  We simply divide kilobits by seconds to get kbps.  On line 47 we figure in a correction for network overhead (packet headers and the like).  The result is a ballpark estimate of the network bandwidth at the moment this page loaded.  We'll set this information in a cookie, just as we did the player information (line 48).

It's important to note my use of the word "ballpark" here.  There are a few points to keep in mind about this.  Network bandwidth can be very variable.  If the user's connection bandwidth is fluctuating, you'll only get the bandwidth at the moment that this page loads.  If the user is experiencing an unusually low- or high-bandwidth moment due to network traffic (on your end or theirs), you'll have an inaccurate notion of their real capability.  

The other point to remember is that the accuracy of the results is biased towards slower network connections.  If you're connecting on a 28.8 or 56k modem, the 31kBytes of data we're loading will take a few seconds and we'll get good time data from the code.  But if the connection is very fast, the time it takes to load the data may be just a  few milliseconds.  With a load time of just a few milliseconds, we're working with a too small a time sample on which to base our calculations.  It's sort of like measuring inches with an odometer (or is it like measuring miles with a micrometer? Hmmm...).  Anyway. in order to increase the accuracy at high bandwidths, we'd have to make the data block much larger.   But....it turns out we really don't have to.  Think of it – you will probably want to treat users on a 28.8 connection differently from those on a 56k, 128k ISDN, or 600k cable modem connection.  But for video streaming, it's less likely to be critical to know whether your users are on, say, a 1Mbps, 10Mbps or 100Mbps connection.

Now you've got some working code that can detect the presence of the three major media players, and the speed of your users' network connection.  Unfortunately, you have different player detection code for different browser and platform combinations. Our solution will be to detect the user's browser and platform at the server — before sending this code. Then we'll respond with the correct code for the user's environment. Stay tuned — in next week's installment we'll move to the server-side and walk through the code that handles this. We'll also examine the code that will read the cookies we've set here. Then, we'll let our users make their own choice about which player they want to use. See you next week!