| Comments

Many have inquired if Silverlight Live Streaming had a replacement since the announcement of it being deprecated.  The SLS team blog pointed to Azure as a possible solution.  Since it doesn’t seem like anyone except James has really tried this, I decided to dust off my Azure account information and give it a try.

First, a note about SLS.  As I’ve said before I don’t think the offering was named very well from the start.  “Streaming” implies a specific technical connotation to most folks.  In fact, the media (or other files) hosted on SLS were never streamed as you might be thinking they were.  It was always a media file hosted on a content delivery network (CDN) and distributed delivered via basic progressive download…not streamed.  Now that we got that out of the way, let’s move on.

Setting up Azure

I’ll be honest.  I’m not sure how you go about getting an Azure token/invite at this point.  But you’ll need one.  Those who attended PDC08 already have access to one.  I believe MSDN subscribers will have access at some point but I don’t see it enabled on my account just yet either.  Bottom line is you’ll need an invitation token.  I cannot help you in this regard, so don’t even ask…I wish I could, but I can’t.

Once you have an Azure account, you want to create a Windows Azure Storage instance and give it a name.  I recommend not using special characters in the name as some of the tools I’m explaining below had problems with that.  I gave mine a simple name “timheuerblob1” and let it provision.

Azure Storage Account creation

Once you have that you’ll see a bunch of configuration screen details:

Azure configuration details

I’d recommend doing the following tasks first before you proceed.  In the bottom you’ll see an option to enable CDN.  For this purpose of hosting files/storage I recommend putting it on.  Additionally, this provisioning of CDN can take some time so do that first.  The next step is to configure your custom domain names (if you’d like) to map to the CDN and/or blob storage endpoints.  This is a simple/fast process but requires you to understand DNS entries and have the ability to modify your domain’s DNS information.  You can find step-by-step instructions at Steve Marx’s blog post here.  Without enabling this CDN feature, you really aren’t going to get the same level of scale as you did with SLS.

The key things you will need for the next part are the Primary Access Key and the Endpoints.  Make note of them.

Tools to upload content

Windows Azure blob storage is exactly what it says: storage.  Right now there aren’t any provided tools from Windows Azure to really manage the contents of the storage blob containers (unless I’m mistaken, and if so, please correct me).  There is an API for you to get access to and publish content, but if you’re wanting to use it like an SLS replacement you’re likely hoping for an easy tool to upload/manage the contents.

Enter two tools: Azure Storage Explorer and Cloud Storage Studio.  Both of these are Windows clients (WPF incidentally) and are installed on your machine.  Cloud Storage Studio actually has an online version if you wanted to use that offering.  I did not try that tool as I’m okay using a client tool.

Azure Storage Explorer is a CDDL licensed CodePlex project (which actually has no source code checked in at this point) provided by Neudesic – a Microsoft partner.  It is a simple UI that requires you to input your blob storage name, access key and endpoints in the Storage Settings dialog.  I initially had problems with this as my name had a special character in it.  I deleted my initial (and old) instance and recreated a new one in Azure and didn’t have problems after that.

Azure Storage Explorer screenshot

It was pretty simple to use and understand.  Create a container, upload stuff into it.  Done. 

Cloud Storage Studio is a commercial offering and unclear if it is going to be free always or just in CTP mode right now.  I couldn’t find information that jumped out at me on their site to let me know. 

Cloud Storage Studio screenshot

Cloud Storage Studio wouldn’t let me resize the window and that was frustrating.  Other than that it operated as expected, same thing – blob container select and upload.

While both tools were providing me basic blob container and upload capabilities, I felt the upload was slow (comparing to my Amazon S3 experience in creating a tool for content management).  I’m not sure if that was the app, Azure, or the nature of the API.  Also, neither tool seemed to enable me to set the content-type of the contents of the blob I was uploading.  I see this to be a problem for some.  The default of application/octet-stream isn’t going to work for all scenarios (for example I cannot use it to host XAPs and embed them because I would need to be able to set the content-type header).

