Práce s videem v Silverlightu 2.0

V tomto článku si představíme podrobněji práci s videem v Silverlightu 2.0. Na příkladu si postupně představíme způsob, jak plnohodnotně pracovat s videem. Výsledkem bude přehrávač umožňující streamování videa.
Seriál: Praktické užití Silverlight 2.0 (12 dílů)
- Praktické užití Silverlight 2.0: Data Binding 15. 12. 2008
- Praktické užití Silverlight 2.0: DataGrid 22. 12. 2008
- Praktické užití Silverlight 2.0: UserControl 29. 12. 2008
- Co zajímavého přínáší Silverlight toolkit 5. 1. 2009
- Silverlight toolkit a vizualizace dat 12. 1. 2009
- Jak na komponenty AutoCompleteBox a TreeView ze Silverlight toolkitu 19. 1. 2009
- Nástroje pro tvorbu layoutu v Silverlightu 2.0 a Silverlight toolkitu 26. 1. 2009
- Design se styly a šablonami v Silverlightu 2.0 2. 2. 2009
- Základy 2D grafiky v Silverlightu 2.0 16. 2. 2009
- Dynamicky generované komponenty v Silverlightu 2.0 3. 3. 2009
- Úvod do streamování médií v Silverlightu 2.0 16. 3. 2009
- Práce s videem v Silverlightu 2.0 1. 6. 2009
Nálepky:
V minulém článku jsme si popisovali základy práce s médii v Silverlightu. Na závěr článku jsme si vytvořili primitivní přehrávač videa. Naším nynějším cílem bude tento přehrávač vylepšit tak, aby splňoval základní kritéria, která jsou v současné době kladena na přehrávače videa na internetu.
Co máme od minula připravené a jaký bude postup vylepšování přehrávače
V minulém článku jsme si vytvořili primitivní přehrávač, který obsahoval tlačítka na spuštění, pozastavení a zastavení videa.
V dalších krocích si přidáme:
- Informace o délce videa
- Informace o pozici videa
- Informace o stavu stáhnutého videa
- Nastavení bufferu
- Umožnění nastavení pozice
- Ovládání hlasitosti
Informace o videu
Prvním naším krokem při vylepšování video přehrávače bude přidání několika informací o videu, které přehráváme. První informací, kterou si přidáme, bude ta o délce videa. Veškeré informace o videu budeme získávat při načtení videa. Využijeme tedy událost MediaElementu – MediaOpened.
XAML:
<MediaElement x:Name="MojeVideo"
Source="http://honza.zlubinaci.eu/video.wmv"
Height="250"
Width="350"
AutoPlay="False"
Margin="5"
MediaOpened="MojeVideo_MediaOpened"/>
<TextBlock x:Name="tb_delka"/>
C#:
//informace o videu
//
private void MojeVideo_MediaOpened(object sender, RoutedEventArgs e)
{
//
//delka videa
//
tb_delka.Text = MojeVideo.NaturalDuration.TimeSpan.ToString();
}
Výsledkem je přidání informace o délce trvání videa.
Ještě bychom mohli informaci o délce videa udělat trochu uživatelsky přívětivější. Vypíšeme tedy čas rozdělený na hodiny, minuty a sekundy. S dalšími informacemi nemá smysl uživatele zatěžovat. Dosáhneme toho pomocí jednotlivých atributů třídy TimeSpan
. Pro složení informace o délce použijeme StringBuilder
(jmenný prostor System.Text
).
C#
//informace o videu
//
private void MojeVideo_MediaOpened(object sender, RoutedEventArgs e)
{
//
//delka videa
//
StringBuilder sb = new StringBuilder();
sb.Append("Délka videa: ");
sb.Append(MojeVideo.NaturalDuration.TimeSpan.Hours);
sb.Append(" hodin ");
sb.Append(MojeVideo.NaturalDuration.TimeSpan.Minutes);
sb.Append(" minut ");
sb.Append(MojeVideo.NaturalDuration.TimeSpan.Seconds);
sb.Append(" sekund");
tb_delka.Text = sb.ToString();
}
Výsledek:
Informace o aktuální pozici videa
Pro zobrazení této informace využijeme hned dvou variant. První variantou bude zobrazení pozice videa pomocí textu (stejně jako u informace o délce videa). Druhou variantou je zobrazení pozice pomocí Slideru
. Tento Slider
nám v další části poslouží i k posouvání pozice.
Informace o pozici pomocí textu
Tohle je věc, která není v Silverlightu řešena zrovna nejlíp. Pro tento případ nám chybí nějaká událost, na kterou bychom jednoduše mohli naši funkcionalitu navléknout. Potřebovali bychom nějakou událost, která by se vyvolala pokaždé, kdykoli by se pozice změnila (to je ten problém, ona se mění neustále). Nicméně, taková událost u MediaElementu
chybí, proto si vytvoříme pomocníka, který nám tuto funkcionalitu bude suplovat – Timer
. Timer
je časovač, který jednou za nastavenou dobu vyvolá událost („tikne“). Timer
vytvoříme následovně:
C#:
//timer
//
System.Windows.Threading.DispatcherTimer dt = new System.Windows.Threading.DispatcherTimer();
Následně definujeme interval a vytvoříme obslužnou událost Tick:
C#:
//nacteni stranky
//
void Page_Loaded(object sender, RoutedEventArgs e)
{
//
//nastaveni timeru
//
dt.Interval = new TimeSpan(0,0,1);
dt.Tick += new EventHandler(dt_Tick);
}
Nesmíme zapomenout také Timer
spustit. To můžeme provést při stisknutí tlačítka Play. Provedeme to příkazem dt.Start();
.
Pokud mám takto vytvořený časovač, nic nebrání tomu, abychom do jeho obslužné události vepsali funkcionalitu pro zobrazení informace o pozici.
XAML:
<TextBlock x:Name="tb_pozice"/>
C#:
//tiknuti
//
void dt_Tick(object sender, EventArgs e)
{
//zjisteni pozice
StringBuilder sb = new StringBuilder();
sb.Append("Pozice videa: ");
sb.Append(MojeVideo.Position.Hours);
sb.Append(" hodin ");
sb.Append(MojeVideo.Position.Minutes);
sb.Append(" minut ");
sb.Append(MojeVideo.Position.Seconds);
sb.Append(" sekund ");
tb_pozice.Text = sb.ToString();
}
Nyní si přidáme druhou variantu zobrazení informace o pozici videa. Použijeme k tomu komponentu Slider
.
C#:
<Slider x:Name="sld_pozice" Height="300"/>
Pro obsluhu použijeme stejnou metodu našeho Timeru
. Logicky budeme Slider
ovládat tak, že si vytáhneme při načtení videa celkovou sekundovou délku videa, tu nastavíme jako maximální hodnotu Slideru
.
C#:
//nastaveni Slideru Pozice
//
sld_pozice.Maximum = Convert.ToDouble(MojeVideo.NaturalDuration.TimeSpan.TotalSeconds);
sld_pozice.Minimum = 0;
sld_pozice.Value = 0;
a následně budeme přidělovat hodnotu Slideru
v podobě uběhnutých sekund.
C#:
sld_pozice.Value = Convert.ToDouble(MojeVideo.Position.TotalSeconds);
Ještě následně nesmíme zapomenout hodnoty nulovat, když je stisknuto tlačítko Stop.
Nyní pokud si přehrávač spustíme můžeme sledovat pozici, kde se video nachází.
Informace o stavu stáhnutého videa
Další užitečnou informaci, kterou budeme chtít uživateli sdělit, je, kolik z celkové velikosti videa se již stáhlo. Na zobrazení informace použijeme také komponentu Slider
, na které budeme ukazovat procentní podíl stažení. Slider
nastavíme pouze ke čtení, jelikož s touto informací se nedá manipulovat.
Pro obsluhu celého Slideru
využijeme událost MediaElementu
– <a> DownloadProgressChanged
.
XAML:
<TextBlock Text="Staženo"/>
<Slider x:Name="sld_stazeno"
Width="300"
Minimum="0"
Maximum="1"/>
C#:
//Ukazatel podilu stazeni
//
private void MojeVideo_DownloadProgressChanged(object sender, RoutedEventArgs e)
{
sld_stazeno.Value = MojeVideo.DownloadProgress;
}
Nastavení časové rezervy
V tuto chvíli nastala ta pravá chvíle na nastavení Bufferu (volně přeloženo jako – časová rezerva). Buffer je opravdu něco jako časová rezerva, kterou si nastavujeme proto, abychom dali staženým datům malý náskok oproti přehrávání. Běžně se může stát že dojde k hluchému místu v uživatelově připojení, a proto je dobré mít menší náskok.
Tuto časovou rezervu si definujeme přímo v těle MediaElementu
pomocí vlastnosti BufferingTime
. V naše případě u minutového videa nám bude bohatě stačit 5 sekund (u delších doporučuji až 20). Nyní náš MediaElement bude vypadat následovně:
XAML:
<MediaElement x:Name="MyVideo"
Source="http://honza.zlubinaci.eu/SL-InstallExperience.wmv"
Height="300"
Width="300"
AutoPlay="True"
DownloadProgressChanged="MyVideo_DownloadProgressChanged"
Loaded="MyVideo_Loaded"
BufferingTime="5"/>
Stavy
Nyní se můžeme podívat na stavy videa. Každý MediaElement
má několik stavů do kterých se může dostat (nejčastěji: Opening, Playing, Paused, Stoped, Closed, Buffering). V tomto příkladu si pouze budeme pro ukázku vypisovat stavy, ve kterých se naše video nachází.
Pojďme si tedy přidat jeden textBlock, ve kterém při každé změně stavu vypíšeme aktuální stav. Využijeme k tomu obslužné události MediaElementu
– CurrentStateChanged
. Informaci o stavu získáme z atributu CurrentState
.
C#:
//Informace o stavu
//
private void MojeVideo_CurrentStateChanged(object sender, RoutedEventArgs e)
{
tb_stav.Text = MojeVideo.CurrentState.ToString();
}
Nastavení pozice
Předposlední věcí, ke které se v tomto článku dostaneme, bude nastavování pozice při přehrávání videa. Dostáváme se tak k jedné ze silných zbraní práce s médii v Silverlightu. Již v minulém článku jsem vyzdvihoval přednosti protokolu MMS. Nyní si ukážeme na příkladu, co takové propojení přináší za obrovskou výhodu.
Protokol MMS nám vytvoří jakýsi tunel mezi přehrávačem, běžícím v prohlížeči a videem uloženým na serveru. Tímto tunelem se můžeme bez problémů dotazovat na jakoukoli pozici videa. Což nám umožňuje „skákat“ po částech videa, jak se nám zachce. Jednou ze zásadních výhod je, že můžeme „skočit“ i do části, která není dosud stažená. Následné stahováni bude probíhat od zvoleného místa.
Nyní si vše ukážeme na našem příkladě. Naším úkolem bude doplnit funkcionalitu Slideru
ukazující aktuální pozici. Doplníme jí o vlastnost, která nám umožní nastavovat pozici, kterou budeme chtít.
Celou akci nám bude zajišťovat událost volaná na Slideru
– <a> MouseLeftButtonUp
. V této události nastavíme pozici, od které budeme přehrávat. Toť vše!
C#:
// Nastaveni pozice
//
void sld_pozice_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
MojeVideo.Position = new TimeSpan(0,0,Convert.ToInt32(sld_pozice.Value));
}
(pro vyzkoušení je vhodné dát do zdroje nějaké větší video – v mém případě jsem použil screencast o Silverlightu).
Hlasitost
Konečně poslední věcí, kterou si dnes ukážeme, bude ovládání hlasitosti. Přibude nám jedno tlačítko pro Mute a jeden Slider
pro ovládání hlasitosti.
V obslužné události tlačítka Mute pouze ověříme, zda je již ztlumeno nebo ne a podle výsledku buď ztlumíme nebo zapneme zvuk. Pro tuto funkcionalitu využijeme atribut MediaElementu
– IsMuted
.
XAML:
<!--mute-->
<Button x:Name="bt_mute"
Content="Mute"
Height="20"
Width="100"
Margin="10"
Click="bt_mute_Click"/>
C#:
//Mute
//
private void bt_mute_Click(object sender, RoutedEventArgs e)
{
if (MojeVideo.IsMuted)
{
MojeVideo.IsMuted = false;
}
else MojeVideo.IsMuted = true;
}
Nyní si vytvoříme Slider pro ovládání hlasitosti. Pro obsluhu využijeme událost Slideru
– ValueChanged
. V této události pouze přiřadíme hodnotu Slideru
k hlasitosti.
XAML:
<!--Hlasitost-->
<TextBlock Text="Hlasitost"/>
<Slider x:Name="sld_hlasitost"
Width="300"
Minimum="0"
Maximum="1"
ValueChanged="sld_hlasitost_ValueChanged"/>
C#:
//Ovladani hlasitosti
//
private void sld_hlasitost_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
MojeVideo.Volume = sld_hlasitost.Value;
}
Závěr
V tomto článku jsme si ukázali, jak se jednoduše dá pracovat s videem v Silverlightu. Drtivá většina věcí, které jsme si ukázali, byly naprosto jednoduché a mnohým z vás možná odpověděli na otázku: „Proč je Silverlight tak často spojován se streamováním videa na internetu?“.
Co nás čeká příště?
V příštím článku dokončíme náš miniseriál o videu v Silverlightu, kdy bychom spolu dali našemu přehrávači vlastní vzhled. Zatím jsme vytvořili pouze funkční logiku. Abychom náš přehrávač začali používat na webu, měl by ještě nějak pěkně vypadat.