LANGUAGES: C# | HTML
ASP.NET VERSIONS: 1.x
STREAMING MEDIA
Stream Audio and Video from your ASP.NET Web Site
ASP.NET doesn’t provide any specific way to play music or video in your Web applications,
but that doesn’t mean there aren’t any options. For example, the following HTML,
when embedded anywhere in an HTML page, will play a background song for visitors:
<bgsound SRC="SomeSong.mp3" loop="0"
balance="0" volume="0">
As you might guess by looking at the definition, there are a few options for adjusting
the volume, balance, and number of times the song will be played. Static snippets
of HTML like this are sure handy sometimes, but it would be even better if there
were a Web control that would encapsulate the dynamic rendering of such HTML at
run time, and perhaps even provide a basic UI so users can control the playback
of the music.
Audio Control
The basic framework for the control is shown in Figure 1. This standard custom Web
control code should look familiar to you if you’ve been reading this column regularly;
all custom Web controls start out similarly.
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Text;
namespace MediaPlayers
{
[ToolboxData("<{0}:Audio runat=server></{0}:Audio>")]
public
class Audio : System.Web.UI.Control
{
//Properties
go here
protected
override void
Render(HtmlTextWriter output)
{
//Custom rendering
goes here
output.Write(“Test”);
}
}
}
Figure 1: All custom Web controls start with a shell similar
to this.
The four properties of this custom control will mirror
the attributes available for the <bgsound> tag: Volume,
prefix="ST1" ?>Loop
, Balance, and FileName. Two of the properties are listed in Figure 2;
the rest can be downloaded from the code that accompanies this article (see end
of article for download details).
private
string _fileName = "";
private int
_Volume = 0;
[Bindable(true),
Category("Appearance"),
Description("URL to a sound file"),
Editor(typeof(System.Web.UI.Design.UrlEditor),
typeof(System.Drawing.Design.UITypeEditor))]
public string
Filename
{
get {
return _fileName;
}
set {
_fileName = value; }
}
[Bindable(true),
Category("Appearance"),
Description("-10000=mute,
0=full volume (default)")]
public int
Volume
{
get
{
return
_Volume;
}
set
{
if
(value>=-10000 &&
value<=0) _Volume= value;
else
throw new ArgumentException
("Volume must be between -1000 and
0");
}
}
Figure 2: The FileName property
has special attributes for improved design time support in the properties window,
and the Volume property throws an exception if an invalid value is set.
First, two private variables are declared to hold the property
values. Next, the FileName property is defined along with several useful attributes
to improve design time support in the properties window. (Note that some of these
attributes will cause a compilation error until you add a project reference to the
System.Design.dll.) When a developer uses this control on their Web form at design
time, an ellipsis button will appear for the property. When clicked, it displays
the dialog box shown in Figure 3 to assist in the selection of
a file.

Figure 3: The FileName
property provides a special design time editor to make it easy for developers to
select a file.
The full code also provides a few more properties for setting
the visibility of the three button controls that will allow the user to play, stop,
and display information about the current track. These three buttons will be the
only user interface visible to the end user at run time, or they can all be set
as invisible if the developer prefers to control the playback entirely through code.
Figure 4 shows the control in action on a Web page that provides
a list of songs for the end user to play on demand. The buttons use client-side
JavaScript to interact with the <bgsound> element of the Web page, so the
music can be started and stopped without posting back to the server.

Figure 4: The audio control
can be dropped onto any Web form to easily spice it up with music and other sounds.
The Render method listed in Figure 5 examines
the properties of the controls and generates the BGSOUND HTML that will be rendered
to the page. The GenerateButtons procedure creates the HTML for the Play, Stop,
and Info buttons. Images could have been used for the symbols, but using the WebDings
font is a more efficient approach.
protected override void Render(HtmlTextWriter
output)
{
StringBuilder sb = new
StringBuilder("<BGSOUND ");
sb.Append("id='"+ this.ClientID
+ "' ");
sb.Append("name='"+ this.ClientID
+ "' ");
sb.Append("SRC='"+ _fileName + "' ");
sb.Append("VOLUME='" + _Volume.ToString() + "' ");
sb.Append("BALANCE='" + _Balance.ToString() + "' ");
sb.Append("LOOP='" + _Loop.ToString() + "' ");
sb.Append("/>");
GenerateButtons(sb);
output.Write(sb.ToString());
}
private StringBuilder GenerateButtons(StringBuilder
sb)
{
string TempID = "BG"+
this.ClientID;
sb.Append("<script language=javascript>var " +
TempID + "=document.getElementById('"+
this.ClientID
+ "');</script>");
if (PlayButtonVisible)
{
sb.Append("<INPUT
type='button' ");
sb.Append("style='font-family:Webdings;'
value='4' ");
sb.Append("title='Play'
onClick=\""+ TempID +
".src='"+ _fileName + "'\">");
}
if (StopButtonVisible)
{
sb.Append("<INPUT
type='button' ");
sb.Append("style='font-family:Webdings;'
value='<' ");
sb.Append("title='Stop'
onClick=" + TempID + ".src=''>");
}
if (InfoButtonVisible)
{
sb.Append("<INPUT
type='button' ");
sb.Append("style='font-family:Webdings;'
value='i' ");
sb.Append("title='Info'
onClick='alert(" +
TempID + ".src)'>");
}
return sb;
}
Figure 5: The final rendering code
examines the control properties to dynamically create the appropriate <bgsound>
tag along with some buttons to allow the end user to control playback.
The Audio control turns out to be fairly robust,
considering it’s doing little more than encapsulating a basic HTML tag. Certainly,
it’s a useful way to quickly and easily get some tunes playing on a Web page. However,
it does have some significant limitations if you want to get some really fancy multimedia
interactivity going on.
Here are some features reasonable developers (and
users) might want that are simply impossible to implement using the preceding approach:
- Fancier controls, such as fast forward and
rewind.
- Support for video playback.
- Buffering, so large media files can start
playing without having to wait for the entire media file to download.
- A friendly and familiar user interface, such
as that of Windows Media Player.
The following approach solves all of these problems.
Video Control
Windows Media Player certainly is a leader in
the field of media playback; it provides rich support for many media file types
and it provides an experience with which most users are already quite familiar.
By embedding the Windows Media Player ActiveX control in an HTML page, you can harness
this power. The required HTML (listed in Figure 6) is not entirely
unlike the <bgsound> tag used earlier in the article, although there are quite
a few more options at your disposal.
<OBJECT ID="Player"
CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"
VIEWASTEXT>
<PARAM
name="autoStart" value="True">
<PARAM name="URL" value="SomeMediaFile.mpg">
<PARAM name="rate" value="1">
<PARAM name="balance" value="0">
<PARAM name="enabled" value="true">
<PARAM name="enabledContextMenu" value="true">
<PARAM name="fullScreen" value="false">
<PARAM name="playCount" value="1">
<PARAM name="volume" value="100">
</OBJECT>
Figure 6: By embedding the Windows Media Player
ActiveX control in a Web page with HTML such as this, you can provide robust audio
and video playback capabilities — as long as your users have a recent version of
Windows Media Player and they accept the standard ActiveX security warning.
Of course, this code requires end users to have a recent version of Windows Media
Player installed, and they may need to accept the standard ActiveX security warning
displayed by Internet Explorer.
(advertisement)
This ActiveX control handles streaming and buffering intelligently, so the media
file will start playing as soon as is practical, even before the entire media file
has been downloaded.
As with the <bgsound> example at the beginning of the article, the HTML snippet
shown in Figure 6 is quite useful — but it’s not very reusable. The rest of this
article describes a new custom Web control, similar to the audio control outlined
in the first half of this article. The main difference is that this new control
will encapsulate the options available with the Media Player ActiveX control instead
of the more simplistic <bgsound> tag.
This control (as well as all custom Web controls) starts with a basic template similar
to that shown in Figure 1. The properties for this new control do little more than
hold values for the parameters in Figure 6 and enforce valid values.
The only thing unique about this control is the HTML that it generates. This HTML
is generated from within the overridden Render event, which is listed in Figure
7
.
//output begin object tag
StringBuilder sb = new StringBuilder("<OBJECT ID='" +
this.ClientID + "'
name='"+ this.ClientID + "' " +
"CLASSID='CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6'"
+
"VIEWASTEXT" +
"height="+_Height + " " + "width="+_Width +
">");
//Render properties
as object parameters
sb.Append("<PARAM name='URL'
value='"+
_fileName + "'>");
sb.Append("<PARAM name='AutoStart'
value='"+
_autoStart.ToString() + "'>");
sb.Append("<PARAM name='balance'
value='"+
_Balance + "'>");
sb.Append("<PARAM name='enabled'
value='"+
_Enabled.ToString() + "'>");
sb.Append("<PARAM name='fullScreen'
value='"+
_fullScreen.ToString() + "'>");
sb.Append("<PARAM name='playCount'
value='"+
_Loop.ToString() + "'>");
sb.Append("<PARAM name='volume'
value='"+
_Volume + "'>");
sb.Append("<PARAM name='rate'
value='"+
_Rate + "'>");
sb.Append("<PARAM name='StretchToFit'
value='"+
_stretchToFit.ToString() + "'>");
sb.Append("<PARAM name='enabledContextMenu'
value='" +
_enableContextMenu.ToString() + "'>");
//Determine
visibility
if (_Invisible)
{
sb.Append("<PARAM name='uiMode'");
sb.Append(" value='invisible'>");
}
else
{
if (_buttonsVisible)
{
sb.Append("<PARAM name='uiMode'");
sb.Append(" value='full'>");
}
else
{
sb.Append("<PARAM name='uiMode'");
sb.Append(" value='none'>");
}
}
//output ending
object tag
sb.Append("</OBJECT>");
//flush everything
to the output stream
output.Write(sb.ToString());
Figure 7: This code from the Render event of the new video-capable
custom Web control transforms property values into HTML similar to that of Figure
6.
The code
starts by using a StringBuilder to concatenate the opening <OBJECT > tag,
then it uses its properties to generate <PARAM> tags similar to those shown
in Figure 6. The determine visibility code block simplifies some of the options
in the ActiveX control to modify the visibility of various parts of the control.
Finally, the ending </OBJECT> tag is rendered and the final HTML string is
flushed to the output stream. Figure 8 shows the control in action.

Figure 8: By harnessing the power of Windows Media Player
in a Web page you can give your users memorable experiences.
This
custom media control, which essentially encapsulates the Windows MediaPlayer ActiveX
control, can have its properties set at design time or run time. At run time you
might have some code in a Web form’s code-behind file that looks like this:
MediaPlayer1.Filename="SomeMediaFile.avi”;
//URL
MediaPlayer1.autoStart=true; //start playing upon page
load
MediaPlayer1.ButtonsVisible=true; //play control buttons
MediaPlayer1.EnableContextMenu=true; //right-click menu
MediaPlayer1.fullScreen=false;
MediaPlayer1.Invisible=false; //true=no UI but it still
plays
MediaPlayer1.Volume=100; //0 = mute, 100 = full blast
The Filename property accepts any publicly accessible URL
to a media file. Alternatively, you could point it to a custom Web page that outputs
a media file from a secured directory. Such a page might use the Response.WriteFile
method to provide authenticated access to media.
One deficiency you may have noticed with both controls
in this article is that they stop playing when the user navigates to another page
in your Web site, which you may or may not want. If your requirements state that
the music should keep playing throughout the user’s visit at your Web site, then
the most common solution is to use frames. That is, host the music control in one
frame and have page navigation occur in a different frame. However, frames can be
a bit of a pain in ASP.NET (often requiring copious amounts of client-side code),
so venture into this territory at your own risk.
Full Throttle
This article only scrapes the surface of the multimedia capabilities at your disposal.
Add some authentication and payment processing and you’ve got yourself an online
music and video store (just be sure you’ve got legal rights to sell the media; you
may have noticed record companies are getting mighty uptight about this kind of
thing lately!).
I suggest you download the Windows Media SDK if you want to delve deeper into the
possibilities. The documentation is thorough, and will likely answer many of the
questions that may be lingering in the back of your mind. Using the Windows Media
SDK, you can create media player skins and new codecs, and you can even create online
stores and other Web sites that appear embedded within Windows Media Player.
Beware: Streaming media tends to eat large amounts of bandwidth, so if your goal
is to create a streaming media Web site with any significant amount of scalability,
you’re going to need fat pipes to go along with beefy servers. Needless to say,
this all adds up to a significant financial investment. Also keep in mind that some
media formats are more demanding than others. For example, midi files are quick
and tiny; video files tend to be the bulkiest.
You should now have enough information at your disposal to create dazzling multimedia
experiences for your Web site’s users. Impress them, but try not to annoy them with
unwanted noise. One of the best things about having a media control on a Web page
is that it allows you to suggest a musical overture that matches your Web site’s
ambiance, but at the same time allows the user to take control of the experience
in case they’re just not in the mood.
If you like this control then perhaps you'll also find my QuickTime
Player or Flash Player controls useful as well.
The sample code in this article is available for
download.
This article was originally published in
ASP.NET Pro Magazine.