Side note: Be sure to check out James Clarke’s CodePlex work on a Windows PowerShell script that will do encoding via Expression Encoder and then trigger a publishing plugin – such as one that will automatically upload to an Azure blob storage account.

Other than that, they served the need of filling the gap for a UI tool that already worked out the API stuff.

UPDATE: CloudBerry for Azure

I cannot believe I didn’t know about this one, since CloudBerry is what I use for my Amazon S3 storage and is AWESOME.  I was directed to CloudBerry for Azure Blob Storage (oddly by their competitor above) and I downloaded it immediately. 

CloudBerry Azure Blob Storage explorer

It met every expectation I had and has been the fastest client.  To me, the other clients must meet this bar of functionality *for blob storage interaction* to be considered for me to use.  The one thing it doesn’t have is custom CDN URI generation in its “WebURL” functionality – but I suspect this might be an Azure API limitation (I’m not familiar with the Azure API).

UPDATE 2: Cloud Storage Studio

Be sure to read the comments below from the team at Cloud Storage Studio.  They were kind enough to reach out to me to clarify some things above and listen to my feedback.  They are ACTIVELY looking to improve their product and provide value-add to Azure users/developers.  I sincerely appreciate when people reach out to their customers for feedback.  It’s been a great dialog with them helping them understand how I would use Azure and what my tools needs might be.

My Silverlight media test

Using my new found tools and some sample media files I uploaded a 720p high-def 30 second clip (30MB) to my blob storage account.  I then used put together a page with a simple player and pointed it to the Azure-hosted media.  I first pointed the media player to the basic blob endpoint.  The result of which is here: Non-CDN Hosted Media Playback.

Users who tested it with me said that the video buffered quite a bit and in remote areas (Australia) it took about 1.5 minutes to download the video.  This is again because this is still not streaming but just progressive download.

I then changed the media URL to the CDN version (after waiting 24 hours for propagation, etc. just to be sure) and have the CDN Hosted Media Playback.

I have to be honest and say that the CDN versions seemed to be better at consistent playback after the initial buffer of video (i.e., I received no more future buffering).  I’d be curious as to what other international people see on the CDN version as it would give a better view of how well the CDN delivers content globally.


I’m not sure if this will be a solution for everyone, but if you are looking for a Microsoft offering for cloud/CDN storage, give Azure a try.  NOTE: It is not a free service once it goes into production!  In fact, most CDN/cloud storage solutions you will find are not.  I’m currently using Amazon S3 for mine and have been for a long while.  It, too, is not free.  (Here’s the Amazon S3 CloudFront version of same media file.)  Again, here are the links to the three different video hosted locations/tests I did:

Either way, now that SLS is gone as a CDN/free hosted service where many were putting their media, you’ll have to look for another option.  Azure is one of those options.  Does it provide an automatic skin for a media player?  No.  You’ll have to do that yourself.  Is it streaming?  No, but neither was SLS.  Is there streaming/smooth streaming on the horizon?  I don’t know…but it would be cool if there was!

Hope this helps.

| Comments

The Encoder team has updated their Silverlight Streaming (SLS) plugin for Expression Encoder 2.  On the surface pretty much nothing has changed, but it essentially updates the ability to use the plugin to publish Silverlight 2 templates to SLS automatically without getting the random error that you’ve probably seen if you tried.

Since the new Silverlight 2 player templates are completely parameter-driven, which is awesome, it did present a small challenge for the plugin.  When you use the new plugin with a Silverlight 2 player template, you’ll notice that the resulting application uses a bootstrapping method to launch with initialization parameters.  This models (in fact I modeled my information) the bootstrap method I outlined in a previous post.

