Ios 下一步如何跟踪AVPlayer
我花了几天的时间试图制作一个包含下一首歌的按钮,但我做不到 这是我的问题 如何使用avPlayer在点击按钮时放置下一个掼掼掼掼ф掼掼 这是我的密码Ios 下一步如何跟踪AVPlayer,ios,swift,uitableview,swift3,avplayer,Ios,Swift,Uitableview,Swift3,Avplayer,我花了几天的时间试图制作一个包含下一首歌的按钮,但我做不到 这是我的问题 如何使用avPlayer在点击按钮时放置下一个掼掼掼掼ф掼掼 这是我的密码 class ViewControllerAudioDetail: UIViewController { var avPlayer:AVQueuePlayer? var status = false fileprivate let seekDuration: Float64 = 10 fileprivate let seekDurationThi
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
}
使用AVQueuePlayer代替AVPlayer可以让您直接添加项目
AVQueuePlayer.insert(item: AVPlayerItem, after: AVPlayerItem?)
AVQueuePlayer.advanceToNextItem()
您还可以使用AVPlayerItems数组初始化播放器
AVQueuePlayer = AVQueuePlayer(items: [AVPlayerItem])
使用AVQueuePlayer代替AVPlayer可以让您直接添加项目
AVQueuePlayer.insert(item: AVPlayerItem, after: AVPlayerItem?)
AVQueuePlayer.advanceToNextItem()
您还可以使用AVPlayerItems数组初始化播放器
AVQueuePlayer = AVQueuePlayer(items: [AVPlayerItem])
在它的tableview中,我添加了func didSelectRowAt,在其中我编写了一个全局计数器来接收单元格编号
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
thisSong = indexPath.row
}
并通过prepareForSegue将数据传递给控制器
在我的详细控制器中,我为前一首歌和下一首歌创建了两个按钮
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
}
在它的tableview中,我添加了func didSelectRowAt,在其中我编写了一个全局计数器来接收单元格编号
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
thisSong = indexPath.row
}
并通过prepareForSegue将数据传递给控制器
在我的详细控制器中,我为前一首歌和下一首歌创建了两个按钮
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
}
播放选定/当前歌曲
要播放Previous歌曲
播放下一首歌
播放选定/当前歌曲
要播放Previous歌曲
播放下一首歌
我已经添加了我的答案,请在您的代码中添加方法,它肯定会工作。如果你需要的话,我有一个完整的例子。@Ashoklondh我已经解决了这个问题,但是你的方法也很有效。你是对的。这两种方法都有效,但我想建议大家使用我的答案,因为这是经过优化的代码。而且它很容易理解。如果有任何这样的问题在AVPlayer让我知道我一定会帮助你。谢谢。@Ashoklondh你能帮我解决这个问题吗?当然,我想帮助你。我已经添加了我的答案,请在你的代码中添加方法,它肯定会工作。如果你需要的话,我有一个完整的例子。@Ashoklondh我已经解决了这个问题,但是你的方法也很有效。你是对的。这两种方法都有效,但我想建议大家使用我的答案,因为这是经过优化的代码。而且它很容易理解。如果有任何这样的问题在AVPlayer让我知道我一定会帮助你。谢谢。@Ashoklondh你能帮我解决这个问题吗?我当然愿意帮助你。