Reputation: 3952
I'm attempting to update a UILabel with the AVPlayer remaining time. I was able to set the UILabel with the video's current time remaining as soon as the video starts but that number doesn't change as the video progresses. I searched Apple's documentation and found this block that observes the time of the video but this resource and other questions on Stackoverflow don't necessarily point out how to update a UILabel using this function.
Here is my code that compiles but I'm unsure of how to move forward:
import UIKit
import AVKit
import AVFoundation
extension UIView {
func fadeTransition(duration:CFTimeInterval) {
let animation:CATransition = CATransition()
animation.timingFunction = CAMediaTimingFunction(name:
kCAMediaTimingFunctionEaseInEaseOut)
animation.type = kCATransitionFade
animation.duration = duration
self.layer.add(animation, forKey: kCATransitionFade)
}
}
class MeetTheAuthorViewController: UIViewController {
@IBOutlet weak var videoTimeRemainingLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//playBackgroundMusic("bensound-jazzyfrenchy-castlesbackground.mp3")
// Do any additional setup after loading the view.
}
func btn_clicked(_ sender: UIBarButtonItem) {
// Do something
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "videoSegue"
{
//set up the player
let videoURL = Bundle.main.url(forResource: "The Atlanta Goat_ Part One-HD", withExtension: "mp4")
let videoViewController = segue.destination as! AVPlayerViewController
videoViewController.player = AVPlayer(url: videoURL!)
videoViewController.player?.play()
//this code is an attempt to have a uilabel update with the time remaining in video
let videoDuration = CMTimeGetSeconds((videoViewController.player?.currentItem?.asset.duration)!)
let videoCurrentTime = videoViewController.player?.currentItem?.currentTime()
let timeRemainingInVideo = videoDuration - CMTimeGetSeconds(videoCurrentTime!)
videoTimeRemainingLabel.fadeTransition(duration: 0.4)
videoTimeRemainingLabel.text = String(describing: timeRemainingInVideo)
/*after the code above which updates the label initially, this code below is an attempt to update the UILabel over time as the video plays
*/
func addPeriodicTimeObserver() {
// Invoke callback every half second
let interval = CMTime(seconds: 0.5,
preferredTimescale: CMTimeScale(NSEC_PER_SEC))
// Queue on which to invoke the callback
let mainQueue = DispatchQueue.main
// Add time observer
var timeObserverToken =
videoViewController.player?.addPeriodicTimeObserver(forInterval: interval, queue: mainQueue) {
[weak self] time in
// update player transport UI
}
}
//end of attempt to update time remaining label
NotificationCenter.default.addObserver(self, selector: #selector(MeetTheAuthorViewController.playerDidFinishPlaying),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: videoViewController.player?.currentItem)
}
}
func playerDidFinishPlaying() {
print("Video Finished")
self.dismiss(animated: true, completion: nil)
}
}
Upvotes: 0
Views: 1384
Reputation: 6459
Update UI should be in the main thread
videoViewController.player?.addPeriodicTimeObserver(forInterval: interval, queue: nil, using: { (time) in
let currentTime = floor(CMTimeGetSeconds(time))
print(currentTime)
// update UI should be in main thread
DispatchQueue.main.async {
videoTimeRemainingLabel.text = String(currentTime)
}
})
Upvotes: 0
Reputation: 4480
Where you have the comment // update player transport UI
, you need to recalculate timeRemainingInVideo
and update the label.
Upvotes: 1