Silverlight & Streaming Media

July 20, 2008

Lately I’m getting a lot of questions what could be done with Silverlight in in terms of work with streaming media.

Today I’ll show what could be done. I’ve built very simple media player based on MediaElement object and prepared some stream to use in my application. The major focus of this post it to briefly show what could be done with stream in Silverlight and not how specifically do it. I’ll be glad to answer any specific questions there will be any.

First about the stream. I’ve tried to find on my laptop some media, which will be longer than a minute and will also compatible with Expression Encoder 2 formats. After some time I’ve found an 80’s music clip performed by Italian singer Sabrina. This music clip was processed in Expression Encoder 2 – I’ve added some markers and script command to the stream and encoded it.

image image

Basically, I’ve defined 4 types of markers/scripts: caption, poll, ADV (advertising) and NAME (general marker).

Now the application itself:

 

The application has very simple UI, and basic media player abilities. Thus, it is still able to stop/play/pause media stream, change volume and displays current position in stream.

The main thing this application does is processing the markers being received from stream. Each type of markers has it own logic. Depending on marker type I’m populating corresponding XAML object:

   1: private void media_MarkerReached(object sender, TimelineMarkerRoutedEventArgs e)
   2: {
   3:     //Add current marker to collection, which have ListBox bounded on.
   4:     Markers.Add(new MarkerData() { MarkerTime = e.Marker.Time.ToString(), MarkerType = e.Marker.Type.ToString(), MarkerText = e.Marker.Text.ToString() });
   5:  
   6:     switch (e.Marker.Type.ToString().ToLower())
   7:     {
   8:         case "caption":
   9:             txtCaptions.Text = e.Marker.Text.ToString();
  10:             txtCaptions.Visibility = Visibility.Visible;
  11:             double captionsPos = (mediaBox.Width - txtCaptions.ActualWidth) / 2;
  12:             txtCaptions.SetValue(Canvas.LeftProperty, captionsPos);
  13:             captionsTimer.Start();
  14:             break;
  15:  
  16:         case "name":
  17:             txtHint.Text = e.Marker.Text.ToString();
  18:             lastHint = e.Marker.Text.ToString();
  19:             ShowHint.Begin();
  20:             hintTimer.Start();
  21:             break;
  22:  
  23:         case "adv":
  24:             txtADV.Text = e.Marker.Text.ToString();
  25:             ShowADV.Begin();
  26:             advTimer.Start();
  27:             break;
  28:  
  29:         case "poll":
  30:             createPoll(e.Marker.Text.ToString());
  31:             pollTimer.Start();
  32:             break;
  33:     }
  34: }

Each received marker being added to MarkersHistory ObservableCollection, which have ListBox bounded to it. The binding are pretty simple, and I’m skipping it here…

The application generating the polls from poll string – adding dynamic XAML objects to pre-defined pool container, and subscribes to event which gives us a way to know how user reacted:

   1: private void createPoll(string poll)
   2: {
   3:     //Clear poll container from previous poll items
   4:     pollStack.Children.Clear();
   5:  
   6:     //Load poll XML which received from stream
   7:     System.Xml.XmlReader reader = System.Xml.XmlReader.Create(new StringReader(poll));
   8:  
   9:     XDocument document = XDocument.Load(reader);
  10:  
  11:     IEnumerable<XElement> childList = from el in document.Elements()
  12:                                       select el;
  13:  
  14:     //For each question in poll, generates known element
  15:     foreach (XElement e in childList)
  16:     {
  17:         XName att = XName.Get("type");
  18:         switch (e.Attribute(att).Value )
  19:         {
  20:             case "Checkbox": //Yes, yes! I know here is written CheckBox and I'm generating RadioButton... This was just a typo in I had no time to re-encode the media
  21:                 
  22:                 XName val = XName.Get("Value");
  23:                 IEnumerable<XElement> optionValues = from el in e.Descendants(val)
  24:                                                      select el;
  25:  
  26:                 foreach (XElement value in optionValues)
  27:                 {
  28:                     //In this sample I'm generating only RadioButton
  29:                     RadioButton option = new RadioButton();
  30:                     option.SetValue(RadioButton.NameProperty, "CB_" + pollStack.Children.Count);
  31:                     option.Content = value.Value;
  32:                     option.Margin = new Thickness(3);
  33:                     //Subscribing to event
  34:                     option.Click +=new RoutedEventHandler(option_Click);
  35:                     pollStack.Children.Add(option);
  36:                 }
  37:                 break;
  38:         }
  39:     }
  40:  
  41:     ShowPoll.Begin();
  42: }

Application XAML (along with full sources) are pretty simple and could been downloaded from here.

All animations done with simple storyboards for simplicity. There is 2 types of storyboards: “Show*” and “Hide*” – one for showing corresponding object, and one to hide it. “Show” Sotryboards being started at the time of corresponded object population, and “Hide” storyboard by timers, which defined how long specific type of object will stay visible.

Lunch the application on page, try it, and hope you will understand better what could be done with streams in Silverlight application.

As usual, will be glad to answer any question.

 

Full sources (including the music video) are here.

 

Enjoy,

Alex

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

one comment

  1. DaveCSFebruary 22, 2009 ב 10:20

    Great stuff!

    Download appears broken though.

    Thanks, Dave

    Reply