AVPlayer seektotime with Pangesturerecognizer - ios

I'm trying to use seektotime with Pangesture recognizer.But its not seeking as expected.
let totalTime = self.avPlayer.currentItem!.duration
print("time: \(CMTimeGetSeconds(totalTime))")
self.avPlayer.pause()
let touchDelta = swipeGesture.translationInView(self.view).x / CGFloat(CMTimeGetSeconds(totalTime))
let currentTime = CMTimeGetSeconds((avPlayer.currentItem?.currentTime())!) + Float64(touchDelta)
print(currentTime)
if currentTime >= 0 && currentTime <= CMTimeGetSeconds(totalTime) {
let newTime = CMTimeMakeWithSeconds(currentTime, Int32(NSEC_PER_SEC))
print(newTime)
self.avPlayer.seekToTime(newTime)
}
What I'm doing wrong in here ?

Think about what's happening in this line here:
let touchDelta = swipeGesture.translationInView(self.view).x / CGFloat(CMTimeGetSeconds(totalTime))
You're dividing pixels (the translation in just the x-axis) by time. This really isn't a "delta" or absolute difference. It's a ratio of sorts. But it's not a ratio that has any meaning. Then you're getting your new currentTime by just added this ratio to the previous currentTime, so you're adding pixels per seconds to pixels, which doesn't give a logical or useful number.
What we need to do is take the x-axis translation from the gesture and apply a scale (which is a ratio) to it in order to get a useful number of seconds to advance/rewind the AVPlayer. The x-axis translation is in pixels so we'll need a scale that describes seconds per pixels and multiple the two in order to get our number of seconds. The proper scale is the ratio between the total number of seconds in the video and the total number of pixels that the user can move through in the gesture. Multiplying pixels times (seconds divided by pixels) gives us a number in seconds. In pseudocode:
scale = totalSeconds / totalPixels
timeDelta = translation * scale
currentTime = oldTime + timeDelta
So I would rewrite your code like this:
let totalTime = self.avPlayer.currentItem!.duration
print("time: \(CMTimeGetSeconds(totalTime))")
self.avPlayer.pause()
// BEGIN NEW CODE
let touchDelta = swipeGesture.translationInView(self.view).x
let scale = CGFloat(CMTimeGetSeconds(totalTime)) / self.view.bounds.width
let timeDelta = touchDelta * scale
let currentTime = CMTimeGetSeconds((avPlayer.currentItem?.currentTime())!) + Float64(timeDelta)
// END NEW CODE
print(currentTime)
if currentTime >= 0 && currentTime <= CMTimeGetSeconds(totalTime) {
let newTime = CMTimeMakeWithSeconds(currentTime, Int32(NSEC_PER_SEC))
print(newTime)
self.avPlayer.seekToTime(newTime)
}

I have same issue, then i create the UISlider and set the action method is given below,
declare AVPlayer is var playerVal = AVPlayer()
#IBAction func sliderAction(sender: UISlider) {
playerVal.pause()
displayLink.invalidate()
let newTime:CMTime = CMTimeMakeWithSeconds(Double(self.getAudioDuration() as! NSNumber) * Double(sender.value), playerVal.currentTime().timescale)
playerVal.seekToTime(newTime)
updateTime()
playerVal.play()
deepLink()
}
And another method is,
func updateTime() {
let currentTime = Float(CMTimeGetSeconds(playerItem1.currentTime()))
let minutes = currentTime/60
let seconds = currentTime - minutes * 60
let maxTime = Float(self.getAudioDuration() as! NSNumber)
let maxminutes = maxTime / 60
let maxseconds = maxTime - maxminutes * 60
startValue.text = NSString(format: "%.2f:%.2f", minutes,seconds) as String
stopValue.text = NSString(format: "%.2f:%.2f", maxminutes,maxseconds) as String
}
I have used CADisplayLink and declare var displayLink = CADisplayLink(), its used continue(automatically) playing audios. code is
func deepLink() {
displayLink = CADisplayLink(target: self, selector: ("updateSliderProgress"))
displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
}
func updateSliderProgress(){
let progress = Float(CMTimeGetSeconds(playerVal.currentTime())) / Float(self.getAudioDuration() as! NSNumber)
sliderView.setValue(Float(progress), animated: false)
}
if you see this above answer, you have get idea, hope its helpful

