Audio playback progress as UISlider in Swift

前端 未结 4 1045
心在旅途
心在旅途 2021-01-31 10:28

I\'ve seen some posts about accomplishing this in Objective-C but I\'ve been unable to do the same via Swift.

Specifically, I can\'t figure out how to implement a

相关标签:
4条回答
  • 2021-01-31 11:13

    Just to elaborate on my previous comment, this is how I implemented it and it seems to work pretty well. Any Swift corrections are more than welcome, I'm still an Obj-C guy for now.

    @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)
    }
    

    *I set time slider's range between 0 and 1 on a storyboard

    0 讨论(0)
  • 2021-01-31 11:13

    Syntax has now changed in Swift 4:

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

    And the function (I have previously set the progressSlider.maxValue to player.duration):

    @objc func trackAudio() {
        progressSlider.value = Float(player!.currentTime)
     }
    
    0 讨论(0)
  • 2021-01-31 11:19

    Specifically for Swift I was able to handle it like this:

    1. I set the maximum value of the scrubSlider to the duration of the music file(.mp3) that was loaded in this method

      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. I player was set to play the music at the time set by the value of the scrubber.

      @IBAction func scrub(sender: AnyObject) {
      
          player.currentTime = NSTimeInterval(scrubSlider.value)
      
      }
      
    0 讨论(0)
  • 2021-01-31 11:33

    Thanks to the suggestion of Dare above, here's how I accomplished this:

    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)
    
    }
    
    0 讨论(0)
提交回复
热议问题