web-dev-qa-db-ja.com

AVPlayerの上にボタンを描画します

ビデオの上にラベルまたはボタンを描画する必要がありますrelay next previous , leave comment。ビデオのリストにはそれがあります。ユーザーがテーブルから1つのアイテムを選択したら、それを再生する必要があります。プレーヤーの再生が終了すると、それらのボタンまたはラベルがビデオの上に表示されます。

これが私のコードです:

comPlayerControl = AVPlayerViewController()

if let player = comPlayerControl {

    let videoURL: String = "http://cdnapi.kaltura.com/p/11/sp/11/playManifest/entryId/"+selectedSubmission.transcodeRefId+"/format/applehttp/protocol/http/a.m3u8"
    let playerItem = AVPlayerItem(URL: NSURL(string: videoURL)! )
    commmentPlayer = AVPlayer(playerItem: playerItem)
    player.player = commmentPlayer
    player.view.frame = videoCell.frame
    player.view.sizeToFit()

    player.showsPlaybackControls = true
    NSNotificationCenter.defaultCenter().addObserver(
        self, 
        selector: #selector(CommentsTableViewController.playerDidFinishPlaying(_:)),
        name: AVPlayerItemDidPlayToEndTimeNotification, 
        object: playerItem
    )

    comPlayerControl.delegate = self
    videoCell.addSubview(player.view)
}

func playerDidFinishPlaying(note: NSNotification) {
    print("Video Finished")
    let DynamicView=UIView(frame: CGRectMake(100, 200, 100, 100))
    DynamicView.backgroundColor=UIColor.greenColor()
    DynamicView.layer.cornerRadius=25
    DynamicView.layer.borderWidth=2
    DynamicView.layer.zPosition = 1;
    comPlayerControl.view.addSubview(DynamicView)
}

このような要件

requirement image

11
Piraba

AVPlayerViewControllerを使用しているので、AlessandroOrnanoの回答のようにアプリケーションのウィンドウにアクセスする理由はありません。なぜ車輪の再発明をするのですか?すべてのAVPlayerViewControllerには contentOverlayView プロパティがあり、プレーヤーとコントロールの間にビューを配置できます。

まず、新しいAVPlayerItemを作成し、そのアイテムのAVPlayerItemDidPlayToEndTimeNotification通知をリッスンします。アイテムをプレーヤーにロードして、再生を開始します。

アイテムが完了すると、AVPlayerItemDidPlayToEndTimeNotification通知をリッスンするように指定したセレクターが呼び出されます。そのセレクターで、contentOverlayViewに直接アクセスし、ボタンを追加します。

一部のViewControllerまたはその他のオブジェクト:

let playerVC = AVPlayerViewController()

// ...

func setupPlayer {

    let playerItem = AVPlayerItem(...)
    playerVC.player?.replaceCurrentItemWithPlayerItem(playerItem)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(VC.itemFinished), name: AVPlayerItemDidPlayToEndTimeNotification, object: playerItem)
    self.presentViewController(playerVC, animated: true) { 
        self.playerVC.player?.play()
    }
}

func itemFinished() {
    let btn = UIButton(type: .System)
    btn.addTarget(self, action: #selector(VC.buttonTapped), forControlEvents: .TouchUpInside)
    self.playerVC.contentOverlayView?.addSubview(btn)
}

func buttonTapped() {
    print("button was tapped")
    // replay/comment logic here
}

コメント(および 拒否された編集 )に記載されているように、ボタンはcontentOverlayViewで機能しない場合があります。別の解決策については、 パイロの答え を参照してください。

AVPlayerViewControllerをサブクラス化して、サブクラスのインスタンス内ですべてを実行することもできますが、Apple 警告

AVPlayerViewControllerをサブクラス化しないでください。このクラスのメソッドのオーバーライドはサポートされておらず、未定義の動作になります。

15
JAL

Avplayerボタンを作成する最良の方法はここで説明されていると思います: AVPlayerとAVPlayerViewControllerを使用したIOS 8ビデオ再生

したがって、私はこれらの手順を優先して同意しますが、それでもこれらのボタンを追加したい場合は、self.windowに追加してみてください。

if let app = UIApplication.sharedApplication().delegate as? AppDelegate, let window = app.window {
        let myFirstButton = UIButton()
        myFirstButton.setTitle("test", forState: .Normal)
        window.addSubview(myFirstButton)
        ...
}
3

ビデオの上にボタンやその他のコンテンツを表示する方法として、AVPlayerLayerを検索することをお勧めします。

AVFoundation再生の進歩 WWDCプレゼンテーションを参照してください。

また、 AVFoundationSimplePlayer-iOS サンプルプロジェクトも確認してください。

基本的に、プレーヤーをホストするビューを作成し、ビューの背後にあるレイヤーをAVPlayerLayerにします。

class PlayerView: UIView {
    var player: AVPlayer? {
        get {
            return playerLayer.player
        }

        set {
            playerLayer.player = newValue
        }
    }

    var playerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }

    override class var layerClass: AnyClass {
        return AVPlayerLayer.self
    }
}
2
Chris Livdahl

