Simple question I can't seem to find an answer to for some reason.
How do you loop AVPlayer in Swift?
numberOfLoops = -1 only works for AVAudioPlayer
I do need it to loop without any delay / black flash etc. That's why I'm not using MPMoviePlayerViewController.
Thanks for any help.
Code:
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 5 (iOS 10.0+)
var playerLooper: AVPlayerLooper! // should be defined in class
var queuePlayer: AVQueuePlayer!
...
let asset: AVAsset = ... // AVAsset with its 'duration' property value loaded
let playerItem = AVPlayerItem(asset: asset)
self.queuePlayer = AVQueuePlayer(playerItem: playerItem)
// Create a new player looper with the queue player and template item
self.playerLooper = AVPlayerLooper(player: queuePlayer, templateItem: playerItem)
< iOS 10.0
All below works in any iOS version. But, for < iOS 10.0 it's the only solution.
Swift 4
var player: AVPlayer!
...
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { [weak self] _ in
self?.player?.seek(to: CMTime.zero)
self?.player?.play()
}
Swift 3
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { [weak self] _ in
self?.player?.seek(to: kCMTimeZero)
self?.player?.play()
}
Swift 2
After AVPlayerItem is configured and player is created:
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()
}
Don't forget to import AVFoundation
Starting from iOS 10, there's no need to use notifications to loop a video, simply use a AVPlayerLooper, just like this:
let asset = AVAsset(url: videoURL)
let item = AVPlayerItem(asset: asset)
let player = AVQueuePlayer(playerItem: item)
videoLooper = AVPlayerLooper(player: player, templateItem: item)
make sure this looper is created outside of a function scope, in case it stops when function returns.
@Christopher Pickslay's answer updated for Swift 4:
func loopVideo(videoPlayer: AVPlayer) {
NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: nil) { notification in
videoPlayer.seek(to: CMTime.zero)
videoPlayer.play()
}
}
But, as I mentioned below his answer, be sure to specify the object as the AVPlayer's player item if you have multiple players.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With