Draw button on top of AVPlayer

I have to draw a shortcut or button on top of the video relay next previous, leave comment . There is a list of videos, as soon as the user selects one element from the table, it needs to be played. Once the player finishes playing, these buttons or cue should appear on top of the video.

Here is my code:

  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 like this

requirement image

+8
source share
4 answers

You are using AVPlayerViewController , so there is no reason to access the window of your application, as in the answer of Alessandro Ornano. Why reinvent the wheel? Each AVPlayerViewController has a contentOverlayView property that allows you to place views between the player and the controls.

First create a new AVPlayerItem and listen for the AVPlayerItemDidPlayToEndTimeNotification notification of this element. Download the item to the player and start playback.

As soon as the element finishes, the selector you specified to listen for the AVPlayerItemDidPlayToEndTimeNotification notification is called. In this selector, directly go to contentOverlayView and add your buttons:

In a sense, a controller or other object:

 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 } 

As stated in the comments (and the change is rejected ), the buttons may not work in the contentOverlayView . For an alternative solution, see Pyro's answer .

You can also subclass AVPlayerViewController and do everything inside an instance of your subclass, but Apple warns about this :

Not a subclass of AVPlayerViewController . Overriding methods of this class is not supported and leads to undefined behavior.

+13
source

I think the best way to make avplayer buttons is explained here: IOS 8 Play video using AVPlayer and AVPlayerViewController .

So, I prefer and agree with these instructions, but if you still want to add these buttons, you can try adding them to 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
source

I recommend looking for AVPlayerLayer as a way to display buttons and other content on top of your video.

See Achievements at the AVFoundation Playback WWDC View.

Also, see the AVFoundationSimplePlayer-iOS sample project.

Essentially, you create a view to host your player, and you create a layer after view in 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
source

Based on your question and Ramis comment / code, I made an example code that you can try

As mentioned by JAL, a contentOverlayView should be the best option for displaying the contentOverlayView video control in the AVPlayerController , but according to my demo contentOverlayView has no user interaction for buttons or other controls, as if you AVTouchIgnoringView in the 3D view, the AVPlayerController has AVTouchIgnoringView / UIView before contentOverlayView which may be a problem when the user interacts with contentOverlayView .

So another solution is to add an overlay view to the 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 } 

In the initial setup, we set AVPlayerController, AVQueuePlayer, etc ... at that time we can add an overlay to AVPlayerController

There is no direct availability for the previous item, and according to the documentation, the item will replaceCurrentItemWithPlayerItem insertItem(item: AVPlayerItem, afterItem: AVPlayerItem?) next item, so we have two parameters, for example replaceCurrentItemWithPlayerItem or insertItem(item: AVPlayerItem, afterItem: AVPlayerItem?)

If you need to check the complete code, you can check it at : https://gist.github.com/Pyrolr/debb4fca8f608b1300e099a5b3547031

Note. This is similar to the prototype, it does not work perfectly in all cases, but it can help you understand the basic functionalities that you need, and you can improve / optimize them according to your requirements.

+1
source

All Articles