Easily manage streaming-media servers
Many users routinely stream audio and video content over the Internet, but few administrators have managed streaming-media servers. With the release of Windows Server 2003, Microsoft Windows Media Services (WMS) has been revamped to make it easier to administer and use. It's so easy, in fact, that companies both large and small are now beginning to stream training videos, company meetings, daily briefings, and other content. This type of content distribution to the workforce has resulted in large cost savings and a more productive workforce. To improve productivity even further, you can use Perl scripts to manage WMS.
For those of you who aren't familiar with streaming media and WMS, let me introduce them to you. Then I'll show you how to write scripts that retrieve WMS information and manage WMS.
What Is Streaming Media?
Streaming media is audio, video, or data delivered over a network in real time. You can broadcast the content or deliver it on demand.
Streamed broadcasts. Streamed broadcasts are like a cable television broadcast. When you want to watch your favorite show, you tune your TV or cable box to the particular station and you begin to receive the broadcast almost instantly. You don't have to wait a long time to download the broadcast to disk first; it simply plays while you receive the data.
The real-time nature of streaming media makes it ideal for sharing presentations (e.g., concerts, news events, speeches) over a network. The presentations might or might not be live, but they're considered to be a shared experience. Just as with a cable television broadcast, a streamed broadcast can be viewed by multiple people at the same time. Therefore, all viewers observe the same content at the same time.
Many online radio stations and music services have eagerly taken advantage of streamed broadcasts to provide music, talk shows, or other types of content. Other types of businesses have also been leveraging streamed broadcasts to cut costs and provide useful media solutions to employees. For example, instead of flying in employees from various regional offices around the world and putting them in hotels for a conference or meeting, many companies are streaming such events over a secured corporate network or even over the Internet.
On-demand streams. If watching a streamed broadcast is like watching a cable television show, then watching an on-demand stream is like watching a DVD movie. You can watch an on-demand stream whenever you want and in whatever way you want. For example, you can pause playback so that you can get up and take a break.
Some companies use on-demand streams for training classes. Scheduling everyone to meet in a class at the same time for specialized training can be difficult, so it makes sense to let employees view the content when they can. Thus, they can view the training not only during business hours but also after hours and on weekends. And because the training is on demand, users can pause the training to answer the phone, stop the training to get some lunch, rewind to hear a confusing section again, and even speed up playback of slow-paced content.
In WMS, there's a new feature called FastCache that enables on-demand streaming that's faster than real time. With FastCache streaming, the client cache receives content to disk while that content is playing. Because the receive rate is faster than the playback rate, you might end up caching the entire content before you've finished playing it. In this case, the remainder of the content plays back from the disk cache. There's no longer any content flowing from the server, even if you pause, play, or rewind.
What Is WMS?
As part of the Windows 2003 platform, WMS (also known as the WMS 9 Series) offers an easy-to-use interface coupled with a powerful streaming-media server. In contrast to its predecessor (WMS 4.1, which shipped with Windows 2000 Server), the WMS 9 Series is easier to use, more flexible, and scales far better.
The version of WMS that comes with Windows 2003, Standard Edition, differs from the version that comes with Windows 2003, Enterprise Edition. The enterprise version of WMS provides more features, such as event scripting plug-in support. Regardless of which version you use, you can still use Perl to interact with WMS.
All the Windows Media tools you need to create, distribute, and play audio and video content are free and easily accessible. You create content with tools such as Windows Movie Maker and Windows Media Encoder. After you create the content, you use WMS to distribute it directly to a player or to another server (for purposes of distribution). Alternatively, you can receive a live broadcast from an encoder and distribute that broadcast to servers and players. You use Windows Media Player (WMP) to receive and render the content. The entire system is available without the need to purchase additional licenses per stream. For more details about the various Windows Media tools, go to http://www.windowsmedia.com.
The WMS 9 Series software development kit (SDK) contains everything you need to start writing code that interacts with WMS. The SDK is available on the Microsoft Developer Network (MSDN) Web site at http:// msdn.microsoft.com/library/en-us/wmsrvsdk/htm/aboutwindowsmediasdk.asp.
The most important thing a WMS scripter needs to know is how to get started. When using Perl, you need to begin by including the code that Listing 1 shows in your script. This code first loads the Win32::OLE extension so that the script can use COM. The code then loads the WMS type library so that the script has access to WMS constant values. Finally, the code at callout A in Listing 1 creates a connection to WMS. When this code runs, the $Server variable represents the IWMSServer interface, which is the entry point into the WMS server. The various properties and methods of the IWMSServer object let you retrieve information about the WMS server and manage WMS. (You can find details about the various methods and properties that this interface provides at http://msdn.microsoft.com/library/en-us/wmsrvsdk/htm/iwmsserverobject.asp.)
Note that the code at callout A works only when your user account has permissions to act as a WMS administrator and when the script is running on the same local Windows 2003 server as WMS. If you need to connect to WMS on a remote Windows 2003 server, you can use Distributed COM (DCOM). You also need to delete the code at callout A and uncomment the code that callout B shows. The $Machine variable can be the remote WMS server's name, DNS name, or IP address. Because the code at callout B works for local machines as well as remote machines, it's the code I use in my Perl scripts. Note, however, that you'll need to define the $Machine variable so that it points to your local machine.
Obtaining WMS Server Information
After you've created the $Server variable, you can interact with your WMS server as much as you like. Two scripts—wmServerStatus.pl and wmServerLimits.pl—provide examples of how to do so.
The wmServerStatus.pl script demonstrates a simple interaction. This script retrieves the current status of the specified WMS server. You specify the server when you launch the script. The syntax for the launch command is
perl wmServerStatus.pl \[machine name\]
where machine name is the name of the remote WMS server on which you want to run the script. If you want to run the script on the local WMS server, you don't need to include this optional argument. (Although this command appears on several lines here, you need to enter it on one line in the command window. The same holds true for the other multiline commands in this article.)
Listing 2 contains an excerpt from wmServerStatus.pl. As the code at callout B shows, this script uses the IWMSServer object (which $Server represents) to connect to the specified WMS server. The script then queries the server for the IWMSServer object's Status property value. The code at callout A defines the possible status values in a hash called %SERVER_STATUS.
The wmServerLimits.pl script demonstrates a more complicated interaction with a WMS server. This script retrieves the WMS server's limits. WMS defines multiple limits that prevent the service from exceeding a desired threshold. For example, the ConnectedPlayers limit defines how many players can be simultaneously connected to your service and the ConnectionRate limit defines the rate at which WMS allows new connections. These limits let WMS administrators determine how bandwidth and other resources are consumed.
You can download wmServerLimits.pl (as well as the other Perl scripts mentioned in this article) from the Windows Scripting Solutions Web site. (Go to http://www.windowsitpro.com/windowsscripting, enter 43757 in the InstantDoc ID text box, then click the 43757.zip hotlink.) To run wmServerLimits.pl, use the command
perl wmServerLimits.pl \[machine name\] \[-p PUBPOINT\]
This command is similar to the one for wmServerStatus.pl, except that it includes an optional -p switch. If you want to display the limits for a publishing point rather than the WMS server, you include -p PUBPOINT, where PUBPOINT is the name of that publishing point. (A publishing point is essentially a name with which content is associated. This concept is similar to how the name of a shared directory or a Microsoft IIS Web server maps virtual roots to directories on a hard disk.)
When wmServerLimits.pl runs, it uses the IWMSServer object to connect to the specified WMS server. The script then uses the IWMSServer object's Limits property to retrieve the IWMSServerLimits object, which stores information about the WMS server's limits. Next, the script checks to see whether the person launching the script wants the limits for a specific publishing point rather than for the WMS server. If the user includes the -p switch, the script connects to the specified publishing point. Finally, the script walks through each limit by name (in alphabetical order) and displays the name and value of each limit.
Because the WMS platform is fully scriptable, creating Perl scripts to manage WMS is quite easy and useful. Let's take a look at how to create scripts that track how many clients are connected to WMS and track WMS errors.
Tracking connected clients. Administrators might need to know how many clients are connected to WMS for a variety of reasons. For example, they might have to shut down WMS or they might suspect that someone is trying to attack the service. The wmClients.pl script queries WMS publishing points to create a list of connected clients. Note that I said connected clients. There can be any number of downstream machines connected to WMS. The downstream machines might be players (i.e., computers of people using WMP to watch or listen to streaming-media content), distribution servers, or caching proxy servers. The script lets you specify the type of client to display: players or distribution servers. Caching proxy servers will be displayed as distribution servers. By default, the script displays players.
To understand how wmClients.pl works, you need to be familiar with its launch command, which has the syntax
perl wmClients.pl Machine \[-dlr\] \[-s SortField\] PubPoint \[PubPoint2 \[...\] \]
This command has two mandatory arguments: Machine, which specifies the name of the target WMS server (unlike in the other scripts, this parameter isn't optional), and PubPoint, which specifies the name of the publishing point you want to query. You can specify more than one publishing point. If you specify "." (or don't specify a publishing point) for PubPoint, the script will query all the publishing points for the specified WMS server and display the result. If you want the script to list distributed servers instead of players, you need to include the -l switch. The -s, -d, and -r switches let you customize how values are sorted and displayed in the list. (For more information about these switches, see the syntax section in wmClients.pl.)
Like the other two scripts, wmClients.pl uses the IWMSServer object to connect to the specified WMS server. Then, wmClients.pl begins the process of walking through each publishing point to determine each client's status (i.e., disconnected, idle, open, or streaming). Listing 3, page 14, shows this part of the script. As callout A shows, the script first determines whether to query all publishing points or only specific publishing points. This determination is based on the action taken by the code that callout D shows. After the script processes all the command-line switches, the code at callout D determines whether publishing points were specified on the command line. The code performs this check by pushing all remaining passed parameters (which represent publishing-point names) into an array. Next, the code checks whether any of the parameters are a publishing-point name; if not, the code pushes "." onto the publishing-point array. Later the script walks through the list of publishing points in this array and runs the code at callout A for each one. The code at callout A assigns the $PubPoint variable to either the IWMSServer object ($Server) or the appropriate publishing point, depending on whether the publishing point name is "." or not, respectively. In either case, the script sets $PubPoint to a COM object that exposes one of two possible collection objects: Players (which represents a collection of players) and OutgoingDistributionConnections (which represents a collection of distribution servers). Which collection object the script uses depends on whether you include the -l switch on the command line.
Interestingly, the Players and OutgoingDistributionConnections collection objects are found both at the server's global level and at the publishing-point level. For this reason, the script works with minimal code.
The code at callout B queries the client objects' (i.e., connected players' or connected servers') status. This code calls the Win32::OLE extension's in() function to enumerate the items from the appropriate collection object. The in() function returns an array of COM objects, which the script sorts by using the Perl sort() function. The sort() function calls the script's SortPlayers() subroutine, which callout C shows, to provide the logic to sort the COM objects.
Tracking Errors. Administrators commonly query Windows machines for errors and warnings in the Win32 event log. This information helps determine whether there are problems or pending failures. Besides using the Win32 Event Log, WMS has a diagnostics interface called IWMSDiagnosticEvents that lets you see streaming mediarelated errors and warnings without having to crack open the Event Viewer.
All diagnostic events are stored in WMS. You can access them with the Microsoft Management Console (MMC) Windows Media Services snap-in or from your Web browser by using Windows Media Services Administrator for the Web. You can also access diagnostic events through scripts. You'll find one such script, wmServerErrors.pl, on the Windows Scripting Solutions Web site.
The wmServerErrors.pl script connects to WMS on the specified machine, then uses the Win32::OLE extension's in() function to enumerate each IWMSDiagnosticEvent object in the IWMSDiagnosticEvents collection object. The script sorts the enumerated objects in chronological order, according to the IWMSDiagnosticEvent object's Time property. Thus, the script processes the diagnostic events in the order in which they were generated.
The script copies the property value of each IWMSDiagnosticEvent object into a hash called %ErrorData, then writes the data to the screen. The property values are first copied to a local hash for two reasons: First, the write command prints global or local variables only. The write command won't print a variable's data if you lexically scope the variable by using the my keyword. Second, write format specifies that one of the IWMSDiagnosticEvent object property values must be modified to accommodate wrapping to the next line when displayed. However, all the property values are read-only. Copying the values into the read-write %ErrorData hash allows the modification of those property values.
Note that %ErrorData is a local hash. In wmServerErrors.pl, the line
local %ErrorData = %$Error;
not only declares that %ErrorData has a local scope but also assigns all the hash keys and values from the $Error hash reference. Because $Error is a reference to a hash, the script dereferences the hash reference by placing the % sign in front of the $Error scalar variable.
You can run wmServerErrors.pl by simply passing in the name of the WMS server and optionally passing in the -r switch, which will remove all errors from the server. Follow the command syntax
perl wmServerErrors.pl \[machine name\] \[-r\]
Create Your Own WMS Scripts
This brief introduction to WMS demonstrates how simple it can be to write scripts that retrieve WMS information and manage the service. Using the WMS 9 Series object model, you can also write sophisticated streaming-media scripts that simplify building and maintaining WMS sites.