質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

3528閲覧

MediaElementとSliderでの動画再生アプリで、スマートに再生時間の取得・設定がしたい

tuyudaku

総合スコア75

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2021/10/13 08:08

現在動画再生アプリを作成しています。

MediaElementで動画の再生
Sliderでシークバーを実装しています。
また、00:10:15/00:30:00というような感じで、TextBoxで再生中動画の総時間と現在再生中の時間を表示しています。
他にも再生ボタン等もありますが、今回の質問には関係ないので割愛します。

MediaElementの再生時間(MediaElement.Position)の取得はBindingに対応していないため、
ビヘイビアを使用して、500msのタイマーで定期的にPositionを取得するようにしています。
また、Sliderによる再生箇所の変更・ユーザー指定による指定箇所へのジャンプの機能を実装するためにもビヘイビアを使用しています。

C#

1 /// <summary> 2 /// 再生時間バインド用プロパティ 3 /// </summary> 4 public static readonly DependencyProperty MediaPositionProperty = 5 DependencyProperty.RegisterAttached( 6 "MediaPosition", 7 typeof(long), 8 typeof(MediaControlBehavior), 9 new PropertyMetadata(0L, OnMediaPositionPropertyChanged)); 10 11 /// <summary> 12 /// MediaPositionPropertyのゲッター 13 /// </summary> 14 /// <param name="target"></param> 15 /// <returns></returns> 16 public static long GetMediaPosition(DependencyObject target) 17 { 18 return (long)target.GetValue(MediaPositionProperty); 19 } 20 21 /// <summary> 22 /// MediaPositionPropertyのセッター 23 /// </summary> 24 /// <param name="target"></param> 25 /// <param name="value"></param> 26 public static void SetMediaPosition(DependencyObject target, long value) 27 { 28 target.SetValue(MediaPositionProperty, value); 29 } 30 31 /// <summary> 32 /// 再生時間変更時処理 33 /// </summary> 34 /// <param name="sender"></param> 35 /// <param name="e"></param> 36 private static void OnMediaPositionPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 37 { 38 var mediaElement = GetMediaElement(sender); 39 mediaElement.Position = TimeSpan.FromSeconds(GetMediaPosition(sender)); 40 } 41 42 /// <summary> 43 /// タイマーTick処理 44 /// </summary> 45 /// <param name="sender"></param> 46 /// <param name="e"></param> 47 private static void TimerTick(object sender, EventArgs e) 48 { 49 SetMediaPosition(_mediaElement, (long)_mediaElement.Position.TotalSeconds); 50 }

このMediaPositionPropertyに対してViewModelで定義したプロパティをBindingすることで再生位置の取得を行っています。
また、SliderのValueに同じプロパティをBindingすることで、MediaElementの再生位置をそのままSliderに反映させて、
Sliderの位置を変えたときにMediaElementに反映できるようにしています。

C#

1// VM----------------------------------------------------------------- 2 /// <summary> 3 /// 再生箇所 4 /// </summary> 5 public long MediaPosition 6 { 7 get => _mediaPosition; 8 set => SetProperty(ref _mediaPositionManager, value); 9 } 10// VM----------------------------------------------------------------- 11 12// View--------------------------------------------------------------- 13<MediaElement x:Name="MediaPlayer" Source="{Binding MediaSource, Mode=OneWay}" 14 b:MediaControlBehavior.MediaPosition="{Binding MediaPosition, Mode=TwoWay}"> 15 16<Slider x:Name="SeekBar" Value="{Binding MediaPosition, Mode=TwoWay}"/> 17// View---------------------------------------------------------------

ただし、この実装方法だと少し気持ちの悪い動きになってしまいます。
タイマーによる定期的なMediaElement.Positionの確認時、ビヘイビアで定義したMediaPositionPropertyに対して代入することで、
BindingされているVMのMediaPositionに対して変更を行っていますが、タイマーによる再生位置の値がMediaPositionに代入されると、
その変更通知がビヘイビアに戻ってきてしまいMediaElement.Positionに対して代入を行ってしまいます。
この無駄な動きが気持ち悪い上に、再生時間が多少前後してしまったりしてしまうため動作に影響も出てしまっています。

動画再生アプリを実装する際にシークバーの実装はよくあることだとは思うのですが、皆さんはどのようにして実装を行っているのでしょうか?
どのように改善したらいいのか、教えていただけないでしょうか?
よろしくお願いいたします。

長くなってしまった上に、質問したいこともうまくまとめられていない気がしますが、
足りない情報があればすぐに捕捉させていただきますのでよろしくお願いします。

言語:C#(.NET 5.0)

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

動画再生アプリを実装する際にシークバーの実装はよくあることだとは思うのですが、皆さんはどのようにして実装を行っているのでしょうか?

個人的には「MediaPlayerElementはよ」という気持ちですね^^;
WinUI MediaPlayerElement · Issue #5172 · microsoft/microsoft-ui-xaml

その変更通知がビヘイビアに戻ってきてしまいMediaElement.Positionに対して代入を行ってしまいます。

シークバー(わたしはSliderよりProgressBarが好みです)のドラッグなんかを考慮すると、ドラッグ中はタイマーを止める必要がありますしユーザー操作と分けるのは仕方ないと思います(泥臭くなってきれいには書けないという意味)

結局Viewべったりな処理なので、あまり最初からMVVMにこだわっても仕方ないんじゃないかと思います。
ユーザーコントロール(理想はカスタムコントロール)に切り出して、まずコードビハインドでちゃんと動くようになってからビヘイビアなりを詰めていくとよさそうな気はします。

理想的にはMediaElementにアタッチするコントローラのようなものができたらうれしい(わたしはできてません^^;

わたしも何度かチャレンジしているのですが、全画面化(ツリー付け替え処理がいる)とか次の動画(何を基準に?)とか、汎用化しようとすると急に煮詰まってしまい結局お蔵入りを繰り返しています^^;

投稿2021/10/13 14:47

TN8001

総合スコア9244

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tuyudaku

2021/10/15 01:35

>個人的には「MediaPlayerElementはよ」という気持ちですね^^; なるほど...MediaPlayerElement使おうと頑張ってはいたのですが、 全然使えないな...導入の仕方間違ってるのか?と思っていたら、そもそも対応していないのですね... はよ... >ドラッグ中はタイマーを止める必要がありますしユーザー操作と分けるのは仕方ないと思います(泥臭くなってきれいには書けないという意味) やはりそうですか... とりあえず、無駄な代入が嫌だったので 別の処理の改修もかねて、MediaElementの現在の再生位置を通知するビヘイビアと MediaElementに再生位置を設定するビヘイビアを二つに分けました。 これがスマートかどうかは置いておいて、データの交通整理は出来たかな...とは思います! 回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問