With the new plugin, for media applications at least, you don’t have to mess with creating your Javascript files or manifest files…the plugin does all that for you now in the pre-processing before uploading to the SLS service.  Because all of this is in there now, my process of making the SL2VideoPlayer a one-click template in Expression Encoder is now complete!  I’ve chosen to stick with my “minimum” fork of the template (no markers or caption support) because that’s the scenario I use mostly, just a player.  You can get the template files here.  Just unzip into the Encoder templates directory and it will show up as an option.  When used, the SLS plugin correctly translates all the settings into initParams for you.

Here’s the download links:

| Comments

Now that the Silverlight 2 Video Player is available from Codeplex, I wanted to make it a template for Expression Encoder.  I’ll attempt to articulate the steps below.  It’s actually pretty trivial.  In fact in the current incarnation, you have to throw some extra stuff in there you may not need :-).

Step 1 – Creating the template folder

While I’ve covered this in previous posts and this is also well documented in the Encoder SDK documentation.

First you’ll navigate to C:\Program Files\Microsoft Expression\Encoder 2\Templates\en and you’ll see the existing template folders.  The folders do not represent the name of the template in the Encoder UI, so don’t worry about that.  Create a folder here.  I called mine SL2VideoPlayer.

Step 2 – Creating the hosting page

Go into that folder and we’ll start creating some files here.  We’ll need the XAP from our media player (in my case VideoPlayer.xap) and simply place it in here.  We’ll also want to put a snapshot of our player here.  You can really name it to be anything, but I’m a fan of consistency and other templates call it preview.jpg so I stuck with that.  I recommend a proportionate image size.  You’ll notice the other templates don’t have this image anymore in Encoder 2.  That’s because their preview actually renders the player in Silverlight.  I’ll be honest here and tell you I haven’t messed around enough to know how to enable that, but my static preview image works and I’m sticking with that as it serves its purpose.

The main file we’ll need here is a hosting page.  I’ve called mine default.html again for consistency.  It is here where we have the magic happen.  In fact this step bleeds into the next 2 steps.  For now, you’ll want to create your hosting page that will host the Silverlight player.  This can be basic or elaborate…just create one.  In the next step we’ll make it wake up.

For me I just took the test page format provided to me by Visual Studio 2008 and the Silverlight project template.

Step 3 – Creating parameters for Encoder

Having a static page is nice, but doesn’t really help Encoder understand what we mean.  To our hosting page let’s add some parameters.  Encoder’s build process understands a certain set of parameters that are helpful for us.  It isn’t the intention of this post to emit them all to you, that’s what the SDK is for, but I’ll point out some key ones.  Let’s take a look at the ‘header’ of our hosting page:

   1: <!-- <[email protected] Options LaunchPage="true"$> -->
   2: <!-- <[email protected] Options Name="Silverlight 2 Video Player"$> -->
   3: <!-- <[email protected] Options TemplatePreviewImage="preview.JPG"$> -->

These are the first 3 lines of my default.html page.  They should be pretty self explanatory.  You can see now where the Encoder UI gets the template name from.  The next few lines immediately after this are interesting.  Here’s what my template looks like (after the first 3 lines above):

   1: <!-- <[email protected] Parameter Name="AutoPlay" Caption="Automatically start video when cued" Tooltip="Select to begin playback when video is loaded" Type="System.Boolean" Default="False" $> -->
   2: <!-- <[email protected] Parameter Name="EnableCaptions" Caption="Allow closed captions to show" Tooltip="Select to allow closed caption text over video during playback"Type="System.Boolean" Default="False" $> -->
   3: <!-- <[email protected] Parameter Name="Muted" Caption="Mute player on start" Tooltip="Select to begin playback in a muted state" Type="System.Boolean" Default="False" $> -->
   4: <!-- <[email protected] Parameter Name="MediaMarkers" Caption="Enable Media Marker Animations" Tooltip="Select to enable animations to appear when media markers are found" Type="System.Boolean" Default="False" $> -->
   5: <!-- <[email protected] Parameter Name="ScaleMode" Caption="Stretch Mode" Tooltip="Change the way the template is displayed on the page" Type="System.Enum" EnumValues="Profile Size=1,Stretch=2" Default="Profile Size" $> -->