Related

UISlider as audio seekbar jumping to maximum value when changed

I am using a UISlider as a seek bar for audio and it works great for adjusting to change position in the track if it is not animated. If it's animated it works great and tracks along the bar in time with the track perfectly but if you try and adjust it while the animation is active, it jumps to the maximum value of the bar. I assume there is a conflict between the two processes but I'm struggling to work out a fix.
func changeProgressBar() {
let trackLength = Float(AudioService.shared.playerItem?.duration.seconds ?? 0)
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true){_ in
let currentTime = Float(AudioService.shared.player?.currentTime().seconds ?? 0)
let sliderPosition = currentTime / (trackLength / 100)
self.progressBar.setValue(sliderPosition, animated: true)
print("the current time is", currentTime)
print("the slider position is", sliderPosition)
}
}
#IBAction func progressBarValueChanged(_ sender: UISlider) {
let trackLength = AudioService.shared.playerItem?.duration.seconds ?? 0
let sliderValueFloat = progressBar.value * 100.00
let sliderValueDouble = Double(sliderValueFloat)
let targetTime = (trackLength / 100 * sliderValueDouble)
let targetTimeActual = CMTimeMake(value: Int64(targetTime), timescale: 1)
AudioService.shared.player!.seek(to: targetTimeActual)
}
I have buttons that add or subtract 30 seconds to skip forward or back in the track and they work fine even when the animation is active.
#IBAction func plus30Secs(_ sender: UIButton) {
let currentTime = Float(AudioService.shared.player?.currentTime().seconds ?? 0)
let seekTime = currentTime + 30
let seekTimeActual = CMTimeMake(value: Int64(seekTime), timescale: 1)
AudioService.shared.player!.seek(to: seekTimeActual)
}
#IBAction func minus30Secs(_ sender: UIButton) {
let currentTime = Float(AudioService.shared.player?.currentTime().seconds ?? 0)
let seekTime = currentTime - 30
let seekTimeActual = CMTimeMake(value: Int64(seekTime), timescale: 1)
AudioService.shared.player!.seek(to: seekTimeActual)
}
ok, i have fixed it.
The issue was i had progressBar.maximumValue = 100 meaning that my progressBar.value * 100.00 was giving a value 100 times what it should have been and as such a value beyond the end of the track. I removed the * 100.00 and now it works great.

Swift Timer() trouble

