【问题标题】:How do next track AVPlayer下一首AVPlayer怎么做
【发布时间】:2017-07-02 15:02:07
【问题描述】:

我尝试了几天来制作一个包含下一首歌曲的按钮,但我不能
这是我的问题
如何使用 avPlayer 将下一个 екфсл 放在单击按钮时

这是我的代码

class ViewControllerAudioDetail: UIViewController {


var avPlayer:AVQueuePlayer?
var status = false
fileprivate let seekDuration: Float64 = 10
fileprivate let seekDurationThirty: Float64 = 30

var mod = [Modal]()



@IBOutlet weak var ImageView: UIImageView!

@IBOutlet weak var startTime: UILabel!
@IBOutlet weak var endTime: UILabel!
@IBOutlet weak var sliderSong: UISlider!
@IBOutlet weak var name: UILabel!

@IBOutlet weak var Volume: UISlider!
@IBOutlet weak var iconChange: UIButton!


override func viewDidLoad() {
    super.viewDidLoad()

    Volume.setThumbImage(UIImage(named:"Play.png"), for: .normal)
    sliderSong.minimumValue = 0
    sliderSong.maximumValue = 1

    name.text = mod[thisSong].AudioName
    ImageView.image = mod[0].ImageViewAudio


    let url = URL(string: mod[thisSong].UrlName!)
    let playerItem = AVPlayerItem(url: url!)
    avPlayer = AVQueuePlayer(playerItem:playerItem)


    let _ = avPlayer!.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main) { [weak self] (time) in

        let duration = CMTimeGetSeconds((self?.avPlayer!.currentItem!.asset.duration)!)
        self?.sliderSong.value = Float(CMTimeGetSeconds(time)) / Float(duration)

    }


    let duration = CMTimeGetSeconds(avPlayer!.currentItem!.asset.duration)
    let minutesTextOut = Int(duration) / 60 % 60
    let secondsTextOut = Int(duration) % 60
    let strDuration = String(format:"%02d:%02d", minutesTextOut, secondsTextOut)
    endTime.text = strDuration



}

@IBAction func sliderSong(_ sender: UISlider) {

        //перемотка аудиозвука
        let duration = CMTimeGetSeconds(avPlayer!.currentItem!.asset.duration)
        let value = sliderSong.value
        let durationToSeek = Float(duration) * value

        avPlayer?.seek(to: CMTimeMakeWithSeconds(Float64(durationToSeek),avPlayer!.currentItem!.duration.timescale)) { [](state) in

            if (self.iconChange.currentImage?.isEqual(UIImage(named: "Play.png")))! {
                self.avPlayer?.pause()
            } else if (self.iconChange.currentImage?.isEqual(UIImage(named: "Pause.png")))!{
                self.avPlayer?.play()
            }
        }
}


@IBAction func volume(_ sender: UISlider) {

    avPlayer?.volume = sender.value
}



