Silverlight Streaming to Your Silverlight Player - Content Only

1/18/2008 10:28:00 AM

Silverlight streaming is pretty cool stuff.  4GB of free space to store your videos and associated Silverlight player files.  Kind of a mini-MyYouTube sort of thing.  Of course, the 10min/22MB size limitation is a negative, but I've been able to work around it for most of the stuff I have done with my Spaghetti Code videos.

My current project (that has gotten in the way of continuing work on my Spaghetti Code 'Almost Live' project - never enough time) is to create a video "broadcasting" interface so folks can get a slick experience to find and view videos.  As part of this, I really wanted to just pull .wmv content off of the Silverlight Streaming infrastructure.  I didn't want to go the iframe route or some other solution that required me to actually host a Silverlight .xaml interface on Silverlight Streaming. 

The Silverlight Streaming SDK references that scenario, but the SDK is pretty sparse on examples or even detail more than just a vague blurb and a snippet of out-of-context code (at least for someone just digging around out of context ;-) ).  The other thing I wanted to do was leverage all of the great templates and javascript that Expression Encoder provides so I could minimize the amount of code I would have to write to get my Silverlight player working.  That was another scenario that did not have a lot of documentation. 

So, my intrepid readers (all four of you - yes Slickthought readership is on the upswing!), here are the steps to stream *.wmv content to your own Silverlight player.  I'm assuming you already have a Silverlight Streaming account and have posted some content out there that you would like to access.

1.  Using Expression Encoder, encode your content and use Encoder to create a Silverlight player for you.  You can open that project file associated with the output and modify in Blend.  See Tim Heuer's blog post on using Expression Encoder templates as the foundation for your own Silverlight player.  If you don't have Expression Encoder, that is fine, but I have based my solution on some of the files it spits out.  If you are building your own player from scratch, you should be able to figure out what you need to do since Expression Encoder uses some of the same files that are provided as part of the Silverlight SDK (that I assume you are using or else you are one sick javascript writing puppy).

2.  Now we need to modify the default output of our Silverlight project to access content directly from the Silverlight Streaming service.  Step one is to change where our silverlight.js file is being downloaded from. 

a) Open default.html

b) Find <script type='text/javascript' src="Silverlight.js" mce_src="Silverlight.js"></script> and change it to <script type='text/javascript' src="http://agappdom.net/h/Silverlight.js"></script>.  This downloads a version of the silverlight.js file that allows us to instantiate our Silverlight object with a different method that we can configure to access content from Silverlight Streaming instead of a normal URL.

3. Next up, we need to update out startplayer.js file.  The first thing we want to look at is function StartPlayer_0(parentId).  It originally looks like this

function StartPlayer_0(parentId) {
    this._hostname = EePlayer.Player._getUniqueName("xamlHost");
    Silverlight.createObjectEx( {   source: 'player.xaml',
                                        parentElement: $get(parentId ||"divPlayer_0"),
                                        id:this._hostname,
                                        properties:{ width:'100%', height:'100%', version:'1.0', background:document.body.style.backgroundColor, isWindowless:'false' },
                                        events:{ onLoad:Function.createDelegate(this, this._handleLoad) } } );
    this._currentMediainfo = 0;     
}

as you can see, this function creates our Silverlight host by using the createObjectEx function.  For our purposes, we like this method of invocation because it allows us to specify what XAML we wanted hosted.  That way, even if the original content on Silverlight Streaming included it's own Silverlight player interface, we can use our own instead.  Unfortunately, createdObjectEx does not let us do this.  That is why we are using the other silverlight.js file, which allows us to modify our code as shown below:

function StartPlayer_0(parentId) {
    this._hostname = EePlayer.Player._getUniqueName("xamlHost");
    Silverlight.createHostedObjectEx( {   source: 'player.xaml?v=1',
                                        parentElement: $get(parentId ||"divPlayer_0"),
                                        id:this._hostname,
                                        properties:{ width:'100%', height:'100%', version:'1.0', background:document.body.style.backgroundColor, isWindowless:'false' },
                                        events:{ onLoad:Function.createDelegate(this, this._handleLoad) },
                                        initParams: 'streaming:/<silverlightAccountId>/<silverlightApplicationName>/somefile.wmv' } );


    this._currentMediainfo = 0;     
}

We change createObjectEx to createHostedObjectEx.  This allows us to still use our own XAML put also specify where the content comes from using initParam and the special syntax of stream:/...  Note that there is only a single forward slash following the colon, not two like in http://.  Following streaming:/ we put a Silverlight account number, followed by the application id that contains the content we want to get, and end with the physical file name of the media file.

4.  The last part is the part that was hard to figure out. If you are just hacking through the code like I was, it takes a little bit of time to figure out what needs to be fixed next.  If you look at the code inside of StartPlayer_0.prototype  you will see it ends with this._playNextVideo(); The code inside of _playNextVideo() function then calls the following function:

function get_mediainfo(mediainfoIndex) {
    switch (mediainfoIndex) {       

        case 0:
            return  { "mediaUrl": "somefile.wmv",
                      "placeholderImage": "someimage.jpg",
                      "chapters": [              
                                  ] };                                                               
        default:
             throw Error.invalidOperation("No such mediainfo");
     }
}

The issue is with the "mediaUrl" value.  By default, it points to the media file that Expression Encoder expects to be in the same web directory as the Silverlight player.  In our case, however, our content is actually in the Silverlight Streaming cloud.  It would seem that all you would have to do is change somefile.wmv to streaming:/<silverlightAccountId>/<silverlightApplicationName>/<somefile.wmv> and you would be good to go.  Unfortunately, life is not that easy.  streaming:/ is a place holder that the createHostedObjectEx function translates into an actual URL that points to the physical file in the Silverlight Streaming cloud.  That URL can be different each time you use streaming:/ even though you may be requesting the same file. 

There may be other ways to do this, and I suspect there are, but, I haven't taken the time to bone up on my javascript or the javascript libraries used by Silverlight, so I "brute forced" an answer based on some info I found on the web.  To fix the problem, I replaced the this._playNextVideo();  with a call to my own function this.loadStreamingVideo();.  The code for this function is added to the StartPlayer_0.prototype and is shown below:

_loadStreamingVideo: function() {
        var params = $get(this._hostname).InitParams;
        this._player.set_mediainfo(
            {"mediaUrl": params, "placeholderImage": "", "chapters": [] }
            );   
    }    

 

That's all there is to it. ;-)  I've attached a copy of startplayer.js here (as a .txt file) so you can take a look and compare the changes to the normal Expression Encoder startplayer.js file.  I'm working on getting SlickthoughtTV up and running so that people can easy browse the videos I am posting.  There are some great examples

Technorati Tags:

of doing this already, but I want to hack it up from scratch since these examples do a lot more than what I want and I want to learn something along the way.  I'll share how I did it in some videos once I get it done.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

SpaghettiCode

Related posts

Comments are closed

Powered by BlogEngine.NET 1.3.1.0
Theme by Mads Kristensen

About the author

Jeff Brand Jeff Brand

This is the personal web site of Jeff Brand, self-proclaimed .NET Sex Symbol and All-Around Good guy. Content from my presentations, blog, and links to other useful .NET information can all be found here.

E-mail me Send mail


Calendar

<<  May 2008  >>
MoTuWeThFrSaSu
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar

Twitter Updates

    Follow Me on Twitter

    Recent comments

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2008

    Sign in