I've done a simple timer in Swift. All is well apart from when the seconds reach 59 seconds. Instead of going back to zero they just carry on going. Would someone would be able to point out where I'm going wrong and why this is happening?
#IBAction func startButtonDidTouch(_ sender: Any) {
if !timerIsRunning{
timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.updateTimer), userInfo: nil, repeats: true)
timerIsRunning = true
}
}
#objc func updateTimer() {
totalSeconds += 0.01
let totalSecondsTimes100: Int = Int(totalSeconds*100)
let minutes = Int(totalSeconds/60)
let timerChoice = Double(minutes)
let minStr = (minutes == 0) ? "00" : "0\(minutes)"
let secStr = (totalSeconds < 9) ? "0\(Float(totalSecondsTimes100)/100)" : "\(Float(totalSecondsTimes100)/100)"
switch Int(timerChoice) {
case Int(timerCountdownLabel.text!)!:
timerLabel.text = "\(minStr):\(secStr)"
audioPlayer.play()
timer.invalidate()
timerIsRunning = false
default:
timerLabel.text = "\(minStr):\(secStr)"
}
}
You should calculate the seconds as:
let seconds = totalSeconds % 60
and then use seconds in your calculation of secStr instead of using totalSeconds.
There are better ways to write your code:
#objc func updateTimer() {
totalSeconds += 0.01
let minutes = Int(totalSeconds) / 60
let seconds = totalSeconds.remainder(dividingBy: 60)
let timeStr = String(format: "%02d:%06.3f", minutes, seconds)
timerLabel.text = timeStr
if Int(timerCountdonwLabel.text!)! == minutes {
audioPlayer.play()
timer.invalidate()
timerIsRunning = false
}
}
And you really shouldn't keep track of time simply by adding 0.01 to totalSeconds. A Timer is not accurate. Your clock will drift over time. It's best to save a timestamp (Date()) when you start the timer and get the current timestamp (Date()) inside updateTimer and get the difference between the two.
Here is a timer function that outputs format minutes:seconds:milliseconds, compare with your code and you'll find what's wrong with your code.
private weak var timer: Timer?
private var startTime: Double = 0
private var elapsed: Double = 0
private var time: Double = 0
private func startTimer(){
startTime = Date().timeIntervalSinceReferenceDate - elapsed
timer = Timer.scheduledTimer(timeInterval: (0.01), target: self, selector: #selector(updateTimeLabel), userInfo: nil, repeats: true)
}
private func stopTimer(){
elapsed = Date().timeIntervalSinceReferenceDate - startTime
timer?.invalidate()
}
#objc func updateTimeLabel(){
time = Date().timeIntervalSinceReferenceDate - startTime
let minutes = UInt8(time / 60.0)
let timeNoMin = time - (TimeInterval(minutes) * 60)
let seconds = UInt8(timeNoMin)
let timeNoSec = timeNoMin - (TimeInterval(seconds))
let milliseconds = UInt16(timeNoSec * 100)
let strMinutes = String(minutes)
var strSeconds = ""
if strMinutes == "0" {
strSeconds = String(seconds)
}
else {
strSeconds = String(format: "%02d", seconds)
}
let strMilliseconds = String(format: "%02d"), milliseconds)
if strMinutes != "0" {
timerLabel.text = "\(strMinutes):\(strSeconds).\(strMilliseconds)"
}
else {
timerLabel.text = "\(strSeconds).\(strMilliseconds)"
}
}
To get minutes and seconds from a floating point total number of seconds elapsed, elapsed you can:
To get minutes, divide by 60.0 and truncate to the nearest integer:
let minutes = Int(elapsed / 60)
To get seconds, get the remainder, either via:
let seconds = elapsed - Double(minutes) * 60
Or
let seconds = elapsed.truncatingRemainder(dividingBy: 60)
A couple of other observations:
There's no point in running a timer every 0.01 seconds when the screen refresh rate is usually capped at 60 frames per second. If you want to update it with the greatest frequency, use a CADisplayLink which is timed not only for maximum screen refresh rate, but also fires optimally to allow the update to happen before the next frame is to be rendered.
You should not use timer to increment the elapsed time by 0.01 (or any fixed interval) because you have no assurances that it will actually fire with that frequency. If something, for example, momentarily blocks the main thread by 200 milliseconds, you don't want this to affect your calculation of the amount of time that has elapsed.
Instead, save the start time when the timer starts, and every time the timer fires recalculate the elapsed time and format the results accordingly.
To complicate this further, you should not even be comparing Date() instances (or CFAbsoluteTimeGetCurrent() values) because, as the documentation warns us:
Repeated calls to this function do not guarantee monotonically increasing results. The system time may decrease due to synchronization with external time references or due to an explicit user change of the clock.
Instead, you should use a mach_absolute_time based calculation (such as returned by CACurrentMediaTime()), for which repeated calls are assured to return accurately elapsed time calculations.
The only time you should use Date() or CFAbsoluteTimeGetCurrent() if your app is saving the start time in persistent storage, to be retrieved later when the app is restarted (possibly after a device reboot) to render the effect of the elapsed time between starts of an app. But this is a pretty narrow edge case.
Anyway, this yields:
var start: CFTimeInterval?
weak var displayLink: CADisplayLink?
func startTimer() {
self.displayLink?.invalidate() // just in case timer had already been started
start = CACurrentMediaTime()
let displayLink = CADisplayLink(target: self, selector: #selector(handleDisplayLink(_:)))
displayLink.preferredFramesPerSecond = 100 // in case you're using a device that can render more than 60 fps
displayLink.add(to: .main, forMode: .commonModes)
self.displayLink = displayLink
}
#objc func handleDisplayLink(_ displayLink: CADisplayLink) {
let elapsed = CACurrentMediaTime() - start!
let minutes = Int(elapsed / 60)
let seconds = elapsed - Double(minutes) * 60
let string = String(format: "%02d:%05.2f", minutes, seconds)
label.text = string
}
func stopTimer() {
displayLink?.invalidate()
}

Format timer label to hours:minutes:seconds in Swift

