W artykule tym, zmierzyłem się z encodingiem pliku video do formatu "lubianego" przez Silvelright-a oraz z wyświetlaniem otrzymanego filmiku w aplikacji. Dodatkowo, chciałem zaprezentować jak w prosty sposób możemy wyświetlić pasek ładowania oraz stanu filmiku.
Obrabiamy filmik
Ponieważ Silverlight jest technologią internetową (RIA), to z racji swoich ograniczeń musi nakładać na wyświetlane elementy pewne standardy. Jednym z nich jest np. brak wyświetlania filmów video w różnych formatach i o dowolnej wielkości (dla porównania, WPF nie ma z tym problemu). Nałożone wymagania ze strony Silverlight-a, zmuszają nas do wstępnego przerobienia plików video, zanim umieścimy go w aplikacji.
Obróbkę pliku video, najlepiej dokonać przy pomoc program "Expression Encoder". W artykule tym użyje "Expression Encoder 2 Beta", wersje tą można pobrać za darmo na stronie Microsoftu (link).
Po zainstalowaniu i uruchomieniu aplikacji "Expression Encoder 2 Beta", ładujemy plik video. Możemy to zrobić poprzez File->Import lub przeciągając plik video na ekran aplikacji. Mając już załadowany filmik, przechodzimy do menu po prawej, gdzie tak jak widać na załączonym obrazku, możemy zmienić ustawienia encodingu.
Opcji jest bardzo dużo ale dla potrzeb tego dema, w zakładce "Profile" wybieramy z rozwijanej listy video np. "Streaming 256k DSL (MP)". Każda opcja jest opisana w tooltip-ie i powoduje zmiany w jakości otrzymanego pliku. Przy każdej zmianie, program wylicza przewidywany rozmiar pliku wyjściowego.
Następnie wciskamy przycisk "Encode" i czekamy na rezultaty. Katalogiem wynikowym jest ten, z zakładki "Output". W katalogu tym, powinien pojawić się gotowy do wstawienia filmik.
Oczywiście program Expression Encoder nie służy tylko do konwersji video dla aplikacji Silverlight ale także posiada wiele innych rozbudowanych opcji.
Umieszczamy video w aplikacji Silvelrigth 2.0
Gotowy film, przerobiony przez Expression Encoder, należy dodać do aplikacji oraz wyświetlić. Aby wyświetlić wystarczy jedna linia kodu:
<MediaElement Source="videoName.wmv" AutoPlay="True"
/>
Natomiast, aby dodać film video do projektu mamy dwa sposoby:
- Poprzez dodanie do projektu oraz ustawienie w properties pliku video, opcji "Copy to Output Directory" na "Copy always", co zapewni nam ciągłe kopiowanie pliku video do katalogu ze skompilowanym plikiem .xap (można oczywiście kopiować ręcznie ale jest to uciążliwe)
- Drugim sposobem jest ustawienie w properties filmiku, opcji "Build Action" na "Resources". Efektem tego ustawienia jest wkompilowywanie filmiku w plik .xap, przez co zwiększamy znacząco jego wielkość. Im większy plik .xap tym wolniej będzie się uruchamiać aplikacja. Opcja ta nie jest zalecana, znacznie lepiej jest odpalić plik xap i zassać filmik już po uruchomieniu aplikacji Silverlight 2.0.
Pasek ładowania oraz stan filmu
Oprócz zwykłego wyświetlania filmu video na stronie, mamy także możliwości dostanie się i obsługiwania jego ładowania oraz stanu wyświetlania.
Aby tego dokonać, dodajmy do pliku xaml trzy prostokąty, które będą reprezentować pasek stanu oraz pasek ładowania.
<Canvas HorizontalAlignment="Left">
<Rectangle x:Name="ProgressRect" Opacity="1"
Stroke="#FF000000" StrokeThickness="2"
Width="448" Height="16"
Canvas.Left="5" Canvas.Top="10"/>
<Rectangle Opacity="0.3"
Fill="#FF000000"
x:Name="playingRect"
Width="0" Height="16"
Canvas.Left="5" Canvas.Top="10"/>
<Rectangle Opacity="0.3"
x:Name="downloadRect"
Fill="#FF000000"
Width="0" Height="16"
Canvas.Left="5" Canvas.Top="10"/>
</Canvas>
oraz StoryBord do obsługi czasu trawania filmu:
<Canvas x:Name="LayoutRoot" >
<Canvas.Resources>
<Storyboard x:Name="timer" Completed="timer_Completed"/>
</Canvas.Resources>
Dla kontorlki MediaElement dodajemy trzy metody:
MediaEnded="MediaElement_MediaEnded" MediaOpened="MediaElement_MediaOpened" DownloadProgressChanged="MediaElement_DownloadProgressChanged"
oraz ich implementacje w kodzie .cs:
bool isMediaOpened = false;
void Page_Loaded(object sender, RoutedEventArgs e)
{
timer_Completed(sender, e);
}private void MediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
timer_Completed(sender, e);
((MediaElement)sender).Stop();
((MediaElement)sender).Play();
}private void MediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
isMediaOpened = true;
}
private void MediaElement_DownloadProgressChanged(object sender, RoutedEventArgs e)
{
downloadRect.Width = Math.Floor(((MediaElement)sender).DownloadProgress * ProgressRect.Width);
}private void timer_Completed(object sender, EventArgs e)
{
if (isMediaOpened)
{
double percent = filmik.Position.Seconds / ((double)filmik.NaturalDuration.TimeSpan.Seconds);
playingRect.Width = Math.Floor(percent * ProgressRect.Width);
}
sekund.Text = filmik.Position.Seconds.ToString();
timer.Duration = new
TimeSpan(0, 0, 1);
timer.Begin();
}
A wiec, w kodzie xaml dodaliśmy trzy prostokąty (Rectangle), które będą reprezentować pasek ładowania oraz pasek stanu filmu (czas). Dodaliśmy takżę StoryBord który będzie się wywoływał co sekunde i atualizował stan prostokątów.
Dodaliśmy także metody, MediaElement_MediaEnded() obsługuje zakończenie trawnia filmu, robi Stop() i ponownie go włącza poprzez wywołanie Play(). Powstała także metoda MediaElement_MediaOpened, która przełącza flagę, gdy filmik zostanie ściągniety z serwera i włączy odliczanie czasu. Kolejna metodą jest MediaElement_DownloadProgressChanged (). Jest ona wywoływana gdy stan pobierania pliku video z serwera się zmienia, a więc podczas łądowania strony. No i ostatnią z metod jest timer_Completed. Obsługuje ona przesuwanie prostokąta odpowiedzialnego za wyświetlanie czasu filmu. Szerkość prostokąta jest zmieniana, a StoryBord zostaje uruchomiony na kolejną sekunde.
Proste i fajnie wygląda.
Demo:
Source Code:
Resources:
- http://geekswithblogs.net/Silverlight2/archive/2008/03/06/silverlight-2.0-beta-1-uri-inconsistency.aspx - blog Imrana Shaika
- http://www.microsoft.com/expression/products/download.aspx?key=encoder2beta – Microsoft Expression Encoder 2
Jacek Ciereszko


























