11

我必须在 video 上绘制一个标签或按钮relay next previous , leave comment。视频列表有它,一旦用户从表格中选择一个项目,它需要播放,一旦播放器播放完成,这些按钮或标签应该出现在视频的顶部

这是我的代码:

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)
}

像这样的要求

需求图片

4

5 回答 5

19

您正在使用AVPlayerViewController,因此没有理由像 Alessandro Ornano 的回答那样访问应用程序的窗口。为什么要重新发明轮子?每个AVPlayerViewController都有一个contentOverlayView属性,允许您在播放器和控件之间放置视图。

首先,创建一个新项目AVPlayerItem并监听AVPlayerItemDidPlayToEndTimeNotification该项目的通知。将项目加载到播放器中并开始播放。

AVPlayerItemDidPlayToEndTimeNotification项目完成后,将调用您指定用于侦听通知的选择器。在该选择器中,contentOverlayView直接访问并添加您的按钮:

在某些视图控制器或其他对象中:

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. 有关替代解决方案,请参阅Pyro 的回答

您还可以在子类AVPlayerViewController的实例中进行子类化并执行所有操作,但 Apple对此提出警告

不要子类化AVPlayerViewController。不支持覆盖此类的方法,并导致未定义的行为。

于 2016-04-04T19:15:45.940 回答
4

我认为制作 avplayer 按钮的最佳方法在这里解释:IOS 8 Video Playback using AVPlayer and AVPlayerViewController

所以,我更喜欢并同意这些说明,但如果您仍想添加这些按钮,您可以尝试将它们添加到 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)
        ...
}
于 2016-04-04T09:55:17.173 回答
4

我建议查找 AVPlayerLayer 作为在视频顶部显示按钮和其他内容的一种方式。

请参阅AVFoundation Playback 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
    }
}
于 2016-12-08T20:09:48.477 回答
3

根据您的问题和拉米斯的评论/代码,我制作了一个示例代码,您可以尝试

正如JAL所提到的,contentOverlayView应该是在它前面有/可能是用户与.AVPlayerControllercontentOverlayViewAVPlayerControllerAVTouchIgnoringViewUIViewcontentOverlayViewcontentOverlayView

所以另一种解决方案是在 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 上添加叠加层

对于上一个项目,没有直接可用的项目,并且根据文档,一旦播放下一个项目,该项目将被删除,因此我们有两个选项,例如replaceCurrentItemWithPlayerIteminsertItem(item: AVPlayerItem, afterItem: AVPlayerItem?)

如果您需要检查完整的代码,可以从以下位置进行检查: https ://gist.github.com/Pyrolr/debb4fca8f608b1300e099a5b3547031

注意:这就像原型一样,并非在所有情况下都能完美运行,但它可以帮助您理解您想要的基本功能,并且您可以根据您的要求进行改进/优化

于 2016-04-04T20:54:20.550 回答
0

检查下面的代码,我可以在叠加层上添加按钮以及正在调用按钮事件。

var playerViewController: AVPlayerViewController?
var OverlayView = UIView()    
    
private lazy var button1: UIButton = {
                    let selfType = type(of: self)
                    let button = UIButton(frame: .init(origin: .zero, size: .init(width: selfType.musicWidth, height: selfType.musicHeight)))
                    button.setImage(UIImage(named: "star"), for: .normal)
                    button.addTarget(self, action: #selector(button1DidSelect), for: .touchUpInside)
                    button.translatesAutoresizingMaskIntoConstraints = false
                    NSLayoutConstraint.activate([
                        button.widthAnchor.constraint(equalToConstant: selfType.musicWidth),
                        button.heightAnchor.constraint(equalToConstant: selfType.musicHeight)
                    ])
                    return button
                }()
        
override func viewDidAppear(_ animated: Bool) {
                    super.viewDidAppear(true)
                    guard let url = URL(string: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4") else { return  }
                    let player = AVPlayer(url: url)
                    self.playerViewController = AVPlayerViewController()
                    guard let playerViewController = self.playerViewController else { return }
                    playerViewController.player = player
                    
                    present(playerViewController, animated: true) {
                        playerViewController.player?.play()
                    }
                
                        self.addButtonsOnOverlayView()
                        self.playerViewController?.showsPlaybackControls = false
                        self.isHideOverlayControls = false
                }
    
     
    
@objc private func button1DidSelect() {
                print("button1 Selected")
                
            }
    
 private func addButtonsOnOverlayView() {
            
            guard let overlayView = self.playerViewController?.contentOverlayView else { return }
            
            if !self. button1.isDescendant(of: overlayView) {
                overlayView.addSubview(self.musicFirstButton)
                 self.playerViewController?.showsPlaybackControls = true
    
            }
            
               NSLayoutConstraint.activate([
                button1.leadingAnchor.constraint(equalTo: overlayView.leadingAnchor, constant: 20),
                button1.topAnchor.constraint(equalTo: overlayView.topAnchor, constant: 20),
            ])
          
        }
于 2020-08-12T21:33:59.840 回答