I have an NSTimer which counts DOWN from 2 hours until 0.
Here are some of my code:
var timer = NSTimer()
let timeInterval:NSTimeInterval = 0.5
let timerEnd:NSTimeInterval = 0.0
var timeCount:NSTimeInterval = 7200.0 // seconds or 2 hours
// TimeString Function
func timeString(time:NSTimeInterval) -> String {
let minutes = Int(time) / 60
let seconds = time - Double(minutes) * 60
let secondsFraction = seconds - Double(Int(seconds))
return String(format:"%02i:%02i.%01i",minutes,Int(seconds),Int(secondsFraction * 10.0))
}
The Timer Label is:
TimerLabel.text = "Time: \(timeString(timeCount))"
HOWEVER, my timer label shows as:
Time: 200:59.0
How do I format my timer label to look like this:
Time: 01:59:59 // (which is hours:minutes:seconds)?
[Please note that I have no problems with my countdown timer, I only need to know how to CHANGE THE TIME FORMAT using the TimeString function.]
EDIT:
Someone mentioned that my question is a possible duplicate of this one: Swift - iOS - Dates and times in different format. HOWEVER, I am asking on how do I change the time format using the TimeString function that I gave above. I am not asking for another WAY on how to do it.
For instance:
let minutes = Int(time) / 60
gives me "200" minutes. etc.
Your calculations are all wrong.
let hours = Int(time) / 3600
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i:%02i", hours, minutes, seconds)
#rmaddy's solution is accurate and answers the question. However, neither the question nor the solution take into account international users. I suggest using DateComponentsFormatter and let the framework handle the calculations and formatting. Doing so makes your code less error prone and more future proof.
I came across this blog post that provides a concise solution:
http://crunchybagel.com/formatting-a-duration-with-nsdatecomponentsformatter/
Pulled from that post, this is the code snippet that would replace the code you're currently using to make your calculations. Updated for Swift 3:
let duration: TimeInterval = 7200.0
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional // Use the appropriate positioning for the current locale
formatter.allowedUnits = [ .hour, .minute, .second ] // Units to display in the formatted string
formatter.zeroFormattingBehavior = [ .pad ] // Pad with zeroes where appropriate for the locale
let formattedDuration = formatter.string(from: duration)
Swift5
var totalSecond = Int()
var timer:Timer?
call startTimer() based on requirement-
func startTimer(){
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(countdown), userInfo: nil, repeats: true)
}
#objc func countdown() {
var hours: Int
var minutes: Int
var seconds: Int
if totalSecond == 0 {
timer?.invalidate()
}
totalSecond = totalSecond - 1
hours = totalSecond / 3600
minutes = (totalSecond % 3600) / 60
seconds = (totalSecond % 3600) % 60
timeLabel.text = String(format: "%02d:%02d:%02d", hours, minutes, seconds)
}
Done
The best way to implement a Timer in Swift (swift 4 works fine).
Declare the variable secs: Int and assign the value, in seconds, of the timer.
Then with the Timer () function, discount one second at a time and pass it to this function.
var secs = 0
var timer = Timer()
func startTimer(segs: Int) {
seg = segs
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerDiscount), userInfo: nil, repeats: true)
}
func timerDiscount() {
let hours = secs / 3600
let mins = secs / 60 % 60
let secs = secs % 60
let restTime = ((hours<10) ? "0" : "") + String(hours) + ":" + ((mins<10) ? "0" : "") + String(mins) + ":" + ((secs<10) ? "0" : "") + String(secs)
}
Declare the variables hours ,minutes and seconds and copy paste the below code it works fine.
if counter > 0 {
let hours = counter / 3600
let minutes = counter / 60
let seconds = counter % 60
counter = counter - 1
timerLbl.text = "\(hours):\(minutes):\(seconds)"
}

Display Timecode for video track using Swift AVPlayer

