Подтвердить что ты не робот

Лучший способ сделать переход к предыдущему с помощью AVQueuePlayer?

Я использую AVQueuePlayer в своем приложении. У меня есть два салфетки, чтобы перейти к следующему и перейти к предыдущим avplayeritems. Прямо сейчас, чтобы сделать переход к следующему, я просто вызываю forwardToNextItem на avqueueplayer, который хорошо работает.

Однако переход к предыдущему я удаляю все элементы и добавляю их обратно с предыдущим видео вверх, это очень медленно при переходе к предыдущему несколько раз. Как я могу сделать это быстрее, как вызов advanceToNextItem?

Мой код выглядит следующим образом:

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)

}
4b9b3361

Ответ 1

Кажется, что AVQueuePlayer удаляет текущий элемент из очереди воспроизведения при вызове advanceToNextItem. Теоретически, нет способа вернуть этот элемент без восстановления очереди.

Что вы можете сделать, это использовать стандартный AVPlayer, иметь массив AVPlayerItems и целочисленный индекс, который хранит индекс текущей дорожки.

Swift 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()
    }
}

Swift 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()
    }
}

Ответ 2

replaceCurrentItemWithPlayerItem имеет ограничение и его следует избегать, если это возможно, в документе Apple, в нем говорится: "Новый элемент должен иметь один и тот же компоновщик как элемент, который он заменяет, или нет композитора".

вместо этого вставьте элементы player один за другим с помощью цикла, просто создайте AVQueuePlayer будет быстрее:

func skipToPrevious() {
    queuePlayer = AVQueuePlayer.queuePlayerWithItems(playerItem)
}

Ответ 3

обрабатывает ли очередь более одного прохода вперед плавно? если это так, вы можете постоянно повторно вставлять предыдущее видео обратно в очередь с индексом 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

используя этот шаблон, вы можете плавно пропустить назад один раз, но его можно изменить, чтобы позволить больше.

определенно не идеальное решение, но может работать!

Ответ 4

Я думаю совсем другой подход, который на самом деле с точки зрения метода advanceToNextItem. Вы сказали, что advanceToNextItem отлично работает. Поэтому мне интересно, можете ли вы реализовать переход к предыдущему с помощью метода advanceToNextItem, но указав в очереди два элемента в обратном направлении от текущего элемента воспроизведения.

например. если вы в очереди, и жирным является текущий элемент

A B C D E F G H

Затем установите текущий элемент на C, а затем используйте forwardToNextItem, чтобы он воспроизводил D.

Не знаю, как реализован ваш advanceToNextItem. Так что это зависит от этого.

Ответ 5

  • Вставить первый элемент после первого элемента:
    player.insert(player.items()[0], after: player.items()[0]).
  • Вставить воссозданный предыдущий элемент после первого элемента:
    player.insert(prevItem, after: player.items()[0])
  • Вызов player.advanceToNextItem().