Okay, these may need a bit more understanding.  Let’s dissect one of them a bit as the all are of type parameter.  First the Name – this is what will be known to your code later (in step 4) so this is really an internal name…not visible to the user.  The second attribute, Caption, will be seen to your user and should be descriptive, but concise.  Tooltip is, well, a tooltip…and if you don’t know what that is, maybe you shouldn’t be customizing templates?  Type is the data type of your parameter…these are standard .NET types like System.String, System.Boolean, etc.  The final attribute, Default, is exactly what it sounds like – providing a default value for the parameter.  At this point you may be asking yourself: How is the user providing input to these values? and that would be a great question.

You see, when you add parameters to your template they show up as advanced options to the template.  Let’s look at Encoder 2 after we’ve selected our template.  Notice the template name and then the expander decorator:

If you expand these advanced properties you’ll see your parameters.  Here’s my setup for the SL2VideoPlayer template:

Pretty cool, huh?  You can totally provide your users of your template the option to provide input parameters.  Now my params are pretty obvious but you could probably think of some other creative uses.  But we didn’t have to do anything to get some of this free UI goodness!  Now we have our template selectable and our users can provide certain parameters…let’s see how we can use them.

Step 4 – Reading the parameters in the template

We’ve got the input parameters, how do we use them?  Well for my input parameters, these directly translate to initParams for my Silverlight application.  However regardless there are some other things you can get other than parameters.  Again, I’ll defer to the full Encoder SDK, but since you are encoding a file, I’m guessing at least the output of that file is an important attribute you’ll want to be aware of.  Again, let’s take a look at other code in my default.html template where I use code to get at these parameters:

   1: <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" 
   2:     <$ if (TemplateParameter.ScaleMode == "1") { $>width="<$=PublishedItems[0].MediaItem.VideoSize.Width$>" 
   3:     height="<$=PublishedItems[0].MediaItem.VideoSize.Height$>"<$}else{$>width="100%" height="100%"<$}$>>
   4:         <param name="source" value="VideoPlayer.xap"/>
   5:         <param name="onerror" value="onSilverlightError" />
   6:         <param name="background" value="white" />
   7:         <param name="initParams" value="autostart=<$=TemplateParameter.AutoPlay$>,muted=<$=TemplateParameter.Muted$>,
   8:             captions=<$=TemplateParameter.EnableCaptions$>,markers=<$=TemplateParameter.MediaMarkers$>,
   9:             m=<$=PublishedItems[0].OutputFileName$>" />
  10:         <a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">
  11:              <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
  12:         </a>
  13: </object>

See some familiar code here?  the “<$>” decoration is instructing the Encoder build process that this is code to be executed.  What kind of code?  .NET baby.  My example is very, very simple here and in fact I’m just extracting attributes.  The SDK has examples of more advanced techniques should you need them.

You can see the use of TemplateParameter that enables me to get at the parameter configuration options that we’ve provided to the user.  I just retrieve them, can inspect them, etc.  Some of them I’m just passing in the parameter, others I’m acting upon.

The one thing that you’ll want to familiarize yourself with is the PublishedItems model.  This represents the Encoder job activities.  You can see that my reference actually uses an index of 0.  This is because Encoder supports encoding multiple files at once and your output could contain more than one file.  This could be helpful in creating a template that uses multiple media sources and you are creating a visual playlist feature.  For me, I’m just using one, so I grab the first item.  I can then reflect on properties of that published item such as name, video size of the media, etc.  A very helpful and powerful little scripting-looking language that can be leveraged to really customize your template.

Using this code we now have our default.html file that in the end will be complete and have all our HTML provided for us.  I should note that the attributes in the header of the page will not be emitted.

Step 5 – Additional File(s)

What is really cool is that the process looks at other files in your template to see if they need to be acted upon as well.  So if you have javascript or other files that might need to be dynamic based on output, you can use the same coding methods as above in other files – it doesn’t all have to live in default.html at all!