I am working on a little app to navigate and play videos which includes framerate and initial timecode information (eg: "TimeCode" : "09:25:15:08"). I am using the AVKit Player View Controller to display my video, and I would like to add a UILabel displaying the current timecode.
I'm all set about the way to add up custom UI elements, but I'm lost about how to calculate the timecode and make it update itself every frame the video plays.
I have read about the AVFoundation - Timecode Support with AVAssetWriter and AVAssetReader, but I'm not sure if I have understood it.
Any explanations, guidance, or content to look at would be really appreciated.
UPDATE:
After thinking for a while, I though that I could use the frame count to build up my own timecode references.
note item is the AVPlayer
using var totalTime = CMTimeGetSeconds(item.currentItem.asset.duration)I can get the total length in seconds of the video track, and currentTime = CMTimeGetSeconds(item.currentItem.currentTime())to get its current time position.
Then I can do var fps = item.currentItem.asset.tracks[0].nominalFrameRateto get the framerate and use this variable to divide totalTime and currentTimeto get the total frame count as well as the current frame.
With this im considering the idea of building up a pre normalized array of time in second for each frame from the total frame count. this way I could know what exact frame is related to a time stamp.
I never had to work with timecode or dates so if someone has an idea about the way to do this I would appreciate the help.
basically, a timecode looks like this: HH:MM:SS:FF (FF being the current frame).
If the fps = 24, then every 24 frames a second is added to the SS and so on.
TEST CASE:
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController {
var player = AVPlayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var url=NSURL(string: "http://km.support.apple.com/library/APPLE/APPLECARE_ALLGEOS/HT1211/sample_iTunes.mov")
player = AVPlayer(URL: url)
let playerController = AVPlayerViewController()
playerController.player = player
self.addChildViewController(playerController)
self.view.addSubview(playerController.view)
playerController.view.frame = self.view.frame
//Debug btn
var btn = UIButton()
btn.frame = CGRect(x:10, y:50, width:100, height:30)
btn.setTitle("FPS", forState: .Normal)
btn.addTarget(self, action: "buttonTapAction:", forControlEvents: UIControlEvents.TouchUpInside)
playerController.view.addSubview(btn)
player.play()
// getFps(player)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getFps(item:AVPlayer) {
var fps = item.currentItem.asset.tracks[0].nominalFrameRate
println("FPS: \(fps)")
var timeRange_src = CMTimeGetSeconds(item.currentItem.asset.duration)
var timeRange = Float(timeRange_src)
println("time Range: \(timeRange)")
var frameCount = timeRange * fps
println("total frames: \(frameCount)")
var timeIs = Float(CMTimeGetSeconds(item.currentItem.currentTime()))
var frameIs = timeIs * fps
println("current time: \(timeIs)")
println("current frame: \(frameIs)")
}
func buttonTapAction(sender:UIButton!)
{
getFps(player)
}
}
Here's how I recently did it with Swift 3:
func formatTimecode(frame: Int, fps: Double) -> String {
let FF = Int(Double(frame).truncatingRemainder(dividingBy: fps))
let seconds = Int(Double(frame - FF) / fps)
let SS = seconds % 60
let MM = (seconds % 3600) / 60
let HH = seconds / 3600
let timecode = [String(format: "%02d", HH), String(format: "%02d", MM), String(format: "%02d", SS), String(format: "%02d", FF)];
return timecode.joined(separator: ":")
}
ok so here is how I solved my problem and built the timecode based on the variables I had:
func pad(fps:Float, currentFrame:Float) -> (String){
var fps = fps
var frame = currentFrame + f
var ff = frame % fps
var seconds = s + ((currentFrame) / fps)
var ss = seconds % 60
var minutes = m + ((seconds - ss) / 60)
var mm = minutes % 60
var hh = h + ((minutes - mm) / 60)
return "\(showTwoDigits(hh)):\(showTwoDigits(mm)):\(showTwoDigits(ss)):\(showTwoDigits(ff))"
}
func showTwoDigits(number:Float) -> (String){
var string = ("00" + String(format:"%.f", number))
var range = Range(start: (advance(string.endIndex, -2)), end: string.endIndex)
var cutStr = string.substringWithRange(range)
return cutStr
}

How do I get current playing time and total play time in AVPlayer?

