Subtitle Workshop, by Urusoft is free captioning software (donation-ware) which allows you to easily transcribe and edit captions and output the resulting file to many different formats. I'll be focusing on Windows Media format here, but you will find this a useful tool for captioning DVD's, Quicktime, and Flash as well.
Note: A much more complete exposition of the concepts summarized in this tutorial is available to members of the Elearning Guild in the article A Guide to Captioning Windows Media and QuickTime Using Subtitle Workshop
You can download Subtitle Workshop here. Once it is installed, launch the application, and follow the steps to create a caption file that can be used in the stand-alone or HTML-embedded Windows Media Player.
Before you begin, your video must be completely edited to its final duration and saved in a format that can be opened by Subtitle workshop, such as Windows Media. It does not have to be at full size, however. For example if your final video is 640x480, you could do the captioning on a 320x240 file, which could save time, space, and enable you to use a lesser computer for this stage of your video workflow.
Creating synced captions
Open your saved SAMI file in a text editor. At the top of the file is a style sheet that controls the size and color of your captions, and also sets some Windows Media-specific parameters. You can change the size, color, margins, etc. here. Upload the SAMI file to your web server. Upload your video file to a streaming server or a web server.
Add a captioned Windows Media player to your web page
1. Create the object and embed tags, and add appropriate parameters.
2. Create 2 asx files, one for the PC, which references the SAMI file, and one for the Mac which doesn't.
<ASX version="3.0"> <ENTRY> <REF HREF="mms://your.streamingserver.com/videofile.wmv?sami=http://path.to.sami/videoName.smi"/> </ENTRY> </ASX>
An easy way to get a head start on creating the HTML for an embedded windows media player is to use this generator provided by UCSF's Center for Instructional Technology. This will create the basic object tag, embed tag and associated parameters. Once you have these basics, you will have to add the captioning-related items shown in red below.
This is an example HTML page showing the embedded player.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML> <HEAD> <TITLE>Closed Captioning Example</TITLE> <!-- the following style sheet controls the look of the div containing the captions.--> <style>
<--
#CapText1 { font-family: Arial, Helvetica, sans-serif; font-size: 12px; text-align:center; background-color:#000000; width:300px; height:80px; color: #FFFFFF; }
--> </style></HEAD>
<BODY>
<!-- the OBJECT tag contains the settings to create the Windows Media Player ActiveX control in the Web page in IE for PC. The Embed tag is contained within the OBJECT tag to support non-IE browsers which use a plugin to create the Media Player-->
<OBJECT classid = clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6 height = 300 id = "Player1" width = 300>
<param name = "AutoStart" value = "1">
<param name = "CaptioningID" value = "CapText1">
<param name = "ShowCaptioning" value="True">
<param name = "URL" value = "videoName.asx">
<!--The Embed tag displays the Netscape Plugin Windows Media Player, which understands a somewhat different set of parameter names-->
<embed TYPE = "application/x-mplayer2"
width="300"
height="360"
ID="Player1"
src="videoName.asx"
autostart="1"
autosize="0"
samifilename="videoName.smi"
showcaptioning="1" >
</embed>
</OBJECT>
<!-- this DIV creates a partition for a closed caption text display in IE for PC -->
<DIV name ="CapText1" id = "CapText1"></DIV></BODY>
</HTML>
ActiveX issues
In February, 2006, Microsoft made changes to Internet Explorer to get around the EOLAS patent, after being sued for infringing on it. The changes made it necessary for IE users to click to activate any element within an "OBJECT" tag: this includes Flash, Shockwave, video, java applets and other plugin technologies. Besides some inconvenience, this negatively impacts the usability of HTML pages, because users sometimes don't notice that they need to click, despite the alerts and messages IE attempts to display. Web developers have come up with several workarounds. Since javascripted embedding does not infringe on the patent, a typical approach is to convert the content of the OBJECT tag to a javascript "write" statement. This must be in an external script to be eliminate the "click to activate".
If you use Dreamweaver, it will automatically apply a fix to your page, if you have the preferences set up correctly.
There are several other methods of getting around the problem. One dynamically replaces a "noscript" tag with the required object tag and its contents. I haven't tested this, but you can try it here: http://www.ediy.co.nz/click-to-activate-and-use-this-control-fix-for-internet-explorer-xidc20771.html
Putting all the pieces together
Additional Reference
function insertList(){
for(var i=0; i< PageArray2.length; i++) {
parent.data.PageArray.splice((window.parent.data.znThisPage-1),0,PageArray2[i]);
parent.data.determineParents();
}
wipePageNo();
wipeNavBar();
printNavBar();
}
function writeArray(){
for(var i=0; i< parent.data.PageArray.length; i++) {
document.getElementById('writeItHere').innerHTML +=(parent.data.PageArray[i].url +" " + parent.data.PageArray[i].title +'
');
} }
addOnePagetoEnd: The following function pushes just one new page at a time into the page list. To use, add title, url, chapter and level information to the "mystring" line, similar to what you did when filling out each line in the page array.
function addOnePagetoEnd() {
mystring=({title:'I am new',url:'page303.htm',chapter:0,level:1});
parent.data.PageArray.push(mystring);
document.getElementById('NavBar').innerHTML = ('');
parent.data.determineParents();//haven't testedd yet but you have to run determineParents after modifying the array
wipePageNo();
wipeNavBar();
printNavBar();}
function replaceAllPages() {
parent.data.PageArray=parent.data.PageArray2;
parent.data.determineParents();
wipePageNo();
wipeNavBar();
printNavBar();
NextPage(); }
//**end branching toolkit**//
The css styles are defined in several sheets. Any of the styles can be overridden by adding a new definition for the selector to /css-local/userStyles.js or to individual pages or even individual elements on a page. YOU WILL NOT BE ABLE TO change any of the files inside the css/ folder but you can add your own overrides to userStyles.css.
If you need special text styles or need to control the positioning of content-specific elements, add those to the userStyles file.
css/allBrowsers.css contains most of the styles used. These include the pseudo-class selectors, and the styles that define the structure of the page, including most of the navBar.
A few Internet Explorer-specific styles are included in includes/headContent.htm, using a conditional comment to hide them from all other browsers. These were unavoidable, since IE still has some unique differences. These override their counterparts in allBrowsers.css.
css/print.css removes the Navbar when printing to make the document fit the page better.
css/header.css contains styles for header and footer.
css/stylesMac.css is not being used at this time.
css/styles800x600 is experimental for use with smaller screens or low resolution monitors, but is not really working well yet.
How to override a style
Let's say you wanted to change the style of all h4 elements to dark blue. In userStyles.css, add the following:
h4 {
color: #003366
}
That's all there is to it! Of course you can also create your own styles as well. userStyles.css is already included in the includes/headContent.htm file so it will automatically be picked up if there is anything in it.
Now you are ready to start building pages.
Important: You will find that Dreamweaver 8 does a much better job of displaying this module, complete with all the Server Side Includes, than earlier versions. It is possible to use earlier versions, but you will only see the central content area of the page, and not the Header/Footer areas or Navbar area.
Note: Typical Dreamweaver-generated javascripts used for rollover images and creating popup windows are already included in the template. You do not need to add them again.
Click to enlarge image
Find the lines that say:
"*****Put content below this line!!!****"
and
"*********Put content above this line!!!******"
#pageTitle {
display:none;
visibility:hidden;
}
Click the image below to see the two columns highlighted in red.
In the same file as the pageArray, you will find several other variables: chapterArray, docTitle, and headerTitle.
The chapterArray can be filled out with chapter titles if desired. This is optional - the chapter and page titles can both be hidden if not needed.
The docTitle and headerTitle are required. The docTitle is the title that shows up at the top of every window -in other words the <title> tag on each page. The headerTitle is the title which shows up in the blue header at the top of each page.
If you want, you may have Chapter titles and Page titles show up automatically on every page, or on only the pages you choose.
Look for:
var chapterArray
Add chapters as necessary, observing the usual caution about the punctuation at the end of the array.

