[Xamarin.Mac] AVPlayerViewで動画を再生してみました

2020.12.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

CX事業本部の平内(SIN)です。

Xamarin.Macを使用すると、C#でネイティブなMacのアプリが作成可能です。 ここでは、私自身がXamarin.Macに入門して学習した事項を覚書として書かせて頂いています。

今回は、動画ファイルを再生してみました。

2 画面設計

Interface Builderでの画面設計です。

最初に、ウインドウいっぱいに上下分割のSplit Viewを置きました。そして、上側のビューの高さを固定し、NSButtonを配置しOutletを作成しました。

Split Viewの下の方のViewに名前(MainView)を付けて、サブクラス化しました。これは、ウインドウのサイズ変更に動画を追従させるためです。

3 AVPlayerView

AVPlayerViewを使用する手順は、概ね以下のとおりです。

  • AVPlayerViewの生成
  • AVPlayerを生成し、AVPlayerに関連付ける
  • AVPlayerViewを表示したいビューのサブクラス化する(AVPlayerView自体をビューにすることも可能です)
  • AVPlayerで再生を開始する

下記は、Openボタンを押された際に、ファイルを開くダイアログを表示し、選択された動画ファイルでAVPlayerViewを初期化しているコードです。

public partial class ViewController : NSViewController {

    AVPlayerView PlayerView = new AVPlayerView();

    public override void ViewDidLoad() {
        base.ViewDidLoad();

        // Openボタンがクリックされた時のイベント追加
        OpenButton.Activated += OpenButton_Activated;
    }

    // Openボタンを押された時の処理
    private void OpenButton_Activated(object sender, EventArgs e) {

        // 動画ファイルの選択
        var dlg = NSOpenPanel.OpenPanel;
        dlg.CanChooseFiles = true;
        dlg.CanChooseDirectories = false;
        dlg.AllowedFileTypes = new string[] {"mov"};

        if(dlg.RunModal() == 1) {
            var url = dlg.Urls[0];
            if(url != null) {
                var fileUrl = new NSUrl($"file:///{url.Path}");

                // AVPlayerを生成して、PlayerViewに関連付ける
                var player = new AVPlayer(fileUrl);
                PlayerView.Player = player;

                // PlayerViewをのViewサイズを合わせてサブビューに追加する
                PlayerView.Frame = View.Bounds;
                View.AddSubview(PlayerView);

                // 再生を開始する
                player.Play();

            }
        }
    }

    //・・・略・・・

4 NSViewのサイズ変更通知

上記のコードでは、ウインドウのサイズが変更されても、再生される動画のサイズが追従しません。

今回は、サブクラス化したMainViewで、Notifications.ObserveFrameChangedでイベントハンドラを公開しました。

public partial class MainView : NSView {

    public event EventHandler OnFrameChagned;

    public MainView(IntPtr handle) : base(handle) {

        Notifications.ObserveFrameChanged(this,(sender, e) =>
        OnFrameChagned?.Invoke(this, EventArgs.Empty));
    }
}

公開されたイベントをViewController側で処理しています。

<br />public partial class ViewController : NSViewController {

    //・・・略・・・

    public override void ViewDidLoad() {
        base.ViewDidLoad();

        // ウインドウサイズが変更された時のイベント追加
        (View as MainView).OnFrameChagned += ViewController_OnFrameChagned;
    }

    private void ViewController_OnFrameChagned(object sender, EventArgs e) {
        //ウインドウサイズが変更された場合に、PlayerViewのサイズを追従させる
        PlayerView.Frame = View.Bounds;
    }

    //・・・略・・・

5 最後に

今回は、動画ファイルの再生を試してみました。

実は、Interface Builderでは、AVKit Player Viewというのがあり、これを使えば、制約だけで、リサイズ時の処理なども必要ないかも知れません。

すいません、実は、ちょっと使いこなせなくて、見送った感じです。