Silverlight でビデオの巻き戻し・早送り

Published 24 September 09 04:33 PM | hiroyuk 

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) とプログレスバーが配置されているとします。

image

コードビハインドは以下のようになります。キモは赤字にした 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;
 
}
}

Filed under:

Comments

No Comments
Anonymous comments are disabled

About hiroyuk

マイクロソフト㈱エバンジェリスト。北海道大学理学部物理学科卒。リアルタイム3Dグラフィックスを専門とし、グラフィックスやシェーダに関する技術文章を執筆・講演。 DirectX SDK日本語ドキュメントの開発に携わるとともに、Windows Presentation Foundation プログラミング(オーム社)、Game Programming Gemsシリーズ、リアルタイム レンダリング第2版(ボーンデジタル)、Texturing & Modeling, A Procedural Approach などを翻訳・監修、XAMLプログラミング(ソフトバンク クリエイティブ)を執筆。趣味は薪割り。

Search

This Blog

DirectX 情報

Silverlight 情報

Windows 情報

WPF 情報

並列コンピューティング情報

著書

Syndication

Page view tracker