why currentTime and duration of AVAudioPlayer are nil?
Recently faced with a task when creating a player link to the mp3 working, checked but at the same time track duration and currenttime nil I try to change AVAudioPlayer to AVPlayer, but I have same problem
What I need to do to correct this?
Maybe I must to download this mp3 before read duration?
But it would be better to solve this problem without downloading mp3
import UIKit
import AVFoundation
class PlayerViewController: UIViewController {
//Instantiate the AVFoundation audio player class
var player: AVAudioPlayer?
//Timer for tracking the progress
var timer: Timer? = nil
@IBOutlet weak var bookCoverImageView: UIImageView!
@IBOutlet weak var timeSlider: CustomSlider!
@IBOutlet weak var timeFromStartLabel: UILabel!
@IBOutlet weak var remainingTimeLabel: UILabel!
@IBOutlet weak var previousButton: UIButton!
@IBOutlet weak var nextButton: UIButton!
@IBOutlet weak var playButton: UIButton!
@IBOutlet weak var bookNameLabel: UILabel!
@IBOutlet weak var authorNameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
_ = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateSlider), userInfo: nil, repeats: true)
do {
//Set the path to the audio file (comes from the bundle)
let path = URL(string: "https://firebasestorage.googleapis.com/v0/b/audio-summary-v3.appspot.com/o/%D0%92%D1%8B%D1%81%D1%82%D1%83%D0%BF%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%B2%20%D1%81%D1%82%D0%B8%D0%BB%D0%B5%20TED%20-%20%D0%94%D0%B6%D0%B5%D1%80%D0%B5%D0%BC%D0%B8%20%D0%94%D0%BE%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD.mp3?alt=media&token=58cae883-36b8-445f-8338-cc04cd518eee")
//Unpacking the path string optional
if let unpackedPath = path {
try player = AVAudioPlayer(contentsOf: unpackedPath)
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
self.timeFromStartLabel.text = String(format: "%d:%02d", Int(self.player!.currentTime) / 60, Int(self.player!.currentTime) % 60)
self.remainingTimeLabel.text = String(format: "%d:%02d", Int(self.player!.duration - self.player!.currentTime) / 60, Int(self.player!.duration - self.player!.currentTime) % 60)
}
player!.play()
timer!.fire()
}
} catch {
print(error)
}
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers, .allowAirPlay])
print("Playback OK")
try AVAudioSession.sharedInstance().setActive(true)
print("Session is Active")
} catch {
print(error)
}
I have error here
timeSlider.maximumValue = Float(self.player!.duration)
}
@IBAction func playButtonTapped(_ sender: Any) {
if player!.isPlaying {
player?.stop()
playButton.setImage(UIImage(named: "play_button"), for: .normal)
}
else {
player?.play()
playButton.setImage(UIImage(named: "stop_button"), for: .normal)
}
}
@IBAction func timeSliderScrolling(_ sender: Any) {
player?.stop()
player?.currentTime = TimeInterval(timeSlider.value)
player?.prepareToPlay()
player?.play()
}
@objc func updateSlider() {
I have error here
timeSlider.value = Float(player!.currentTime)
}
}
Use AVPlayer
over AVAudioPlayer
so that you can observe the current play time with addPeriodicTimeObserver
.
import UIKit
import AVFoundation
class ViewController: UIViewController {
// MARK: - Variables
var player: AVPlayer?
@IBAction func playAudio(_ sender: UIBarButtonItem) {
player?.play()
}
override func viewDidLoad() {
super.viewDidLoad()
guard let path = Bundle.main.path(forResource: "myAudio", ofType:"m4a") else {
debugPrint("File not found")
return
}
let audioURL = URL(fileURLWithPath: path)
let playerItem = AVPlayerItem(url: audioURL)
player = AVPlayer(playerItem: playerItem)
player!.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: DispatchQueue.main) { (CMTime) -> Void in
if self.player!.currentItem?.status == .readyToPlay {
let time : Float64 = CMTimeGetSeconds(self.player!.currentTime());
print("Current play time: \(time)")
}
}
}
}