Jacob is a corporate MIS manager. He can be reached at [email protected].
Encoding Windows Media Video Files
Using ActiveX Controls to Encode RealNetworks Video Files
In the early days of the Web, analog modems were the prevailing method to connect to the Internet. As a result, web sites mostly served textual content with a small number of graphical elements. This picture is changing gradually. With an increasing number of DSL and cable modem installations, web sites are starting to incorporate bandwidth-intensive content such as high-quality graphics and streaming video into their designs.
Microsoft and RealNetworks dominate the streaming video market. Both vendors offer user-friendly tools to create and publish streaming video files. RealNetworks has a large installed base and is still the leading streaming video vendor. Windows MediaPlayer is the playback solution of choice for Windows users. Although Windows MediaPlayer is available for Solaris and the Macintosh, RealNetworks is the preferred streaming video player on these platforms. In addition, RealNetworks has players for many UNIX derivatives, including Linux.
Although these tools are straightforward to use for single users, organizations face several challenges when publishing video content. First of all, they need to agree on video formats and bit rates for the streaming video files they publish. Second, a process needs to be defined to publish and manage streaming video content. Most importantly, organizations need an easy-to-use tool that enforces this process as well as consistent video formats, and that enables a diverse audience to publish streaming video files.
In this article, I'll present an application that addresses these needs. It is an ASP-based web page that runs on the client side, through which users select size, bit rate, and streaming video formats, as well as the AVI and MPEG files to be encoded. Once the selected AVI or MPEG files are uploaded, a server-side Visual Basic application encodes it into Windows Media and/or RealVideo files, and publishes the resulting streaming video clips to a streaming video server.
Application Overview
Figure 1 illustrates the streaming video publishing workflow. The process expects users to have AVI/MPEG files, which they create using video capture hardware and software (such as that from Pinnacle Systems, http://www.pinnaclesys.com/). Figure 2 shows the web page VidUpload.asp, which is used for selecting formats and uploading raw video files.
The selection of the proper format is crucial and depends on the target audience. To offer a good viewing experience for both broadband and modem users, the following streaming video formats should be created:
- 160X120 at 28.8 Kbps and 160X20 at 56 Kbps ensure that analog modem users get reasonable performance through low-bandwidth modem connections.
- 240X180 at 100 Kbps and 240X180 at 256 Kbps give ISDN, DSL, cable modem, and other high-bandwidth users a high-quality video and audio playback experience.
The server-side encoding application creates multibit rate files whenever possible. While the Windows Media Encoder will create multibit rate files automatically, RealVideo requires you to explicitly specify the SureStream option. SureStream is RealNetworks's term for a multibit rate streaming video file. As you can see in Figure 1, the Video Upload web page lets you select encoding in RealVideo, Windows Media, or both streaming video formats. This selection is crucial because there is a licensing difference between the two streaming video applications. While Microsoft Windows Media is part of Windows 2000 Server and, therefore, free, RealNetworks charges a fee for each simultaneous connection.
Listing One is VidUpload.asp, a simple ASP page that displays the form elements of Figure 1, which lets users define the bit rates and formats of the video file(s) to be uploaded. We use the ASPUpload COM component to perform the HTML upload chore. We take advantage of the XUpload ActiveX control, which works hand-in-hand with the server-side ASPUpload component. XUpload makes the HTML upload a more user-friendly experience by providing features such as an accurate progress bar. Both ASPUpload and XUpload are available at http://www.persits.com/.
On submitting VidUpload.asp, VidUploadSubmit.asp is executed, which triggers multiple events. First, the selected video file is uploaded to the web server. Second, we create an entry for the uploaded AVI/MPEG clip into the database table tblVideo (see Table 1). The new database entry holds all relevant information about the uploaded video clip such as the selected bit rates and formats.
Listing Two, VidUploadSubmit.asp, starts with setting the script timeout to 3000 seconds to make sure that file uploads over a slow modem connection aren't terminated prematurely. After setting the maximum file size to 10 MB, we write the file name, description, and file size to local variables. VidUploadSubmit.asp then determines the streaming video formats that need to be generated. The sample application supports the following streaming video file sizes: 160X120, 240X180, and 320X240, respectively. The required formats for each file size are determined and stored in three local variables: s160x120, s240x180, and s320x240. The value of each of these variables has the format WIDTHxHEIGHT_BITRATE1_BITRATE2_BITRATE3. For instance, if users specify that the uploaded video clip should be available as a 28.8-Kbps and 56-Kbps stream at 160X120, and as a 100 Kbps and 256-Kbps stream at 240X180, the values for the local variables would be:
- s160X120 = "160x120_28_56"
- s240X180 = "240x180_100_256"
- s320X240 = ""
In addition to size and bit rate, VidUploadSubmit.asp determines if RealVideo and/or Windows Media formats should be generated. sFormat can have the following values:
- sFormat = 1 (Windows Media only)
- sFormat = 2 (RealVideo only)
- sFormat = 3 (Both Windows Media and RealVideo)
VidUploadSubmit.asp submits file name, description, file size, a member ID, and the various formats to tblVideo, which is part of a relational Access or SQL server database, as in Table 1.
The EncodingStatus field in tblVideo has a key function, because it handles the handshake between the encoding application, Video Upload page, and playback web page. As long as EncodingStatus is 0, the file will not be available for playback. On the other hand, EncodingStatus 0 informs the server-side encoding application that a new file was uploaded, and needs to be encoded. Once the encoding process is finished, the encoding application sets the EncodingStatus equal to 1, which makes the streaming video file available for viewing.
The Windows Media SDK
Microsoft provides six major components in its Windows Media SDK to develop streaming audio/video applications:
- The Windows MediaPlayer SDK lets you use the Windows MediaPlayer ActiveX control to add multimedia playback capabilities to COM-based documents and applications, as well as web pages.
- The Windows Media Encoder SDK supports the Automation interface for programmatically configuring and controlling Windows Media Encoder.
- The Windows Media Format SDK enables the reading, writing, and editing of Windows Media files, along with the downloading of files to portable devices.
- The Windows Media Services SDK provides an API to programmatically manage unicast and multicast streaming services.
- The Windows Media Rights Manager SDK lets you protect Windows Media files and issue licenses to maintain copyrights.
- The Windows Media Meta Files support the creation of Windows Media metafile playlists, including ad insertion, banner graphics, and seamless stream switching.
Detailed information as well as the actual SDKs are available at http://www.microsoft.com/windowsmedia/.
The server-side Visual Basic encoding application uses the Windows Media Encoder API to encode AVI/MPEG clips into streaming Windows Media files. To programmatically encode video files, the application needs to perform a series of steps described in the text box "Encoding Windows Media Video Files."
The RealVideo ActiveX Control
Like Microsoft, RealNetworks provides SDKs, which are available at http://www.realnetworks.com/. In addition to the SDK, RealNetworks offers an ActiveX control for encoding that drastically simplifies application development. The RealProducer ActiveX Control lets you automate the functionality provided by the RealNetworks RealProducer application. For our application, I will use the ActiveX control to encode AVI/MPEG files into RealVideo files. See the accompanying text box entitled "Using ActiveX Controls to Encode RealNetworks Video Files."
The Encoding Application
Figure 3 is a flowchart of the server-side encoding application. Figure 4 shows the encoding application in action. The encoding occurs in a Visual Basic Timer function, which is called every two seconds. blnTimer1 ensures that only one file is encoded at one time. We first check if a previous encoding session failed, and try to encode it until we succeed or reach the maximum number of errors allowed. We then look for newly uploaded files by checking if EncodingStatus equals 0.
The actual encoding process starts by copying the uploaded AVI/MPEG file to the encoding server. Depending on the selected formats and bit rates, we create the requested Windows Media and RealVideo files and copy them to a streaming video server. We then activate the clips for viewing by setting the field Active in tblEncodedVideo to 1. Last, we delete files that are no longer needed, including the initially uploaded AVI/MPEG file. Before we exit Timer1, we set blnTimer1 to False, allowing another encoding session to start. The complete application including source code, database script, and Windows Media Profiles is available electronically; see "Resource Center," page 5.
Application Deployment
To install the application, you need to perform the following steps:
1. Create a web site to host VidUpload.asp, VidUploadSubmit.asp, and XUpload.ocx. Install ASPUpload on this web server, and create the c:\VidUploads directory. Both ASPUpload.asp and XUpload.ocx are at http://www.persits.com/.
2. Create the SQL server database videoDB by running videoDB.sql in SQL server 7.0 Query Analyzer. Create the database user video and make it the owner of the videoDB database.
3. On the encoding server, install Windows Media Encoder and copy the profiles (available electronically) into the Profile directory of Windows Media Encoder. Also, install the RealNetworks RealProducer application and the RealProducer ActiveX control on the encoding server. Both are available at http:// www.realnetworks.com/.
4. On the encoding server, copy encoder.cfg to c:\, and create the directory c:\Encoding. Copy small.jpg and still.jpg into the c:\Encoding directory.
5. Copy the encoding application to the Encoding server.
6. Setup a video folder on a Windows 2000 streaming video server, which is shared by both Windows Media Server and RealNetworks Server. This folder contains the encoded Windows Media and RealVideo clips. The location of this video folder will need to be configured in the encoding application.
7. Start the encoding application on the encoding server and click on Configure to configure the video upload location, streaming video location, encoding and encoding log directory, the database connection string, as well as the error retry property and time interval between retries.
Conclusion
The SDKs and tools provided by Microsoft and RealNetworks let you develop a fully automated streaming video encoding application so that users can submit AVI/MPEG files. The application publishes the submitted clips and encodes them to the requested streaming video formats.
DDJ
Listing One
<SCRIPT LANGUAGE="VBScript"> Sub Select_OnClick UploadCtl.Select End Sub Sub Remove_OnClick UploadCtl.RemoveHighlighted End Sub Sub Upload_OnClick UploadCtl.Upload End Sub Sub goUpload timerID = setTimeOut("UploadCtl.Upload",100) UploadCtl.Select End Sub < /SCRIPT> <HTML> <HEAD> <TITLE>Upload and Encode your Video Files</TITLE> </HEAD> <BODY bgcolor="White" Language="vbscript" OnLoad="goUpload"> <table width="400" border="1" cellspacing="0" cellpadding="10"> <tr bgcolor="#eeeeee"><td align="center"> <h2><font color="Black">Upload and Encode your Video Files</font></h2> <FORM NAME="frmInfo"> <table border="1"> <tr bgcolor="Black"><td> <table> <tr> <td width="120" align="center"><b><font color="White">Size</font></b></td> <td width="100" align="right"><b><font color="White">Bitrate</font></b></td> </tr> </table> </td></tr> <tr bgcolor="White"><td> <table> <tr><td width="120" align="center">160x120</td> <td align="right" width="100"> 28.8 kbps<br> 56 kbps<br> 100 kbps </td> <td align="left" width="80"> <input type="checkbox" name="160x120x28"><br> <input type="checkbox" name="160x120x56"><br> <input type="checkbox" name="160x120x100"><br> </td> </tr> </table> </td></tr> < tr bgcolor="White"><td> <table> <tr><td width="120" align="center">240x180</td> <td align="right" width="100"> 56 kbps<br> 100 kbps<br> 256 kbps </td> <td align="left" width="80"> <input type="checkbox" name="240x180x56"><br> <input type="checkbox" name="240x180x100"><br> <input type="checkbox" name="240x180x256"> </td> </tr> </table> </td></tr> < tr bgcolor="White"><td> <table> <tr><td width="120" align="center">320x240</td> <td align="right" width="100"> 56 kbps<br> 100 kbps<br> 256 kbps </td> <td align="left" width="80"> <input type="checkbox" name="320x240x56"><br> <input type="checkbox" name="320x240x100"><br> <input type="checkbox" name="320x240x256"> </td> </tr> </table> </td></tr> < tr bgcolor="White"><td> <table> <tr><td width="120" align="Right">Windows Media</td> <td align="Left"> <input type="checkbox" name="WindowsMedia"> </td> </tr> <tr><td width="120" align="Right">Real Video</td> <td align="Left"> <input type="checkbox" name="RealVideo"> </td> </tr> </table> </td></tr> </table> <br> <font color="6666FF"><b>Short Description:</b></font><br> <input type=text id="sDescription" name="sDescription" size="60" value=""><br> </FORM> <OBJECT WIDTH=500 HEIGHT=50 ID="UploadCtl" CLASSID="CLSID:E87F6C8E-16C0-11D3-BEF7-009027438003" CODEBASE="XUpload.ocx"> <PARAM NAME="Server" VALUE="www.mystudionline.com"> <PARAM NAME="Script" VALUE="/qa/VidUploadSubmit.asp"> <PARAM NAME="ViewServerReply" VALUE="False"> <PARAM NAME="EnablePopupMenu" VALUE="False"> <PARAM NAME="ShowProgress" VALUE="True"> <PARAM NAME="MaxFileCount" VALUE="1"> <PARAM NAME="Redirect" VALUE="True"> <PARAM NAME="RedirectURL" VALUE="VidUpload.asp"> <PARAM NAME="HtmlForm" VALUE="frmInfo"> <% If strFileName <> "" Then %> <PARAM NAME="File1" VALUE="<%=strFileName%>"> <% End If %> </OBJECT> <P> <INPUT TYPE=BUTTON NAME="SELECT" VALUE="Browse"> <INPUT TYPE=BUTTON NAME="REMOVE" VALUE="Remove"> <INPUT TYPE=BUTTON NAME="UPLOAD" VALUE="Upload"> </td></tr> </table> </BODY> </HTML>
Listing Two
<%@ Language=VBScript %> <!--#include file="adovbs.inc"--> <% Dim viMemberID, vCount, vFileName, sFileDesc, sFileSize, oConn, strSQL, rsVideo 'For this sample page, we set the Member ID to 1. viMemberID = 1 'Determines the value of Set160x120Profile '------------------------------------------ Function Set160x120Profile(s160x120x28, s160x120x56, s160x120x100) Set160x120Profile = "" If (s160x120x28="on") AND NOT (s160x120x56="on") AND NOT (s160x120x100="on") Then Set160x120Profile = "160x120x28" Exit Function End If If NOT (s160x120x28="on") AND (s160x120x56="on") AND NOT (s160x120x100="on") Then Set160x120Profile = "160x120x56" Exit Function End If If NOT (s160x120x28="on") AND NOT (s160x120x56="on") AND (s160x120x100="on") Then Set160x120Profile = "160x120x100" Exit Function End If If (s160x120x28="on") AND (s160x120x56="on") AND NOT (s160x120x100="on") Then Set160x120Profile = "160x120x28_56" Exit Function End If If (s160x120x28="on") AND NOT (s160x120x56="on") AND (s160x120x100="on") Then Set160x120Profile = "160x120x28_100" Exit Function End If If NOT (s160x120x28="on") AND (s160x120x56="on") AND (s160x120x100="on") Then Set160x120Profile = "160x120x56_100" Exit Function End If If (s160x120x28="on") AND (s160x120x56="on") AND (s160x120x100="on") Then Set160x120Profile = "160x120x28_56_100" Exit Function End If End Function 'Determines the value of Set240x180Profile '------------------------------------------ Function Set240x180Profile(s240x180x56, s240x180x100,s240x180x256) Set240x180Profile = "" If (s240x180x56="on") AND NOT (s240x180x100="on") AND NOT (s240x180x256="on") Then Set240x180Profile = "240x180x56" Exit Function End If If NOT (s240x180x56="on") AND (s240x180x100="on") AND NOT (s240x180x256="on") Then Set240x180Profile = "240x180x100" Exit Function End If If NOT (s240x180x56="on") AND NOT (s240x180x100="on") AND (s240x180x256="on") Then Set240x180Profile = "240x180x256" Exit Function End If If (s240x180x56="on") AND (s240x180x100="on") AND NOT (s240x180x256="on") Then Set240x180Profile = "240x180x56_100" Exit Function End If If (s240x180x56="on") AND NOT (s240x180x100="on") AND (s240x180x256="on") Then Set240x180Profile = "240x180x56_256" Exit Function End If If NOT (s240x180x56="on") AND (s240x180x100="on") AND (s240x180x256="on") Then Set240x180Profile = "240x180x100_256" Exit Function End If If (s240x180x56="on") AND (s240x180x100="on") AND (s240x180x25="on") Then Set240x180Profile = "240x180x56_100_256" Exit Function End If End Function 'Determines the value of Set320x240Profile '------------------------------------------ Function Set320x240Profile(s320x240x56, s320x240x100, s320x240x256) Set320x240Profile = "" If (s320x240x56="on") AND NOT (s320x240x100="on") AND NOT (s320x240x256="on") Then Set320x240Profile = "320x240x56" Exit Function End If If NOT (s320x240x56="on") AND (s320x240x100="on") AND NOT (s320x240x256="on") Then Set320x240Profile = "320x240x100" Exit Function End If If NOT (s320x240x56="on") AND NOT (s320x240x100="on") AND (s320x240x256="on") Then Set320x240Profile = "320x240x256" Exit Function End If If (s320x240x56="on") AND (s320x240x100="on") AND NOT (s320x240x256="on") Then Set320x240Profile = "320x240x56_100" Exit Function End If If (s320x240x56="on") AND NOT (s320x240x100="on") AND (s320x240x256="on") Then Set320x240Profile = "320x240x56_256" Exit Function End If If NOT (s320x240x56="on") AND (s320x240x100="on") AND (s320x240x256="on") Then Set320x240Profile = "320x240x100_256" Exit Function End If If (s320x240x56="on") AND (s320x240x100="on") AND (s320x240x256="on") Then Set320x240Profile = "320x240x56_100_256" Exit Function End If End Function 'Determines the requested Streaming Video formats: ' 1: WindowsMedia Only ' 2: RealVideo Only ' 3: Both WindowsMedia and RealVideo '------------------------------------------------- Function SetFormat(sWindowsMedia, sRealVideo) SetFormat = 3 If (sWindowsMedia="on") AND NOT (sRealVideo="on") Then SetFormat = 1 Exit Function End If If NOT (sWindowsMedia="on") AND (sRealVideo="on") Then SetFormat = 2 Exit Function End If If (sWindowsMedia="on") AND (sRealVideo="on") Then SetFormat = 3 Exit Function End If End Function 'Set script timeout to 3000 seconds Server.ScriptTimeout = 3000 'ASPUpload code '--------------- Set vUpload = Server.CreateObject("Persits.Upload.1") vUpload.OverwriteFiles = False ' Generate unique filenames vUpload.SetMaxSize 10040000, True ' Reject files above 10 Megabyte vCount = vUpload.Save( Application("UploadPath") ) For each file in vUpload.Files vFileName = File.ExtractFileName sFileSize = File.Size Next sFileDesc = vUpload.Form("sDescription") 'Determine requested Streaming Video file formats '------------------------------------------------ s160x120 = Set160x120Profile(vUpload.Form("160x120x28"),vUpload.Form("160x120x56"),vUpload.Form("160x120x100")) s240x180 = Set240x180Profile(vUpload.Form("240x180x56"),vUpload.Form("240x180x100"),vUpload.Form("240x180x256")) s320x240 = Set320x240Profile(vUpload.Form("320x240x56"),vUpload.Form("320x240x100"),vUpload.Form("320x240x256")) sFormat = SetFormat(vUpload.Form("WindowsMedia"),vUpload.Form("RealVideo")) 'Update tblVideo '--------------- Set oConn = Server.CreateObject("ADODB.Connection") oConn.Open(application("CONNECTIONSTRING")) strSQL = "select * from tblVideo Where ID = -1" Set rsVideo = oConn.execute(strSQL) rsVideo.AddNew rsVideo("FileName") = cstr(vFileName) rsVideo("Description") = cstr(sFileDesc) rsVideo("FileSize") = sFileSize rsVideo("MemberID") = viMemberID rsVideo("[160x120]") = s160x120 rsVideo("[240x180]") = s240x180 rsVideo("[320x240]") = s320x240 rsVideo("Format") = sFormat rsVideo("EncodingStatus") = 0 rsVideo("Active") = 0 rsVideo.Update rsVideo.Close Set rsVideo = Nothing oConn.Close Set oConn = Nothing Set vUpload = Nothing %>