I've used AVPlayer and AVPlayerViewController.
let playerController = AVPlayerViewController()
var player = AVPlayer()
self.player = AVPlayer(URL: NSURL(fileURLWithPath:videoPath))
self.playerController.player = self.player
self.playerController.showsPlaybackControls = false
self.addChildViewController(self.playerController)
self.view.addSubview(self.playerController.view)
self.playerController.view.frame = ...
I can play video with controls but when video finish I have to hide controls.
I found the event if video finished and at that time I hide the control
func playerDidFinishPlaying(note: NSNotification) {
self.playerController.showsPlaybackControls = false
}
Problem: If user zoom out video and video finished then hide control so Is there any possibilty to back to original frame
Thank you so much in adv.
Related
I am using Fairplay implementation as per Apple's Fairplay Streaming sample code at https://developer.apple.com/streaming/fps/, although I tried to choose only parts that are related to Online Fairplay Streaming, not the persistence/offline playback. In the below code a video without Fairplay plays/pauses/seeks normally, but when I play a Fairplay protected video, only the video track behaves correctly.
Pausing playback won't stop the audio playback, changing audio track won't stop the previous audio track, so both plays together and perhaps the seek also does not work.
Besides this helper class below, I have AssetLoaderDelegate and AssetPlaybackManager from Apple's client sample code of FairPlay Streaming Server SDK https://developer.apple.com/streaming/fps/ and I have updated the code to handle SPC/CKC for our DRM keys provider.
Did I miss to implement some important part of the code to handle audio for FPS Streaming? Can you please point me into right direction? Many thanks.
class PlayHelper {
static let shared = PlayHelper()
fileprivate var playerViewController: PlayerViewController?
init() {
AssetPlaybackManager.sharedManager.delegate = self
}
// Play video without DRM
func playVideo(from urlString: String, at context: UIViewController) {
guard let videoURL = URL(string: urlString) else {
Log.error("Video URL can't be created from string: \(urlString)")
return }
let player = AVPlayer(url: videoURL)
let playerViewController = PlayerViewController()
playerViewController.player = player
context.present(playerViewController, animated: true) {
playerViewController.player?.play()
}
}
// Play FPS video
func playFpsVideo(with asset: AVURLAsset, at context: UIViewController) {
// Cleanup, should be done when playerViewController is actually dismissed
if self.playerViewController != nil {
// The view reappeared as a results of dismissing an AVPlayerViewController.
// Perform cleanup.
AssetPlaybackManager.sharedManager.setAssetForPlayback(nil)
self.playerViewController?.player = nil
self.playerViewController = nil
}
let item = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: item)
// Customize player
player.appliesMediaSelectionCriteriaAutomatically = true
let playerViewController = PlayerViewController()
playerViewController.player = player
self.playerViewController = playerViewController
context.present(playerViewController, animated: true) {
playerViewController.player?.play()
}
}
// Stop video
func stop() {
// Cleanup, should be done when playerViewController is dismissed
if self.playerViewController != nil {
// Results of dismissing an AVPlayerViewController, perform cleanup
AssetPlaybackManager.sharedManager.setAssetForPlayback(nil)
self.playerViewController?.player = nil
self.playerViewController = nil
}
}
}
// MARK: - Extend `PlayHelper` to conform to the `AssetPlaybackDelegate` protocol
extension PlayHelper: AssetPlaybackDelegate {
func streamPlaybackManager(_ streamPlaybackManager: AssetPlaybackManager, playerReadyToPlay player: AVPlayer) {
player.play()
}
func streamPlaybackManager(_ streamPlaybackManager: AssetPlaybackManager, playerCurrentItemDidChange player: AVPlayer) {
guard let playerViewController = playerViewController, player.currentItem != nil else { return }
playerViewController.player = player
}
}
I can also provide the code in AssetLoaderDelegate and AssetPlaybackManager if needed.
My bad. I called play() twice in the code above... Grrr.. Once when the presentation of the PlayerViewController finished and second time in the callback from AssetPlaybackDelegate that is triggered by KVO in AssetPlaybackManager. This way the player controls stopped playing the video, but most probably a second (audio) stream was still playing there. I removed the play() in playerReadyToPlay callback and now all the controls in the Player works as expected. I can pause, resume, seek, change audio tracks.
I am writing an app that need display different video according to the selection of the user. When the user select a video, the function playVideo will be called. And after the video finish playing, then the videoView will be hidden again.
My code is as follows:
var player: AVPlayer?
func playVideo(String: videoFile) {
self.videoView.isHidden = false
let videoURL: NSURL = Bundle.main.url(forResource: videoFile, withExtension: "mp4")! as NSURL
self.player = AVPlayer(url: videoURL as URL)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.videoView.frame
self.videoView.layer.addSublayer(playerLayer)
let duration : Int64 = 0
let preferredTimeScale : Int32 = 1
let seekTime : CMTime = CMTimeMake(duration, preferredTimeScale)
self.player?.seek(to: seekTime)
self.player?.play()
NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
}
#objc func playerItemDidReachEnd()
{
self.player?.pause()
self.videoView.isHidden = true
NotificationCenter.default.removeObserver(self)
}
However, with the code above, i have several question:
How to delete / deallocate the player gracefully? If just using my current code, will it consume lots of memory?
Every time, when the user press a button, the function playVideo will be called, and the corresponding player will be created and play. Is this the right way to do so? Is there any other method or more efficient way or elegant way to do so?
I did try to replace the code on creation of the player by the following, but it fails to play the video.
let playerItem: AVPlayerItem = AVPlayerItem(url: videoURL as URL)
self.player? = AVPlayer(playerItem: playerItem)
Thank you
I have a video player in an IOS App and I want to update the video when I click on a button, but I do not see how to manage this.
(Note : it's not a list of video within a queue)
Here is the code for adding the AVPlayer:
let url = NSURL.fileURLWithPath(path)
let player = AVPlayer(URL: url)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
..
..
self.ViewForVideo.addSubview(playerViewController.view)
self.addChildViewController(playerViewController)
player.play()
I have done like this : each time I want to change the video I create a new AVPlayer and affect it to the playerViewController.player like this
let url = NSURL.fileURLWithPath(path)
let player = AVPlayer(URL: url)
playerViewController.player = player
I'm playing a video:
let path = NSBundle.mainBundle().pathForResource("Video", ofType:"mp4")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = moviePlayer {
player.view.frame = self.view.bounds
player.prepareToPlay()
player.scalingMode = .AspectFill
player.controlStyle = .None
self.view.addSubview(player.view)
}
and I want to replace this with another video when a button is pressed:
#IBAction func aButtonIsPressed(sender: AnyObject) {
let path = NSBundle.mainBundle().pathForResource("Another Video", ofType:"mp4")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = moviePlayer {
player.view.frame = self.view.bounds
player.prepareToPlay()
player.scalingMode = .AspectFill
player.controlStyle = .None
self.view.addSubview(player.view)
}
}
When I tap the button the video plays, but there seems to be a delay adding the new video, which gives it a choppy transition. Is there any way to minimize this delay? I could try adding another MPMoviePlayerController to preload the second video maybe but from some testing I found the line causing the chop is here.
self.view.addSubview(player.view)
Can I keep the first video playing until the line above 'didFinish'? That would be great.
You are creating new MPMoviePlayerController object that's why you are getting this issue, you should use same object and which is already playing an object and just set contentURL property to new resource's URL,
If you set this property while a movie is playing, that movie pauses
and the new movie begins loading. The new movie starts playing at the
beginning
For more detail visit this link
I am to play same video in two screens with keeping seek time. So that I am reusing AVPlayer instance in these screen. For first time AVPlayer works fine, but whenever it is reused frame of player animates from top-left to fit target view on start of play.
like,
https://www.dropbox.com/s/8ieb4bnb0rsn9ig/ezgif.com-gif-maker.gif?dl=0
code looks like,
if myObj._playerResult != nil {
_player = myObj._playerResult //reuse player instance
} else {
// First create an AVPlayerItem
let playerItem : AVPlayerItem = AVPlayerItem(URL: NSURL(string:sVideoUrl as String))
_player = AVPlayer(playerItem: playerItem)
}
playerController = AVPlayerViewController()
playerController?.showsPlaybackControls = false
playerController?.player = _player
playerController!.view.frame = targetView.bounds
targetView.addSubview(playerController!.view)
_player?.play()