@IBAction func minusThirtySec(_ sender: Any) {

    let playerCurrentTime = CMTimeGetSeconds((avPlayer?.currentTime())!)
    var newTime = playerCurrentTime - seekDurationThirty

    if newTime < 0 {
        newTime = 0
    }
    let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
    avPlayer?.seek(to: time2, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)


}
@IBAction func minusTenSec(_ sender: Any) {

    let playerCurrentTime = CMTimeGetSeconds((avPlayer?.currentTime())!)
    var newTime = playerCurrentTime - seekDuration

    if newTime < 0 {
        newTime = 0
    }
    let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
    avPlayer?.seek(to: time2, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

}

@IBAction func plusTenSec(_ sender: Any) {

    guard let duration = avPlayer?.currentItem?.duration else{
        return
    }
    let playerCurrentTime = CMTimeGetSeconds((avPlayer?.currentTime())!)
    let newTime = playerCurrentTime + seekDuration

    if newTime < (CMTimeGetSeconds(duration) - seekDuration) {

        let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
        avPlayer?.seek(to: time2, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

    }

}
@IBAction func plusThirtySec(_ sender: Any) {

    guard let duration = avPlayer?.currentItem?.duration else{
        return
    }
    let playerCurrentTime = CMTimeGetSeconds((avPlayer?.currentTime())!)
    let newTime = playerCurrentTime + seekDurationThirty

    if newTime < (CMTimeGetSeconds(duration) - seekDuration) {

        let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
        avPlayer?.seek(to: time2, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

    }

}

@IBAction func Next(_ sender: Any) {

    let url = URL(string: mod[thisSong].UrlName!)
    let playerItem = AVPlayerItem(url: url!)
    avPlayer = AVQueuePlayer(playerItem:playerItem)

    avPlayer?.insert(playerItem, after: playerItem)
    avPlayer?.advanceToNextItem()


 //        if thisSong + 1 > mod.count {
 //            thisSong = 0
 //        } else {
 //            thisSong += 1
  //        }
  //      
  //        
  //        if thisSong != mod.count{
  //            
 //            name.text = mod[thisSong].AudioName
 //            player(urlSong:mod[thisSong].UrlName!)
 //            avPlayer?.play()
 //
 //            
 //            
 //        }

}
@IBAction func Back(_ sender: Any) {



 //        if thisSong != 0{
 //            thisSong -= 1
 //            name.text = mod[thisSong].AudioName
 //            player(urlSong:mod[thisSong].UrlName!)
 //            avPlayer?.play()
 //
 //            
 //        }

}




@IBAction func Play(_ sender: Any) {


    if avPlayer?.rate == 0 {
        avPlayer?.play()
        avPlayer?.rate = 1.0
        iconChange.setImage(UIImage(named:"Pause.png"), for: .normal)


        avPlayer?.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1), queue: nil, using: {
            (CMTime) -> Void in

            self.updateProgressBar()
        })



    } else {
        avPlayer?.rate = 0.0
        avPlayer?.pause()
        iconChange.setImage(UIImage(named:"Play.png"), for: .normal)

    }

}


func player(urlSong:String) {




}



func updateProgressBar(){
    let timeNow = Int(avPlayer!.currentTime().value) / Int(avPlayer!.currentTime().timescale)

    let minutesText = timeNow / 60
    let secondsText = timeNow % 60

    let duration = String(format:"%02d:%02d", minutesText, secondsText)
    startTime.text = duration

}

tableview 从这里得到数据

var thisSong = 0


 class TableViewControllerAudioList: UITableViewController {


override func viewDidLoad() {
    super.viewDidLoad()

    tableView.estimatedRowHeight = 50
    tableView.rowHeight = UITableViewAutomaticDimension



}

override func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return modalsF.count
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCellAudioList

    cell.name.text = modalsF[indexPath.row].AudioName
    cell.number.text = "\(indexPath.row + 1)"

    thisSong = indexPath.row


    return cell
}



override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let vc  = segue.destination as? ViewControllerAudioDetail

    vc?.mod = [modalsF[(tableView.indexPathForSelectedRow?.row)!]]

}

【问题讨论】:

  • 我已经添加了我的答案,请在您的代码中添加这些方法,它肯定会起作用。如果有想要我有它的整个例子。
  • @AshokLondhe 我已经解决了这个问题,但你的方法也有效
  • 你是对的。两者都在工作,但我想建议我的答案,因为那是优化的代码。也很容易理解。如果在 AVPlayer 中有任何此类问题,请告诉我,我一定会帮助您。谢谢。
  • @AshokLondhe 你能帮我解决这个问题吗? stackoverflow.com/questions/44921042/…
  • 我当然愿意帮助你。

标签: ios swift uitableview swift3 avplayer


【解决方案1】:

播放所选/当前歌曲

func play(at index: Int) {
    audioPlayer.removeAllItems()
    playerItem = audioItems[index]
    playerItem?.seek(to: kCMTimeZero)
    audioPlayer.insert(playerItem!, after: nil)
    audioPlayer.play()
    isPlaying = true

    self.playAllSongsTableView.reloadData()
}

