UISlider to control AVAudioPlayer

后端 未结 4 1115
执笔经年
执笔经年 2020-12-01 03:40

I\'m trying to implement a little function in my app. I am currently playing sounds as AVAudioPlayers and that works fine. What I would like to add is to control the sound\'

相关标签:
4条回答
  • 2020-12-01 04:05

    I needed to adapt the above answer a bit to get it to work. The issue is that using

    slider.maximumValue = [player duration];
    slider.value = player.currentTime;
    player.currentTime = slider.value;
    

    Do not work because the slider expects a float and the player currentTime and dration return CMTime. To make these work, I adapted them to read:

    slider.maximumValue = CMTimeGetSeconds([player duration]);
    slider.value = CMTimeGetSeconds(player.currentTime);
    player.currentTime = CMTimeMakeWithSeconds((int)slider.value,1);
    
    0 讨论(0)
  • 2020-12-01 04:06

    To extend on paull's answer, you'd set the slider to be continuous with a maximum value of your audio player's duration, then add some object of yours (probably the view controller) as a target for the slider's UIControlEventValueChanged event; when you receive the action message, you'd then set the AVAudioPlayer's currentTime property to the slider's value. You might also want to use an NSTimer to update the slider's value as the audio player plays; +scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: is the easiest way to do that.

    0 讨论(0)
  • 2020-12-01 04:08

    Shouldn't be a problem - just set the slider to continuous and set the max value to your player's duration after loading your sound file.

    Edit

    I just did this and it works for me...

    - (IBAction)slide {
        player.currentTime = slider.value;
    }
    
    - (void)updateTime:(NSTimer *)timer {
        slider.value = player.currentTime;
    }
    
    - (IBAction)play:(id)sender {
        NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"sound.caf" ofType:nil]];
        NSError *error;
        player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
        if (!player) NSLog(@"Error: %@", error);
        [player prepareToPlay];
        slider.maximumValue = [player duration];
        slider.value = 0.0;
        
        [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES];  
        [player play];
    }
    

    The slider is configured in IB, as is a button to start playing.

    Swift 3.0 Update:

    var player: AVAudioPlayer!
    var sliderr: UISlider!
    
    @IBAction func play(_ sender: Any) {
        var url = URL(fileURLWithPath: Bundle.main.path(forResource: "sound.caf", ofType: nil)!)
        var error: Error?
        do {
            player = try AVAudioPlayer(contentsOf: url)
        }
        catch let error {
        }
        if player == nil {
            print("Error: \(error)")
        }
        player.prepareToPlay()
        sliderr.maximumValue = Float(player.duration)
        sliderr.value = 0.0
        Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.updateTime), userInfo: nil, repeats: true)
        player.play()
    }
    
    func updateTime(_ timer: Timer) {
        sliderr.value = Float(player.currentTime)
    }
    
    @IBAction func slide(_ slider: UISlider) {
        player.currentTime = TimeInterval(slider.value)
    }
    
    0 讨论(0)
  • 2020-12-01 04:25

    Problems that I've faced during playing an audio file and show start/end time and controlling the song with the UISlider.

    1. Not playing audio directly without downloading it in temp folder.
    2. UISlider got crashed on main thread in lower iOS version i.e 12.4/13.1
    3. Smooth Scrolling of UISlider.
    4. Calculating and updating the start/end time of the song.

    This answer needs some editing, but it will work without any doubt.

      //UISlider init
      lazy var slider: UISlider = {
        let progress = UISlider()
        progress.minimumValue = 0.0
        progress.maximumValue = 100.0
        progress.tintColor = UIColor.init(named: "ApplicationColor")
        return progress
    
    }()
    
     var audioPlayer : AVAudioPlayer?
       //First I've downloaded the audio and then playing it.
      override func viewWillAppear(_ animated: Bool) {
    
        super.viewWillAppear(animated)
    
    
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(trackAudio), userInfo: nil, repeats: true)
    
        if let audioURLString = audioURL{
            let urlstring = URL(string: audioURLString)!
            downloadFromURL(url: urlstring) { (localURL, response, error) in
                if let localURL = localURL{
                    self.playAudioFile(url: localURL)
                }
    
            }
        }
    }
    
     override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        stopTimer()
    }
    
    
    // Stop TimeInterval After View disappear
    func stopTimer() {
        if timer != nil {
            timer?.invalidate()
            audioPlayer?.stop()
            audioPlayer = nil
            timer = nil
        }
    }
    @objc func sliderSelected(_ sender : UISlider){
    
        if audioPlayer != nil{
            if !isPlaying{
                self.audioPlayer?.play()
                playButton.setImage(UIImage.init(named: "AudioPause"), for: .normal)
                isPlaying = true
            }else{
                self.audioPlayer?.currentTime = TimeInterval(Float(sender.value) * Float(self.audioPlayer!.duration) / 100.0)
                if (sender.value / 100.0 == 1.0){
    
                    //Do something if audio ends while dragging the UISlider.
    
                }
            }
    
    
        }
    
    }
     func downloadFromURL(url:URL,completion: @escaping((_ downladedURL: URL?,_ response :URLResponse?,_ error: Error?) -> Void)){
        var downloadTask:URLSessionDownloadTask
        downloadTask = URLSession.shared.downloadTask(with: url) {(URL, response, error) in
            if let url = URL{
                completion(url,nil,nil)
            }else if let response = response{
                completion(nil,response,nil)
            }
            if let error = error{
                completion(nil,nil,error)
            }
    
    
        }
    
        downloadTask.resume()
    }
    
    
    func playAudioFile(url:URL){
        do{
    
            self.audioPlayer = try AVAudioPlayer(contentsOf: url)
            self.audioPlayer?.prepareToPlay()
            self.audioPlayer?.delegate = self
            self.audioPlayer?.play()
    
       let audioDuration = audioPlayer?.duration
            let audioDurationSeconds = audioDuration
            minutes = Int(audioDurationSeconds!/60);
            seconds =  Int(audioDurationSeconds!.truncatingRemainder(dividingBy: 60))
        } catch{
            print("AVAudioPlayer init failed")
        }
    }
    
    @objc func trackAudio() {
    
        if audioPlayer != nil{
            DispatchQueue.main.async {
                print("HI")
                let normalizedTime = Float(self.audioPlayer!.currentTime * 100.0 / self.audioPlayer!.duration)
                self.slider.setValue(normalizedTime, animated: true)
                let currentTime = self.audioPlayer?.currentTime
                self.currentMinutes = Int(currentTime!/60);
                self.currentSeconds =  Int(currentTime!.truncatingRemainder(dividingBy: 60))
                self.startTimeLabel.text =  String(format: "%02i:%02i", self.currentMinutes, self.currentSeconds)
                self.endTimeLabel.text = String(format: "%02i:%02i", self.minutes, self.seconds)
            }
        }
    
    
    
    
    
    }
    
    0 讨论(0)
提交回复
热议问题