Step 6 – Prepare the template for Silverlight Streaming

At this point our template will work.  We can import a video media asset, choose our template and click Encode.  After encoding the start page will launch with our options passed in and render.  But what about the next step?  What if I wanted to upload to Silverlight Streaming Services to host my media and application.  Well, I know that there is already a plugin that allows a quick upload for this – the SLSPlugin.  How can we tap into this?  I thought that I’d be able to just click publish and it would work, but that isn’t the case.

First the plugin expects at least one XAML file to exist…and we have a XAP.  So trick one, create foo.xaml with nothing in it and put it in the template folder.  Done.

Second, it expects a manifest.xml file to exist.  This is because the plugin is packaging our template assets into a ZIP that Silverlight Streaming understands for multiple assets.  This requires a manifest definition file that is a part of that ZIP.  So I create a manifest.xml file and put it in my template directory.  Remember step 5?  In my manifest I have it with some code as well:

   1: <SilverlightApp>
   2:   <source>VideoPlayer.xap</source>
   3:   <version>2.0</version>
   4:   <name><$=PublishedItems[0].MediaItem.Name$></name>
   5:     <$if (TemplateParameter.ScaleMode == "1") {$>
   6:         <width><$=PublishedItems[0].MediaItem.VideoSize.Width$></width>
   7:         <height><$=PublishedItems[0].MediaItem.VideoSize.Height$></height>
   8:     <$}$>
   9: </SilverlightApp>

So my manfiest is dynamically generated based on the output as well.  This file is created as a part of the encode process and is not a part of the default.html file…so you can see an example of separate files being able to access the parameters as well as the PublishedItems collection as well.  Now that the file is created it can get packaged into the app!

