如何在Swift中循环播放AVPlayer?
简单的问题,我似乎无法find一个答案出于某种原因。
如何在Swift中循环播放AVPlayer?
numberOfLoops = -1只适用于AVAudioPlayer
我需要它没有任何延迟/黑色闪光等循环。这就是为什么我不使用MPMoviePlayerViewController。
谢谢你的帮助。
码:
let url_1 = NSURL.fileURLWithPath(outputFilePath_1) let asset_1 = AVAsset.assetWithURL(url_1) as? AVAsset let playerItem_1 = AVPlayerItem(asset: asset_1) let player_1 = AVPlayer(playerItem: self.playerItem_1) let playerLayer_1 = AVPlayerLayer(player: self.player_1) playerLayer_1!.frame = self.view.frame self.view.layer.addSublayer(self.playerLayer_1) player_1!.play()
Swift 3
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { _ in self.player?.seek(to: kCMTimeZero) self.player?.play() }
Swift 2
在configurationAVPlayerItem并且创build播放器之后:
var player: AVPlayer! ... // Invoke after player is created and AVPlayerItem is specified NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerItemDidReachEnd:", name: AVPlayerItemDidPlayToEndTimeNotification, object: self.player.currentItem) ... func playerItemDidReachEnd(notification: NSNotification) { self.player.seekToTime(kCMTimeZero) self.player.play() }
好的,我已经解决了。 感谢Msencenb用Objective C的答案指引我正确的方向。
player_1?.actionAtItemEnd = .None //set a listener for when the video ends NSNotificationCenter.defaultCenter().addObserver(self, selector: "restartVideoFromBeginning", name: AVPlayerItemDidPlayToEndTimeNotification, object: player_1?.currentItem) //function to restart the video func restartVideoFromBeginning() { //create a CMTime for zero seconds so we can go back to the beginning let seconds : Int64 = 0 let preferredTimeScale : Int32 = 1 let seekTime : CMTime = CMTimeMake(seconds, preferredTimeScale) player_1!.seekToTime(seekTime) player_1!.play() }
或者,您可以使用基于块的NSNotificationCenter API:
func loopVideo(videoPlayer: AVPlayer) { NSNotificationCenter.defaultCenter().addObserverForName(AVPlayerItemDidPlayToEndTimeNotification, object: nil, queue: nil) { notification in videoPlayer.seekToTime(kCMTimeZero) videoPlayer.play() } }
@Christopher Pickslay的答案更新了Swift 3 :
func loopVideo(videoPlayer: AVPlayer) { NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: nil) { notification in videoPlayer.seek(to: kCMTimeZero) videoPlayer.play() } }
但是,正如我在下面提到的他的回答,如果您有多个玩家,请务必将该对象指定为AVPlayer的玩家项目。
我设法在swift 3中为OSX创build了一个无缝的video循环。它应该可以在iOS上运行,并且在swift 2上也可以做很less的修改。
var player : AVQueuePlayer! // Looping video initial call internal func selectVideoWithLoop(url : URL) { let asset = AVAsset(url: url) player.pause() let playerItem1 = AVPlayerItem(asset: asset) let playerItem2 = AVPlayerItem(asset: asset) player.removeAllItems() player.replaceCurrentItem(with: playerItem1) player.insert(playerItem2, after: playerItem1) player.actionAtItemEnd = AVPlayerActionAtItemEnd.advance player.play() let selector = #selector(ViewController.playerItemDidReachEnd(notification:)) let name = NSNotification.Name.AVPlayerItemDidPlayToEndTime // removing old observer and adding it again for sequential calls. // Might not be necessary, but I like to unregister old notifications. NotificationCenter.default.removeObserver(self, name: name, object: nil) NotificationCenter.default.addObserver(self, selector: selector, name: name, object: nil) } // Loop video with threadmill pattern // Called by NotificationCenter, don't call directly func playerItemDidReachEnd(notification: Notification) { let item = player.currentItem! player.remove(item) item.seek(to: kCMTimeZero) player.insert(item, after: nil) }
当您要更改video时,只需再次调用具有不同url的selectVideoWithLoop即可。
Swift 3.0:
首先检查video的结束点: –
NotificationCenter.default.addObserver(self, selector: #selector(LoginViewController.playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem) func videoDidReachEnd() { //now use seek to make current playback time to the specified time in this case (O) let duration : Int64 = 0 (can be Int32 also) let preferredTimeScale : Int32 = 1 let seekTime : CMTime = CMTimeMake(duration, preferredTimeScale) player!.seek(to: seekTime) player!.play() }
从iOS 10开始,不需要使用通知来循环播放video,只需使用AVPlayerLooper即可:
let asset = AVAsset(url: videoURL) let item = AVPlayerItem(asset: asset) let player = AVQueuePlayer(playerItem: item) videoLooper = AVPlayerLooper(player: player, templateItem: item)
确保这个looper是在函数作用域之外创build的,以防函数返回时停止。