ios swift avfoundation avplayer

ios - Progreso de reproducción de audio como UISlider en Swift



avfoundation avplayer (4)

Específicamente para Swift pude manejarlo de esta manera:

  1. Establecí el valor máximo del scrubSlider a la duración del archivo de música (.mp3) que se cargó en este método

    override func viewDidLoad() { super.viewDidLoad() do { try player = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("bach", ofType: "mp3")!)) scrubSlider.maximumValue = Float(player.duration) } catch { //Error } _ = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(ViewController.updateScrubSlider), userInfo: nil, repeats: true) }

  2. El reproductor I estaba configurado para reproducir la música a la hora establecida por el valor del depurador.

    @IBAction func scrub(sender: AnyObject) { player.currentTime = NSTimeInterval(scrubSlider.value) }

He visto algunas publicaciones sobre cómo lograr esto en Objective-C, pero no he podido hacer lo mismo a través de Swift.

Específicamente, no puedo encontrar la forma de implementar addPeriodicTimeObserverForInterval en la siguiente addPeriodicTimeObserverForInterval .

var player : AVAudioPlayer! = nil @IBAction func playAudio(sender: AnyObject) { playButton.selected = !(playButton.selected) if playButton.selected { let fileURL = NSURL(string: toPass) player = AVAudioPlayer(contentsOfURL: fileURL, error: nil) player.numberOfLoops = -1 // play indefinitely player.prepareToPlay() player.delegate = self player.play() startTime.text = "/(player.currentTime)" endTime.text = NSString(format: "%.1f", player.duration) } else { player.stop() }

Cualquier ayuda sería apreciada.


Gracias a la sugerencia de Dare anterior, así es como logré esto:

var updater : CADisplayLink! = nil @IBAction func playAudio(sender: AnyObject) { playButton.selected = !(playButton.selected) if playButton.selected { updater = CADisplayLink(target: self, selector: Selector("trackAudio")) updater.frameInterval = 1 updater.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes) let fileURL = NSURL(string: toPass) player = AVAudioPlayer(contentsOfURL: fileURL, error: nil) player.numberOfLoops = -1 // play indefinitely player.prepareToPlay() player.delegate = self player.play() startTime.text = "/(player.currentTime)" theProgressBar.minimumValue = 0 theProgressBar.maximumValue = 100 // Percentage } else { player.stop() } } func trackAudio() { var normalizedTime = Float(player.currentTime * 100.0 / player.duration) theProgressBar.value = normalizedTime } @IBAction func cancelClicked(sender: AnyObject) { player.stop() updater.invalidate() dismissViewControllerAnimated(true, completion: nil) }


La sintaxis ahora ha cambiado en Swift 4:

updater = CADisplayLink(target: self, selector: #selector(self.trackAudio)) updater.preferredFramesPerSecond = 1 updater.add(to: RunLoop.current, forMode: RunLoopMode.commonModes)

Y la función (he establecido previamente progressSlider.maxValue en player.duration):

@objc func trackAudio() { progressSlider.value = Float(player!.currentTime) }


Solo para explicar mi comentario anterior, así es como lo implementé y parece funcionar bastante bien. Cualquier corrección Swift es más que bienvenida, por ahora sigo siendo un tipo Obj-C.

@IBAction func playAudio(sender: AnyObject) { var playing = false if let currentPlayer = player { playing = player.playing; }else{ return; } if !playing { let filePath = NSBundle.mainBundle().pathForResource("3e6129f2-8d6d-4cf4-a5ec-1b51b6c8e18b", ofType: "wav") if let path = filePath{ let fileURL = NSURL(string: path) player = AVAudioPlayer(contentsOfURL: fileURL, error: nil) player.numberOfLoops = -1 // play indefinitely player.prepareToPlay() player.delegate = self player.play() displayLink = CADisplayLink(target: self, selector: ("updateSliderProgress")) displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode!) } } else { player.stop() displayLink.invalidate() } } func updateSliderProgress(){ var progress = player.currentTime / player.duration timeSlider.setValue(Float(progress), animated: false) }

* Establecí el rango del control deslizante de tiempo entre 0 y 1 en un guión gráfico