However, with my implementation of SL2 Video Player I run into a snag.  You see the default.html page is great and we can use it and it supplies all of our needs because we are using initParams.  However SLS doesn’t use our hosting page.  It generates it’s own HTML hosting page and creates the Silverlight object using createObject.  This is fine except for one thing: it doesn’t currently support initParams.  Yes I know createObject does, but SLS hasn’t built in the support to use those yet.  So alas, my final step here for my particular use is broken :-(.  I’m working with the SLS guys to implement initParams support much easier.  I’d love to see it a part of the manfiest options so I could have:

   1: <SilverlightApp>
   2:     <source>VideoPlayer.xap</source>
   3:     <initParams>m=foo.wmv,captions=true</initParams>
   4: </SilverlightApp>

And then the solution would be complete and life would be glorious.  We’ll let you know when that happens.


In brief summary hopefully this let’s you see some of the options you have for still being able to use Silverlight 2 in your Encoder 2 workflow.  The SDK provides a way for us to get integrated into the encoding pipeline and do our customizations.  It’s simple to do and will only get better.  You can download my complete template example here.  Please note that this was based on an earlier build of the SL2 Video Player.  The project has been progressing and you can get the latest version of the player at the Codeplex project site.

| Comments

I’ve seen this issue a few times with people using the Manage Videos portion of Silverlight Streaming to directly upload a video file to be hosted.  Now with direct endpoints to the WMV files I’m seeing it a bit more.  Let me see if I can shed some light on this situation.

First, there is a distinction between uploading an application to Silverlight Streaming versus just a video.  What I’m going to discuss here is working with video only uploads.  If you didn’t know, you can directly upload just a video and Silverlight Streaming will host that file and create a Silverlight player experience for you as well (if you want it).

Okay, now on to the issue.  It is important to note that there are specific size limitations of videos with Silverlight Streaming services.  If you are trying to go beyond those size limitations your issue could be that right away.  The video file size must be smaller than 105MB.  Moving on…

Some of you may have attempted to upload a video and then directed to the page that shows the video processing and seen a “Video cannot be processed” message. 

Your issue could be related to what I’ll explain here.  It’s a bug.  We released the Silverlight Streaming transcoding (upload video turnkey only) service when Expression Encoder 2 was not yet released.  When Encoder 2 shipped, we realized that it wasn’t playing nice (the outputs rather) with the transcoding service.  We have to fix this and are working on it.  If you are taking a video source, running it through Expression Encoder 2 and then trying to upload that resulting video, you may be hitting this issue.

One thing to note, is that the “upload video” is a transcoding service.  So if you already have a VC-1 (or Silverlight capable) media format WMV, there really is no need to use the upload video portion.  You already have a high-quality encoded format and don’t need to transcode that again.  So how do you get it up there if this issue exists?  A few ways.

Option 1 – Upload an Application with a manifest

You can package the video file up with an application and use the Manage Applications functionality to upload that content.  You can use one of the Encoder templates if you’d like as well.  Even though you may not need the extra files, that is okay, because you can still have an endpoint to your WMV if that is what you want.  Since we don’t have the Silverlght Streaming Publish plug-in for Expression Encoder 2 complete yet (it is coming), here is a workaround on how to create those packages.

Option 2 – Upload the file direct with the API

While maybe not flexible for some, you can upload the file as an application directly using the API which doesn’t require a ZIP format for this purpose.  More information on the methods and API you would need can be found here.  The API is a WebDAV-based API for managing applications.

Option 3 – Name your WMV file to ‘video.wmv’ and upload as an application

Before you do any operation rename your file to ‘video.wmv’ and then go to the Manage Applications area of Silverlight Streaming.  Create a new application and give it a name, then in the next screen upload the ‘video.wmv’ file you just renamed.  After completion you can go to the Manage Videos section of the administration site and see your video.

We understand this may be a problem for some of you and are doing our best to address it as soon as possible.  Please note this is only an issue for Expression Encoder 2 file outputs that are attempting to be uploaded via the Silverlight Streaming transcoding service (aka Manage Videos) section.

Hope this helps!

| Comments

In my previous post about cross-domain policy files I received some comments about whether or not cross-domain access is allowed on Silverlight Streaming.  I think really this is two questions that I'll try to clarify here.

What is Silverlight Streaming?

For those who don't know, Microsoft provides anyone with an account to "stream" Silverlight applications for free.  We'll give you 10GB of space to put your Silverlight applications.  There are some limitations, which you can read about in the service.  The "streaming" name has confused some.  It isn't only a "where can I put media files" location, but is a service to "stream" your entire Silverlight application.  You can have a media player, or a hello world textbox...no matter.  If you haven't checked it out, sign up.

Does Silverlight Streaming support cross domain calls from Silverlight?

This really has to do with the Silverlight Streaming API.  Silverlight Streaming provides an API to manage your applications.  You can perform various activities on your Silverlight Streaming account through this API such as managing your applications, requesting files, etc.

Now I'm not sure why you would want to access the API from a Silverlight application, but I will say that the in order for this to happen (as noted in my post about cross domain access), the service would have to host a policy file at the end point.  Silverlight Streaming currently does not have that policy file.

Can my application hosted in Silverlight Streaming access cross domain services?

This is what I think the question really is in the comments.  Yes.  Provided that the service you are accessing has a clientaccesspolicy.xml file at the root of the site, then yes it could.  I whipped up a quick DataGrid sample and put it on my Silverlight Streaming account.  This is a Silverlight 2 application (xap) that calls the MSN Video POX service via a WebClient call.  I take the information and bind it to a DataGrid.  So this application below is hosted in Silverlight Streaming, calling a 3rd party service (which has a policy file enabled) and embedded within my blog post here.

I hope that makes it a little clear that yes you can do this with your apps.

How did you get a Silverlight 2 application on Silverlight Streaming?

Very easily.  Just a bit after MIX08, the SLS team added support for Silverlight 2 Beta 1 applications.  You can read about it here, but here is the manifest I used for the application you see above:


I added that manifest.xml and my StreamingCrossDomain.xap file to a zip, uploaded it to my account and done.

Hope this helps!