WPF の MediaElementには SpeedRatio プロパティがあるので再生速度の変更(早送り)が可能です、また再生速度については MediaClock や MediaTimeline を見ることもできます。しかし、Silverlight の MediaElement にはそのようなプロパティがなく、再生速度の調整はできません。
しかし Silverlight の MediaElement にも Position プロパティはあるので、メディア ファイルが正しくロードされていれば、任意の位置に移動できます。任意の位置に移動するとその位置での静止画が表示されます。
Silverlight ビデオ早送りのアイデアは、DispatcherTimer で100ミリ秒ごとにコールバックを呼び出し、N倍速のときN*100ミリ秒分だけPositionを変更するというものです。つまり4倍速早送りなら4*100ミリ秒、8倍巻き戻しなら -8*100ミリ秒だけPositionを進めるのです。
通常ビデオは30fps(33ミリ秒)なので、少しカクカクしますが、早送りなのであまり目立ちません。また、再生していないので早送り・巻き戻し中に音は出ません。
XAMLでは以下のように一連のボタンと MediaElement(myMediaElement) とプログレスバーが配置されているとします。
コードビハインドは以下のようになります。キモは赤字にした Position の変更です。
//速度レート internal enum Speed:int {back8=-8, back4=-4, pause= -1, stop = 0, play=1, forward4=4, forward8=8}; internal int currentSpeedRate = (int)Speed.stop; //タイマー internal DispatcherTimer timer = new DispatcherTimer(); //タイマーの時間幅を100ミリ秒に設定 internal static int timerinterval = 100; /// <summary> /// タイマーによるコールバック /// 倍速・巻き戻しの時、時間幅に速度レートを掛けて /// メディアのPositionを移動 /// </summary> private void timerCallback(object sender, EventArgs e) { if (currentSpeedRate < (int)Speed.pause || currentSpeedRate > (int)Speed.play) { myMediaElement1.Position += new TimeSpan(0, 0, 0, 0, timerinterval * currentSpeedRate); if (myMediaElement1.Position>myMediaElement1.NaturalDuration.TimeSpan || myMediaElement1.Position < new TimeSpan()) { myMediaElement1.Stop(); currentSpeedRate = (int)Speed.stop; } } myProgressbar.Value = (double)myMediaElement1.Position.Ticks; } /// <summary> /// メディアロード時にタイマーをスタート /// </summary> private void myMediaElement1_Loaded(object sender, RoutedEventArgs e) { timer.Tick += new EventHandler(timerCallback); timer.Interval = new TimeSpan(0, 0, 0, 0, timerinterval); timer.Start(); } /// <summary> /// 倍速・巻き戻しボタンが押された時のコールバック /// メディアをポーズにして速度レートを設定 /// </summary> private void Button_Click(object sender, RoutedEventArgs e) { myMediaElement1.Pause(); Button b = (Button)sender; switch ((string)b.Content) { case "<<8": currentSpeedRate = (int)Speed.back8; break; case "<<4": currentSpeedRate = (int)Speed.back4; break; case "4>>": currentSpeedRate = (int)Speed.forward4; break; case "8>>": currentSpeedRate = (int)Speed.forward8; break; } }