Click to enlarge image
Find the file js-local/pageArray.js and duplicate it to make a backup copy. Then open the original file js-local/pageArray.js
Don't be intimidated by all the code on this page. You will simply be adding titles to the list of pages.
You can see that there is a line for each page in the module. Each line in the Array contains the following:
Carefully replace the button and page titles with the titles from your outline. Add the relative URL's for each page. You may use any filename for your pages, not just page01, page02, etc. However if you choose to change the name of the first page, "page01.htm", please be sure to change it in the "index.htm" page as well or the frameset will open with a "not-found" error.
It is very important that you DO NOT DELETE ANY PUNCTUATION, so be careful when you are pasting in titles. If you do, and cannot find what you deleted, use the backup file you just created, and try again. Every line in the array gets a comma after it, except for the last one.
Note: make sure the number of chapters in the Chapter Array matches the number in the Page Array.
For the simple outline shown here
the page array would look like this:
and would result in this navbar:
For the more complex hierarchical outline shown here:

the page array would look like this:
and would result in this navbar, with Chapter III shown open.
Example of a finished module based on the template. Note: the look of the navigation column has changed slightly since this article was first written.
>> View a live demo of the template here
>> Download the template files here
![]() |
| Another example of a module based on the template. The navigation bar shown here is the latest version. |
>> View a live demo of the template here
>> Download the template files here
This HTML template is designed to simplify the creation of SCORM-compatible learning modules. Some of the features include:
You will notice that several of the directories have two versions - a "global" version and a "local" version ("css-local," "includes-local," and "js-local"). There is also a "media" folder which is where you will put your module-specific images. This is because on our production server, we use a version control process where the global folders are replaced with symlinks, so that changes to the template will immediately update all templates on the server. Changes made in the local folders will affect that module only.
The files in the "local" directories and files can be modified as needed, and can be used to override many global settings. For example, the CSS styles can be changed by adding styles to the file "css-local/userStyles.css."