Is it possible get playing time and total play time in AVPlayer? If yes, how can I do this?
You can access currently played item by using currentItem property:
AVPlayerItem *currentItem = yourAVPlayer.currentItem;
Then you can easily get the requested time values
CMTime duration = currentItem.duration; //total time
CMTime currentTime = currentItem.currentTime; //playing time
Swift 5:
if let currentItem = player.currentItem {
let duration = CMTimeGetSeconds(currentItem.duration)
let currentTime = CMTimeGetSeconds(currentItem.currentTime())
print("Duration: \(duration) s")
print("Current time: \(currentTime) s")
}
_audioPlayer = [self playerWithAudio:_audio];
_observer =
[_audioPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 2)
queue:dispatch_get_main_queue()
usingBlock:^(CMTime time)
{
_progress = CMTimeGetSeconds(time);
}];
Swift 3
let currentTime:Double = player.currentItem.currentTime().seconds
You can get the seconds of your current time by accessing the seconds property of the currentTime(). This will return a Double that represents the seconds in time. Then you can use this value to construct a readable time to present to your user.
First, include a method to return the time variables for H:mm:ss that you will display to the user:
func getHoursMinutesSecondsFrom(seconds: Double) -> (hours: Int, minutes: Int, seconds: Int) {
let secs = Int(seconds)
let hours = secs / 3600
let minutes = (secs % 3600) / 60
let seconds = (secs % 3600) % 60
return (hours, minutes, seconds)
}
Next, a method that will convert the values you retrieved above into a readable string:
func formatTimeFor(seconds: Double) -> String {
let result = getHoursMinutesSecondsFrom(seconds: seconds)
let hoursString = "\(result.hours)"
var minutesString = "\(result.minutes)"
if minutesString.characters.count == 1 {
minutesString = "0\(result.minutes)"
}
var secondsString = "\(result.seconds)"
if secondsString.characters.count == 1 {
secondsString = "0\(result.seconds)"
}
var time = "\(hoursString):"
if result.hours >= 1 {
time.append("\(minutesString):\(secondsString)")
}
else {
time = "\(minutesString):\(secondsString)"
}
return time
}
Now, update the UI with the previous calculations:
func updateTime() {
// Access current item
if let currentItem = player.currentItem {
// Get the current time in seconds
let playhead = currentItem.currentTime().seconds
let duration = currentItem.duration.seconds
// Format seconds for human readable string
playheadLabel.text = formatTimeFor(seconds: playhead)
durationLabel.text = formatTimeFor(seconds: duration)
}
}
With Swift 4.2, use this;
let currentPlayer = AVPlayer()
if let currentItem = currentPlayer.currentItem {
let duration = currentItem.asset.duration
}
let currentTime = currentPlayer.currentTime()
Swift 4
self.playerItem = AVPlayerItem(url: videoUrl!)
self.player = AVPlayer(playerItem: self.playerItem)
self.player?.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1), queue: DispatchQueue.main, using: { (time) in
if self.player!.currentItem?.status == .readyToPlay {
let currentTime = CMTimeGetSeconds(self.player!.currentTime())
let secs = Int(currentTime)
self.timeLabel.text = NSString(format: "%02d:%02d", secs/60, secs%60) as String//"\(secs/60):\(secs%60)"
})
}
AVPlayerItem *currentItem = player.currentItem;
NSTimeInterval currentTime = CMTimeGetSeconds(currentItem.currentTime);
NSLog(#" Capturing Time :%f ",currentTime);
Swift:
let currentItem = yourAVPlayer.currentItem
let duration = currentItem.asset.duration
var currentTime = currentItem.asset.currentTime
Swift 5:
Timer.scheduledTimer seems better than addPeriodicTimeObserver if you want to have a smooth progress bar
static public var currenTime = 0.0
static public var currenTimeString = "00:00"
Timer.scheduledTimer(withTimeInterval: 1/60, repeats: true) { timer in
if self.player!.currentItem?.status == .readyToPlay {
let timeElapsed = CMTimeGetSeconds(self.player!.currentTime())
let secs = Int(timeElapsed)
self.currenTime = timeElapsed
self.currenTimeString = NSString(format: "%02d:%02d", secs/60, secs%60) as String
print("AudioPlayer TIME UPDATE: \(self.currenTime) \(self.currenTimeString)")
}
}
Swift 4.2:
let currentItem = yourAVPlayer.currentItem
let duration = currentItem.asset.duration
let currentTime = currentItem.currentTime()
in swift 5+
You can query the player directly to find the current time of the actively playing AVPlayerItem.
The time is stored in a CMTime Struct for ease of conversion to various scales such as 10th of sec, 100th of a sec etc
In most cases we need to represent times in seconds so the following will show you what you want
let currentTimeInSecs = CMTimeGetSeconds(player.currentTime())

Resources