I recently completed a web-enabled application where my client wanted to correlate transaction events stored in a database with video clips captured by surveillance cameras. The transaction events were comprised of cash register events that occurred at a parking toll plaza. The idea was that if management noticed suspicious cash register events for a particular toll collector, they could quickly locate the captured video clips that showed what the collector was doing during these suspect transaction events. Obviously, watching the corresponding video clips is crucial in determining if something illegal transpired.
The closed captioning technology that is part of the Windows Media Player provided a great way of linking the transaction events to video clips. Closed captions are shown at specific time points within a video clip, so by presenting the transaction events as closed captions, the user could both be alerted as to when the transaction event occurred within a given video as well as jump to a particular moment in the video based on a particular transaction event.
The hook between the video clip and the closed captions is called a SAMI file. The MSDN contains an introductory article on SAMI that will get you started in learning about how it works. You may also want to look at this article on SAMI at WebAIM. Most people use SAMI to provide captions for the hard of hearing or translations into different languages. In these cases, the SAMI files are static since the content is well-known a priori. For my project, I needed a dynamic, data-driven SAMI file based on transaction events stored in a SQL Server database. So, the SAMIFileName property on the Windows Media Player object was set in JavaScript to an ASPX page that would generate the SAMI file by performing a database query for the transaction events based on query string parameters.
The web page containing the Windows Media Player and the closed captioning information looked something like this:
<html>
<head>
<script language="JavaScript">
function Loaded()
{
WMP1.SAMIFileName = 'http://localhost/TestSite/GetSAMI.aspx?' +
'tid=Transid01823288' +
'&clipdt=11/27/2005%2000:00:12' +
'&durms=46000';
WMP1.Open('http://localhost/TestSite/Test.avi');
}
</script>
<body onload="Loaded();">
<object
classid="CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95"
id="WMP1"
width="320"
height="240"
style="margin:6; border:3 inset white;" >
<param name="captioningID" value="cc">
<param name="SAMIStyle" value="Black Print">
<param name="AutoStart" value=false>
<param name="AutoRewind" value=true>
<param name="EnableContextMenu" value=false>
</object>
<!-- A <div> window for the SAMI captioning, 'id=cc' is specified
for 'captioningID' parameter -->
<div
id=cc
style="margin-top:3; width:290; height:90; background:
white; border:2 inset silver;">
</div>
</body>
</html>
The important thing to notice here is that in the Loaded() JavaScript function, I set the SAMIFileName property on the Windows Media Player object to my ASPX page with the corresponding query string parameters used to do the database query. The HTML part of the GetASPX page is rather simple:
<%@ Page language="c#" Codebehind="GetSAMI.aspx.cs" AutoEventWireup="false" Inherits="TestSite.GetSAMI" %>
<SAMI>
<HEAD>
<TITLE>Toll Data Events</TITLE>
<STYLE TYPE="text/css">
<!--
P {background-color: <%= Common.BG_COLOR_1 %>;}
.ENUSCC {Name: "English Captions"; lang: en-US-CC;}
<% // This bogus style is needed to get the output text to render correctly %>
#Bogus {font-size: 24pt;}
-->
</STYLE>
</HEAD>
<BODY>
<%= SyncHTML.ToString() %>
</BODY>
</SAMI>
In the code behind, you first need to set the content type of the response to "application/octet-stream" so that the Windows Media Player will process the SAMI correctly:
// Set response type according to what is needed for SAMI file
Response.ContentType = "application/octet-stream";
After that, perform the database query based on the given query string parameters and then set the SyncHTML string to the appropriate <SYNC> elements based on the query results. You'll need to calculate offsets into the clip file based on the start date/time of the clip file, which was given as a query parameter.
Unfortunately, I found the dynamically-generated SAMI files to be a bit quirky — you may have noticed the line I had to add to GetSAMI ASPX file above with the style named Bogus. Without this line, the Windows Media Player did not render the closed caption (i.e., the correlated transaction events) correctly. You may have to fiddle with your GetSAMI ASPX page to get this working correctly for you.