播放上一首歌曲....

@IBAction func backWordAction(_ sender: UIButton) {
   var index =  audioItems.index(of: audioPlayer.currentItem!) ?? 0
    if index > 0 {
        index = index - 1
    }
    play(at: index)
}

播放下一首歌曲....

@IBAction func forwordAction(_ sender: UIButton) {
    var index =  audioItems.index(of: audioPlayer.currentItem!) ?? 0
    if index < (audioItems.count - 1) {
        index = index + 1
    }
    play(at: index)

}

【讨论】:

    【解决方案2】:

    使用 AVQueuePlayer 代替 AVPlayer 可以让你直接添加项目;

    AVQueuePlayer.insert(item: AVPlayerItem, after: AVPlayerItem?)
    AVQueuePlayer.advanceToNextItem()
    

    您还可以使用 AVPlayerItems 数组初始化播放器

    AVQueuePlayer = AVQueuePlayer(items: [AVPlayerItem])
    

    【讨论】:

      【解决方案3】:

      在其tableview 中,我添加了func didSelectRowAt,其中我编写了一个接收单元格编号的全局计数器

       override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
      
          thisSong = indexPath.row
      
      }
      

      并通过prepareForSegue将数据传递给控制器​​

       override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
      
          if segue.identifier ==  "listToDetail"{
              let vc  = segue.destination as? ViewControllerAudioDetail
              vc?.mod = mod
          }
      }
      

      在我的详细控制器中,我为上一首歌曲和下一首歌曲创建了两个按钮

      var avPlayer:AVPlayer?
      
      var mod = [Modal]()
      
      
      @IBAction func Next(_ sender: Any) {
      
      
          if thisSong == mod.count - 1 {
              thisSong = 0
          } else {
              thisSong += 1
          }
      
      
          if thisSong != mod.count{
              avPlayer?.removeTimeObserver(sliderDuration)
      
              name.text = mod[thisSong].AudioName
              player(urlSong:mod[thisSong].UrlName!)
      
              Status()
      
          }
      
      }
      
      @IBAction func Back(_ sender: Any) {
      
      
          if thisSong != 0 {
              thisSong -= 1
          } else {
              thisSong = mod.endIndex
          }
      
      
              avPlayer?.removeTimeObserver(sliderDuration)
              name.text = mod[thisSong].AudioName
              player(urlSong:mod[thisSong].UrlName!)
      
             Status()
      
      
      
      
      }
      

      该函数确定哪个是播放器的状态并设置相同的数据

      func Status(){
          if status == true {
              iconChange.setImage(UIImage(named:"Pause.png"), for: .normal)
              avPlayer?.play()
          } else {
              iconChange.setImage(UIImage(named:"Play.png"), for: .normal)
              avPlayer?.pause()
          }
      
      }
      

      我在这里创建一个播放器

      func player(urlSong:String) {
      
          let url = URL(string: urlSong)
          let playerItem = AVPlayerItem(url: url!)
          avPlayer = AVPlayer(playerItem:playerItem)
      
      
           sliderDuration = avPlayer!.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main) { [weak self] (time) in
      
              let duration = CMTimeGetSeconds((self?.avPlayer!.currentItem!.asset.duration)!)
              self?.sliderSong.value = Float(CMTimeGetSeconds(time)) / Float(duration)
      
          }
      
      
          let duration = CMTimeGetSeconds(avPlayer!.currentItem!.asset.duration)
          let minutesTextOut = Int(duration) / 60 % 60
          let secondsTextOut = Int(duration) % 60
          let strDuration = String(format:"%02d:%02d", minutesTextOut, secondsTextOut)
          endTime.text = strDuration
      
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-28
        • 2012-07-16
        • 2017-01-05
        • 1970-01-01
        • 2017-06-05
        相关资源
        最近更新 更多