Silverlight MediaElement Playing a Video stored in Windows Azure Blob Storage

There are two things that I want to show in this post:

  1. That you can use Silverlight in a Windows Azure Cloud Service
  2. That you can stream a movie progressively via http (more about that here) from Windows Azure Blob storage

The code is attached to this blog post.  Note that you will have to add and reference the Common and StorageClient projects that come as samples in the Windows Azure SDK.

What I did, is start with my Simple Blob Storage Walkthrough and adapted it to be a Video Store instead.

image

The top part of the app is really the same as in the Simple Blob Storage Walkthrough where another column was added to the GridView to provide play buttons.

When you hit play, the Silverlight control sitting underneath the form part of the page uses a MediaElement to play the video.  The video is played directly from its location in blob storage.

Adding Silverlight

Starting where the Simple Blob Storage Walkthrough finished off, lets add Silverlight to that project.  (this assumes that you have Silverlight Tools installed.  See here for more information)

Note that you may have to configure the mime type in IIS for Silverlight -- you'll know if you get a "Could not download Silverlight application"error:

Registering MIME type in development fabric

To ensure solutions containing Silverlight clients work correctly in the development fabric, please ensure that the MIME type for the Silverlight .xap extension is configured correctly in IIS.

1. Open Internet Information Services (IIS) Configuration Manager and select the server to manage (usually the top-level item on the left side)

2. Double-click MIME Types on the right side

3. Add an entry to map the .xap extension to the application/x-silverlight-app MIME type

Right click on the solution node in the Solution Explorer and select Add -> New Project.  Select "Silverlight Application":

image

Name the project VideoPlayer.

Select to "Link this Silverlight control into an existing Web site" and make sure that your Web Role is selected.  For this walkthrough I chose not to add a test page as I want to add the Silverlight control onto the existing page.

image

Solution Explorer will now look contain a Silverlight project and will look like this:

image

Open up Default.aspx and at the bottom of the page, just after the statusMessage Label you had from the previous walkthrough, add the following snippet to add the Silverlight control onto the page:

         <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <div style="height: 100%;">
            <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/VideoPlayer.xap" MinimumVersion="2.0.30523"
                Width="100%" Height="100%" />
        </div>

You also need to Register the Silverlight assembly otherwise the asp:Silverlight tag will come up as unknown.  You can do this at the top of Default.aspx, right under the "<%@ Page ..." tag:

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DownloadSite_WebRole._Default" %>
<%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls"
    TagPrefix="asp" %>

You may also have to add a reference to System.Web.Silverlight from your web Role (it can be found on the .Net tab of the add references dialog).

Open up Page.xaml and change the Background property of the Grid to "Green" so that we can see the control on the aspx page.  Hit "F5" to debug.

You should get the following:

image

Cool!  We have Silverlight!

Coding up the Silverlight Page

First we need a MediaElement to play the video.  Open up Page.xaml and add the MediaElement tag to the Grid as follows.  While we're at it, let's set the Width and Height of the Page to be 640 x 480 to make the video a little bigger and remove the Background attribute. 

Name the MediaElement "mediaPlayer".

 <UserControl x:Class="VideoPlayer.Page"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
    Width="640" Height="480">
    <Grid x:Name="LayoutRoot">
        <MediaElement x:Name="mediaPlayer"/>        
    </Grid>
</UserControl>

Note: A couple of issues I've been seeing (with the PDC October 2008 CTP) while developing Silverlight applications running on a Windows Azure Web Role: debugging doesn't seem to be working, the xap in the Web Role isn't always updating as expected resulting in a stale Silverlight UI on F5.  For the second problem, I found right clicking on the Silverlight project and hitting "Rebuild" then right clicking on the Web Role and hitting "Rebuild" before hitting F5 resolved the problem.  We're actively investigating both issues.

We'll just keep things really simple.  When the play button is clicked, we'll use Javascript to call a method on the Silverlight control passing in the URI that contains the video to play.

Let's add a scriptable method to the Page class in Page.xaml.cs:

 using System.Windows.Browser;
public partial class Page : UserControl
{
    {. . .}
    [ScriptableMemberAttribute]
    public void Play(string fileUriString)
    {
        if (!string.IsNullOrEmpty(fileUriString))
        {
            Uri fileUri = new Uri(fileUriString);
            mediaPlayer.Source = fileUri;
        }
    }
}

If you want to know more about the ScriptableMemberAttribute and how all this works, please see the MSDN article here.

The second part of making the control scriptable is to register the scriptable object.  That is done in App.xaml.cs in Application_Startup()

 using System.Windows.Browser;
private void Application_Startup(object sender, StartupEventArgs e)
{
    Page p = new Page();
    HtmlPage.RegisterScriptableObject("VideoPlayer", p);

    this.RootVisual = p;
}

Playing the Video

In order to play the video, we need to add a "play" button to each row of the GridView.

Open up Default.aspx and in the Columns for the GridView, add a column at the end for the Play button.  We'll use the <input/> tag for this as we don't want a postback to occur when we click the button (that will re-initialize the Silverlight control)

 <asp:TemplateField>
    <ItemTemplate>
        <input type="button" value="Play"/>
    </ItemTemplate>
</asp:TemplateField>

To that button, let's hook up an event handler when it gets clicked.  I did this programatically on the RowDataBound method on the fileView GridView control. 

The reason is that I wanted an easy way to pass the URI for the video to the Silverlight control.  In the RowDataBound event handler, I can get at the URI and pass it along as a parameter. 

The event handler will be run on the client side in Javascript.

In Default.aspx.cs in Page_Load(), register to handle the event:

 fileView.RowDataBound += new GridViewRowEventHandler(fileView_RowDataBound);

Then handle the event by adding the event handler for each of the <input/> buttons that will pass the URI as a parameter.

 void fileView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        FileEntry fe = (FileEntry)e.Row.DataItem;
        e.Row.Cells[3].Attributes.Add("onclick", "onGridViewRowSelected('" + fe.FileUri + "')");
    }
}

Finally, back in Default.aspx, we add the Javascript event handler that calls the scriptable method on our Silverlight control:

 <script language="javascript" type="text/javascript">
    function onGridViewRowSelected(fileUri) {
        var control = document.getElementById("Xaml1");
        control.content.VideoPlayer.Play(fileUri);
    }
</script>

Hit F5 to give it a try on the Development Fabric/Storage.  Upload a video sample (say from C:\Users\Public\Videos\Sample Videos) and then hit play.

One final thing to remember is the upload file size limit on the FileUpload control which is discussed in the Simple Blob Storage Walkthrough.  More likely you'll run into here with video files.

image

DownloadSite.zip