Start by outlining your entire learning module. List all the pages you want to include. You can change the list after you get started, so don't worry if there are items you aren't sure about.The module structure can be very simple as shown in Example 1, or more structured with chapters and sections as shown in Example 2. This template can accommodate up to four levels if needed.
Example 1The outline below shows a flat structure, with all pages on the same hierarchical level. In this example, all items would be on level 1. |
This is the navbar that results from this outline. Links to all items are visible at all times. |
|
|
![]() |
Example 2This outline shows a more complex hierarchical structure with chapters and sub-sections. In this example, the Competency Criteria page and the Chapter Introductions would be on level 1 and the Subtopics would all be on level 2. |
This is the navbar that results from this outline. Only the top level (level1) items are visible at all times. Other levels are visible when browsing any page in the respective chapter. NOTE: each page on level 1 should have a different chapter number. |
|
|
![]() |
SCORM courses in the SumTotal 6.5 Learning Management System are launched from a page that lists each SCO (lesson) in a list of links representing the course structure.
On clicking the "Enter the Lesson" button next to any SCO, a new frameset window opens. The screenshot below shows the "Enter the Lesson" page, with the course window open in front of it.
Once the course window opens, there is no corresponding list of links within it to allow the user to jump back and forth between SCOs. In some courses, it would be useful to allow inter-SCO navigation without having to close the course window.
SumTotal 6.5 does have a "sequencing" feature, which means that if the LMSFinish command is sent by the SCO, the next SCO, if there is one, will open in the same frame. But there is no way to jump around between SCOs at will, or perhaps more importantly, to try the same SCO again without closing the window.
The frameset structure of the course window is as shown below:

SumTotal provides API extensions which allow such functions as "nextSCO", "previousSCO" etc., all of which consult the course structure to generate the actual links.
The easiest way to determine the correct DOM paths to these functions from wherever you currently are in the window is probably to use the DOM inspector tool in Firefox. The image below illustrates.
The code for various types of jumps is shown below. These links work from within the course itself. I'll post the code for generating a complete navbar in a future entry.
Go to the first SCO:
<a href="javascript:top.API.LMSFinish('');top.API_extensions.changeSCOContent(top.API_extensions.gSCOCourseStructure.scos[0],parent.frames[0]);">SCO1</a>
Go to the second SCO:
<a href="javascript:top.API.LMSFinish('');top.API_extensions.changeSCOContent(top.API_extensions.gSCOCourseStructure.scos[1],parent.frames[0]);">SCO2</a>
Go to the third SCO:
<a href="javascript:top.API.LMSFinish('');top.API_extensions.changeSCOContent(top.API_extensions.gSCOCourseStructure.scos[2],parent.frames[0]);">SCO3</a>
Go to the fourth SCO:
<a href="javascript:top.API.LMSFinish('');top.API_extensions.changeSCOContent(top.API_extensions.gSCOCourseStructure.scos[3],parent.frames[0]);">SCO4</a>
Go to the next SCO:
<a href="javascript:top.API.LMSFinish('');top.API_extensions.changeSCOContent(top.API_extensions.gSCOCourseStructure.getNextSCO(),parent.frames[0]);">getNextSCO()</a>
Go to the previous SCO:
<a href="javascript:top.API.LMSFinish('');top.API_extensions.changeSCOContent(top.API_extensions.gSCOCourseStructure.getPreviousSCO(),parent.frames[0]);">getPreviousSCO()</a>
Try this SCO again:
<a href="javascript:top.API_extensions.changeSCOContent(top.API_extensions.gSCOCourseStructure.getCurrentSCO(),parent.frames[0]);">getCurrentSCO() (Try again!)</a>
Get a SCO by specific ID:
<a href="javascript:top.API.LMSFinish('');top.API_extensions.changeSCOContent(top.API_extensions.gSCOCourseStructure.getSCO('A2'),parent.frames[0]);">getSCO('A2')</a>