情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

WPFで動画再生(2)

今回はコードの方です。詳細はコメントを見てください。

適切なコーデックを入れるとavi wmv mpeg mp4 mkv ts flvなどなど主要な動画ファイルは全て再生できます。

処理の重さはWMPと同じか少し重いくらいです。Flash Playerの軽いMP4再生に比べるとかなり差があります(当環境では(1024x768 x264+AAC).mp4を再生した場合WPFがCPU使用率20~25%、Flash Playerが10%前後だった)。

//ストーリーボード
Storyboard storyboard = null;

//ファイル名
string fileName = "";

//リピート再生
bool isRepeat = true;
//再生中か
bool isPlaying = false;

//「開く」メニューがクリックされた時
private void menuItemOpen_Click(object sender, RoutedEventArgs e)
{
    //ファイルを開くダイアログボックスを表示
    OpenFileDialog openFileDialog = new OpenFileDialog();
    openFileDialog.Filter = "動画ファイル(*.avi;*.wmv;*.mpg;*.mpeg;*.mp4;*.mkv;*.m2ts;*.flv)|*.avi;*.wmv;*.mpg;*.mpeg;*.mp4;*.mkv;*.m2ts;*.flv";
    if (openFileDialog.ShowDialog() != true)
        return;

    //ファイル名を保存
    fileName = openFileDialog.FileName;

    if (storyboard != null)
        Stop();

    //再生開始
    Start();
}

//メディアタイムラインの現在時間が無効化された時
void mediaTimeline_CurrentTimeInvalidated(object sender, EventArgs e)
{
    //ストーリーボードがnullでない(=再生する(している)動画が存在する)場合
    if (storyboard != null)
    {
        //タイムスライダの更新
        sliderTime.Value = mediaElement.Clock.CurrentTime.Value.TotalMilliseconds;
        //
        if (mediaElement.Clock.CurrentTime.HasValue && mediaElement.Clock.NaturalDuration.HasTimeSpan)
            textBlockTime.Text = mediaElement.Clock.CurrentTime.Value.Minutes.ToString() + ":" + mediaElement.Clock.CurrentTime.Value.Seconds.ToString() + "/" + mediaElement.Clock.NaturalDuration.TimeSpan.Minutes.ToString() + ":" + mediaElement.Clock.NaturalDuration.TimeSpan.Seconds.ToString();

        //動画が終了している場合
        if (mediaElement.NaturalDuration.HasTimeSpan == true && mediaElement.Clock.CurrentTime.Value.TotalMilliseconds == mediaElement.NaturalDuration.TimeSpan.TotalMilliseconds)
        {
            //再生停止
            Stop();

            //リピート再生が有効になっている場合は、再生を繰り返す
            if (isRepeat)
                Start();
        }
    }
}

//再生を開始する
private void Start()
{
    //メディアタイムラインを作成
    MediaTimeline mediaTimeline = new MediaTimeline(new Uri(fileName));
    mediaTimeline.CurrentTimeInvalidated += new EventHandler(mediaTimeline_CurrentTimeInvalidated);
    Storyboard.SetTargetName(mediaTimeline, mediaElement.Name);

    //ストーリーボードを作成・開始
    storyboard = new Storyboard();
    storyboard.Children.Add(mediaTimeline);
    storyboard.Begin(this, true);

    //コントロールの有効化・変更
    sliderTime.IsEnabled = true;
    buttonPlay.IsEnabled = true;
    buttonPlayImage.Source = new BitmapImage(new Uri("Image/一時停止.png", UriKind.Relative));
    buttonStop.IsEnabled = true;

    //フラグを再生中に
    isPlaying = true;
}

//再生を停止する
public void Stop()
{
    //ストーリーボード停止・消却
    storyboard.Stop(this);
    storyboard.Children.Clear();
    storyboard = null;

    //コントロールの無効化・変更
    sliderTime.Value = (double)0;
    sliderTime.IsEnabled = false;
    buttonPlayImage.Source = new BitmapImage(new Uri("Image/再生.png", UriKind.Relative));
    buttonStop.IsEnabled = false;

    //フラグを待機状態に
    isPlaying = false;
}

//再生ボタン(一時停止ボタン)をクリックした時
private void buttonPlay_Click(object sender, RoutedEventArgs e)
{
    //停止中の場合、再生開始
    if (storyboard == null)
        Start();
    //再生中または一時停止状態の場合
    else
    {
        //再生中の場合、再生を一時停止
        //一時停止状態の場合、再生を再開
        if (isPlaying)
            storyboard.Pause(this);
        else
            storyboard.Resume(this);
        buttonPlayImage.Source = new BitmapImage(new Uri(isPlaying ? "Image/再生.png" : "Image/一時停止.png", UriKind.Relative));
        //フラグを反転
        isPlaying = !isPlaying;
    }
}

//停止ボタンをクリックした時
private void buttonStop_Click(object sender, RoutedEventArgs e)
{
    //再生停止
    Stop();
}

private void buttonRepeat_Click(object sender, RoutedEventArgs e)
{
    //フラグを反転
    isRepeat = !isRepeat;
    buttonRepeatImage.Source = new BitmapImage(new Uri(isRepeat ? "Image/リピート.png" : "Image/ノンリピート.png", UriKind.Relative));
}

//動画が開かれた時
private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
    //タイムスライダの最大値を動画の長さに設定
    sliderTime.Maximum = mediaElement.NaturalDuration.TimeSpan.TotalMilliseconds;
}

//タイムスライダがドラッグ開始した時
private void sliderTime_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
    //再生を一時停止(mediaTimeline_CurrentTimeInvalidatedの発生を防ぐ)
    if (isPlaying)
        storyboard.Pause(this);
}

//タイムスライダがドラッグ完了した時
private void sliderTime_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
    //シークする
    storyboard.Seek(this, new TimeSpan((long)Math.Floor(sliderTime.Value * TimeSpan.TicksPerMillisecond)), TimeSeekOrigin.BeginTime);

    //再生を再開
    if (isPlaying)
        storyboard.Resume(this);
}

//音量スライダの値が変更された時
private void sliderVolume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    //音量を設定
    if (mediaElement != null)
        mediaElement.Volume = sliderVolume.Value;
}

(終)

pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-C#, wpf