あなたの質問とRamisのコメント/コードから私はあなたが試すことができるサンプルコードを作りました

[〜#〜] jal [〜#〜]で述べたように、contentOverlayViewはコントロールを表示するための最良のオプションです。 AVPlayerControllerのビデオですが、私のサンプルデモによると、contentOverlayViewには、AVPlayerControllerAVTouchIgnoringViewの前にUIView/contentOverlayViewがあり、これはcontentOverlayViewとのユーザー操作で問題になる可能性があります。

したがって、別の解決策は、AVPlayerViewControllerにオーバーレイビューを追加することです。

_func addContentOverlayView() {

    OverlayView.frame = CGRectMake(0,30,AVPlayerVC.view.bounds.width, 100)
    OverlayView.hidden = true
    OverlayView.backgroundColor = UIColor ( red: 0.5, green: 0.5, blue: 0.5, alpha: 0.379 )

    let btnNext = UIButton(frame:CGRectMake(AVPlayerVC.view.bounds.width - 60,0,60,44))
    btnNext.setTitle(">>", forState:.Normal)
    btnNext.addTarget(self, action:"playNext", forControlEvents:.TouchUpInside)
    //        btnNext.layer.borderColor = UIColor ( red: 0.0, green: 0.0, blue: 1.0, alpha: 0.670476140202703 ).CGColor
    //        btnNext.layer.borderWidth = 1.0
    OverlayView.addSubview(btnNext)

    let btnReplay = UIButton(frame:CGRectMake((AVPlayerVC.view.bounds.width/2)-40,0,80,44))
    btnReplay.setTitle("Replay", forState:.Normal)
    btnReplay.addTarget(self, action:"replayVideo", forControlEvents:.TouchUpInside)
    OverlayView.addSubview(btnReplay)

    let btnPrevious = UIButton(frame:CGRectMake(0,0,80,44))
    btnPrevious.setTitle("<<", forState:.Normal)
    btnPrevious.addTarget(self, action:"previousVideo", forControlEvents:.TouchUpInside)
    OverlayView.addSubview(btnPrevious)

    let btnComment = UIButton(frame:CGRectMake((AVPlayerVC.view.bounds.width/2)-70,40,140,44))
    btnComment.setTitle("Comments", forState:.Normal)
    btnComment.addTarget(self, action:"openComments", forControlEvents:.TouchUpInside)
    OverlayView.addSubview(btnComment)

    AVPlayerVC.view.addSubview(OverlayView);

}

func playNext() {
    prevItem = AVPlayerVC.player?.currentItem
    OverlayView.hidden = true
    commmentQueuePlayer.advanceToNextItem()
}

func replayVideo() {
    OverlayView.hidden = true
    AVPlayerVC.player?.currentItem?.seekToTime(kCMTimeZero)
    AVPlayerVC.player?.play()
}

func previousVideo() {
    OverlayView.hidden = true
    if prevItem != AVPlayerVC.player?.currentItem {
        if (commmentQueuePlayer.canInsertItem(prevItem!, afterItem:AVPlayerVC.player?.currentItem)) {
            //commmentQueuePlayer.insertItem(prevItem!, afterItem:AVPlayerVC.player?.currentItem)
            commmentQueuePlayer.replaceCurrentItemWithPlayerItem(prevItem)
            prevItem = AVPlayerVC.player?.currentItem
            replayVideo()
        }
    } else {
        replayVideo()
        //Else display alert no prev video found
    }
}

func stopedPlaying() {
    if prevItem == nil {
        prevItem = AVPlayerVC.player?.currentItem
    }
    OverlayView.hidden = false
}
_

初期設定では、AVPlayerController、AVQueuePlayerなどを設定します...その時点で、AVPlayerControllerにオーバーレイを追加できます

前のアイテムについては直接利用できるものはなく、ドキュメントによると、次のアイテムが再生されるとアイテムは削除されるため、replaceCurrentItemWithPlayerItemまたはinsertItem(item: AVPlayerItem, afterItem: AVPlayerItem?)のような2つのオプションがあります。

完全なコードを確認する必要がある場合は、次の場所から確認できます: https://Gist.github.com/Pyrolr/debb4fca8f608b1300e099a5b3547031

注:これはプロトタイプと同じで、すべての場合に完全に機能するわけではありませんが、必要な基本機能を理解するのに役立ちます。要件に基づいて改善/最適化

1
HardikDG