web-dev-qa-db-ja.com

AVAudioPlayerを制御するUISlider

アプリに小さな機能を実装しようとしています。私は現在、AVAudioPlayersとしてサウンドを再生していますが、これは問題なく動作します。追加したいのは、UISliderでサウンドの位置(currentTime)を制御することです。それを行う簡単な方法はありますか?

Apple=プロジェクトを見てみましたが、かなり面倒でした...サンプルや提案はありますか?

事前にみんなに感謝

33
David Pollak

Paullの答えを拡張するには、スライダーをオーディオプレーヤーのdurationの最大値と連続するように設定し、スライダーのUIControlEventValueChangedイベントのターゲットとして、いくつかのオブジェクト(おそらくビューコントローラー)を追加します。アクションメッセージを受け取ったら、AVAudioPlayercurrentTimeプロパティをスライダーの値に設定します。また、NSTimerを使用して、オーディオプレーヤーの再生時にスライダーの値を更新することもできます。 +scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:が最も簡単な方法です。

16

問題ないはずです-スライダーを連続に設定し、サウンドファイルを読み込んだ後、最大値をプレーヤーの継続時間に設定してください。

編集

私はこれをやっただけでうまくいきました...

- (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];
}

スライダーはIBで設定され、再生を開始するボタンも同様です。

Swift 3.0アップデート:

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)
}
51
Paul Lynch

私はそれを機能させるために上記の答えを少し適応させる必要がありました。問題は、

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

スライダーはフロートを想定しており、プレーヤーのcurrentTimeとdrationはCMTimeを返すため、機能しません。これらを機能させるために、私はそれらを次のように改作しました。

slider.maximumValue = CMTimeGetSeconds([player duration]);
slider.value = CMTimeGetSeconds(player.currentTime);
player.currentTime = CMTimeMakeWithSeconds((int)slider.value,1);
7
3leggedcheetah

オーディオファイルの再生中に直面した問題と開始/終了時間を表示し、UISliderで曲を制御します。

  1. 一時フォルダーにダウンロードせずにオーディオを直接再生しない。
  2. IOSの下位バージョン、つまり12.4/13.1のメインスレッドでUISliderがクラッシュしました
  3. UISliderのスムーズスクロール。
  4. 曲の開始/終了時間を計算して更新します。

この回答は多少の編集が必要ですが、間違いなく機能します。

  //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
Shanu Singh