Adding Subtitles to videos in Silverlight

This article is about adding sutitles to videos hosted inside a Silverlight plugin. It is possible to do so using ultra-simple technique in javascript and a feature of Silverlight, which allows text to be drawn over videos. The technique involves a simple javascript timer, that checks the current position of video and shows appropriate subtitle text. With this tecnhique you can:

Subtitles displayed on video

Click here to see online demo !

  • Add subtitles to any video.
  • Customize how they look (color,font, positon).
  • Add subtitles in multiple languages.
  • Make use of javascript and silverlight.So the whole job can be accomplished with a text editor.

Given below is detailed ‘how-to’.

Creating the XAML

<Canvas Width="320" Height="240" xmlns="http://schemas.microsoft.com/client/2007"  
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="Black">

<MediaElement x:Name="VideoControl" Canvas.Top="0" Canvas.Left="0"
Source="http://localhost/SlvrSub/test.wmv" AutoPlay="true"> </MediaElement>

<Canvas Background="#40000000" Width="320" Height="20" Canvas.Top="220"
Canvas.Left="0" Opacity="255"> <TextBlock FontSize="12" x:Name="Subtitle"
FontFamily="Arial Unicode MS" Canvas.Left="40" Foreground="White">
Javascript needs to be turned on to show subtitles.</TextBlock>
</Canvas>

</Canvas>

In the above XAML notice the following things:

  • The size of parent ‘Canvas’ is set to size of video( i.e 320*240).
  • There is a child ‘Canvas’ that contains a TextBlock, which is used to show the subtitles. Note that I have used a unicode font for displaying subtitles, so that multiple languages can be supported.
  • Videos should be converted to a format playable by Silverlight.

Writing Javascript

The javascript required for this, is very simple. I have written a simple javascript class, called ‘Subtitler’ which is used to fetch subtitle related to current position of the video. The current position of video is obtained using ‘MediaElement.Position.seconds’. One nice thing about this is, it returns total number of seconds from the start of the video. This means we dont have to mess around with a ‘Timespan’ object get current position. Subtitles are stored as javascript array. The index corresponds to the position (in second) where it should be shown in the video. I mean ‘subtitle[120]’ would be shown during the 120th second of the playback. To make things clearer, let use see the code.

var sub_en = new Array();
sub_en[1] = "Subtitle as 1st Second";
sub_en[2] = "Subtitle as 2nd Second";
sub_en[3] = "Subtitle as 3rd Second";
sub_en[4] = "Subtitle as 4th Second";
sub_en[5] = "Subtitle as 5th Second";
// ..... Add till last second of video.

var slvr_ctrl,videoCtrl,subobj;
var persistTextSec = 5;
var oldTitlePos = 0;

//Initialize variables. Called on 'OnInit'
// of Silverlight Plugin.
function Init(sender)
{
subobj = new SubTitler();
subobj.SubtitleDataSource = sub_en;
slvr_ctrl = sender.getHost();
videoCtrl = slvr_ctrl.content.findName("VideoControl")
//Set a javascriptimer
window.setTimeout("timerCompleted()",100);
}

//If the video is playing get subtitles corresponding to current
// position of the video.
function timerCompleted()
{
if(videoCtrl.CurrentState == 'Playing' || videoCtrl.CurrentState == 'Opening')
{
var sec = Math.round(videoCtrl.Position.seconds);
var lbl = slvr_ctrl.content.findName("Subtitle");
var subtxt = subobj.GetSubtitle(sec);
if(subtxt)
{lbl.Text = subtxt; oldTitlePos = sec;}
else
{ if(sec - oldTitlePos > persistTextSec) lbl.Text = "";}
}
window.setTimeout("timerCompleted()",100);
}

//Error handler
function Err(a,z)
{alert(z.errorCode+" "+z.errorMessage);}

The ‘Init’ function get called when the plugin loads. It initializes global variables and sets off a javascript timer. Though the timer is triggered every 100 millisecond, subtitles can only be changed per second. When the timer elapses ‘timerCompleted’ is called. It simply pulls out the subtitle corresponding to current position (in seconds) of the video and draws it on top of the video. Since we care of showing subtitles with only second accurracy, we round off the current position of video and get the corresponding subtitle text (since it turns out to be a floating point number). The ‘persistTextSec’ value is number of seconds a subtitle should continue to show on the screen, if no subtitles are found for consequtive seconds. If you want to simply test subtitling for long video, then you can use a javascript loop to initialize subtitle array to dummy strings

//Intializes subtitles with dummy strings
//for first hundred seconds of playback.
for(i=0;i<100;i++) {sub_en[i]="Subtitle at" +="" i;}="">

Creating HTML file

The HTML file is a very straightforward one. It includes ‘Subtitler.js’ (for the Subtitler) and ‘Subtitles.js’ (containing subtitles). The sequence of inclusion of these scripts is important. Then, all that is required is the code to embbed the Silverlight plugin itself.

<html>
<head><title>Subtitles Demo</title>
<script type="text/javascript" src="Subtitler.js"></script>
<script type="text/javascript" src="Subtitles.js"></script>
</head>
<body>
<object type="application/x-silverlight" height=240 width=320>
<param NAME="Source" VALUE="VideoPlayer.xaml">
<param NAME="MaxFramerate" VALUE="30">
<param NAME="Windowless" VALUE="0">
<param NAME="OnError" VALUE="Err">
<param NAME="OnLoad" VALUE="Init">
</object>
</body></html>

That was easy wasn’t it. If you use this technique in your please share it with me so that I can put a link here on my website. As always appreciation or criticsm are always welcomed.