18

I am using an AVQueuePlayer in my app. I have a two swipe gestures to skip to next and skip to previous avplayeritems. Right now to do skip to next I am just calling advanceToNextItem on the avqueueplayer which works well.

However the skip to previous I am removing all items and adding them back in with the previous video up front, this is really slow when skipping to previous multiple times. How can I make this faster just like calling advanceToNextItem?

My code looks like this:

func skipToPrevious() {
    queuePlayer.removeAllItems()
    // move the previous playerItem to the front of the list then add them all back in
    for playerItem in playerItems:
        queuePlayer.insertItem(playerItem, afterItem: nil)

}
4

6 回答 6

28

似乎AVQueuePlayer在调用时从播放队列中删除了当前项目advanceToNextItem。从理论上讲,如果不重建队列,就无法取回该项目。

你可以做的是使用一个标准的AVPlayer,有一个数组AVPlayerItems,和一个整数索引,它保持当前轨道的索引。

斯威夫特 3:

let player = AVPlayer()
let playerItems = [AVPlayerItem]() // your array of items
var currentTrack = 0

func previousTrack() {
    if currentTrack - 1 < 0 {
        currentTrack = (playerItems.count - 1) < 0 ? 0 : (playerItems.count - 1)
    } else {
        currentTrack -= 1
    }

    playTrack()
}

func nextTrack() {
    if currentTrack + 1 > playerItems.count {
        currentTrack = 0
    } else {
        currentTrack += 1;
    }

    playTrack()
}

func playTrack() {

    if playerItems.count > 0 {
        player.replaceCurrentItem(with: playerItems[currentTrack])
        player.play()
    }
}

斯威夫特 2.x:

func previousTrack() {
    if currentTrack-- < 0 {
        currentTrack = (playerItems.count - 1) < 0 ? 0 : (playerItems.count - 1)
    } else {
        currentTrack--
    }

    playTrack()
}

func nextTrack() {
    if currentTrack++ > playerItems.count {
        currentTrack = 0
    } else {
        currentTrack++;
    }

    playTrack()
}

func playTrack() {

    if playerItems.count > 0 {
        player.replaceCurrentItemWithPlayerItem(playerItems[currentTrack])
        player.play()
    }
}
于 2016-01-26T14:15:42.563 回答
2

我正在考虑一种非常不同的方法,实际上是 AdvanceToNextItem 方法。你说AdvanceToNextItem 工作正常。所以我想知道你是否可以使用 AdvanceToNextItem 本身实现跳转到上一个,但是通过将队列指向当前播放项目的两个项目。

例如,如果您的队列是这个,而粗体是当前项目

ABCD E FGH

然后将当前项目设置为 C,然后使用 AdvanceToNextItem 使其播放 D。

不确定您的 AdvanceToNextItem 是如何实现的。所以这取决于它。

于 2016-02-01T11:43:54.733 回答
2

replaceCurrentItemWithPlayerItem限制,应尽可能避免,在Apple 的文档中,它指出“新项目必须具有与其替换的项目相同的合成器,或者没有合成器。”

而是使用循环一个一个地插入 playerItems,只需创建一个AVQueuePlayer会更快:

func skipToPrevious() {
    queuePlayer = AVQueuePlayer.queuePlayerWithItems(playerItem)
}
于 2016-01-26T15:12:30.123 回答
2

队列是否可以顺利处理多个向前跳过?如果是这样,您可以不断地将前一个视频重新插入到索引 n+2 处的队列中。当用户希望播放上一首曲目时,您将向前跳两次。

如果从音轨 A 播放到 F 没有任何跳过,则模式将如下所示:

A B C D E F
B C D E F

// re-insert A after next track
B C A D E F
C A D E F

// remove A then re-insert B
C D E F
C D B E F
D B E F

// remove B then re-insert C
D E F
D E C F
E C F

// remove C then re-insert D
E F
E F D
F D

// remove D then re-insert E
F
FE

使用这种模式,您只能平滑地向后跳过一次,但可以对其进行修改以允许更多。

绝对不是一个理想的解决方案,但可能会奏效!

于 2016-01-31T09:13:09.953 回答
1

您可以将当前项目替换为上一个项目并添加已替换的项目:

let previousItem = AVPlayerItem(url: url )
let currentItem = AVPlayerItem(url: currentUrl)

 player.replaceCurrentItem(with: previousItem)
    if player.canInsert(currentItem, after: previousItem) {
         player.insert(currentItem, after: previousItem)
    }

// 或者像这样

 let previousItem = AVPlayerItem(url: url )
 if let currentItem = player.currentItem {
   player.replaceCurrentItem(with: previousItem)
     if player.canInsert(currentItem, after: previousItem) {
         player.insert(currentItem, after: previousItem)
     }
  }
于 2020-01-19T01:07:39.287 回答
-1
  1. 在第一项之后插入第一项:
    player.insert(player.items()[0], after: player.items()[0])
  2. 在第一项之后插入重新创建的上一项:
    player.insert(prevItem, after: player.items()[0])
  3. 打电话player.advanceToNextItem()
于 2018-01-18T03:04:15.613 回答