Переупорядочить музыкальную очередь MediaPlayer [iOS] - PullRequest
0 голосов
/ 14 января 2019

Я действительно изо всех сил пытаюсь что-то выяснить, я просмотрел весь Интернет и не могу найти ответ. Как вы знаете, музыкальные приложения, такие как Spotify и Apple Music, позволяют пользователю переставлять следующую очередь, даже когда пользователь слушает песню. Я не смог понять, как сделать то же самое. Я хочу иметь возможность полностью изменить порядок очереди, включая добавление, удаление и перемещение песен в следующей очереди. Я пробовал разные способы сделать это, например

musicPlayer.setQueue([queue])

но это потребовало бы от меня вызова musicPlayer.prepareToPlay() afterwords для обновления очереди, которая завершит текущую песню и инициирует новую очередь.

Я также пытался использовать

musicPlayer.perform(queueTransaction: { (currentQueue) in
    let oldItems = currentQueue.items

    var currentItem: MPMediaItem? = nil
    for (i, item) in oldItems.enumerated() {
        if i == musicPlayer.indexOfNowPlayingItem {
            currentItem = item
            continue
        }

        currentQueue.remove(item)
    }

    currentQueue.insert(queue, after: currentItem)
}, completionHandler: { (newQueue, error) in
    if let error = error {
        print("there was an error updating the queue", error)
        return
    }

    print("===  NEW QUEUE  ===")  //insert does not work
    for item in newQueue.items {
        print("  -", item.title ?? "[No Title]")
    }
})

но, как вы, возможно, знаете из этого вопроса: MPMusicPlayerControllerMutableQueue вставка песни Apple Music не работает

функция вставки после элемента в очереди, похоже, не работает (и я также пытался установить для элемента значение nil, которое иногда удаляло текущий элемент и устанавливало в очередь ничего). Я также знаю о musicPlayer.prepend([queue]), который добавит новую очередь после воспроизводимого в данный момент элемента, но мне также пришлось бы удалить предыдущую очередь из памяти, чтобы следующая очередь не имела длины более 300 песен. Я также пытался использовать функцию prepend внутри транзакции очереди, но иногда песня останавливалась посередине, и музыкальный проигрыватель устанавливал nowPlayingItem на ноль. Я действительно надеюсь, что кто-то знает ответ на этот вопрос, потому что у меня есть эта проблема уже более 4 дней, и я не могу найти решение, которое работает 100% времени.

1 Ответ

0 голосов
/ 14 января 2019

MPMusicPlayerController (и связанные с ним подклассы) очень затрудняет беспрепятственное управление такой очередью. Если я правильно помню, вы даже не можете добавить дубликаты MPMediaItem объектов в очередь, и нажатие на воспроизводимое мультимедиа из Центра управления фактически запустит приложение Музыка вместо вашего собственного. По сути, ваше приложение может действовать только как оболочка для воспроизведения музыки, а приложение «Музыка» выполняет всю тяжелую работу.

В зависимости от ваших требований у вас может быть другой вариант, хотя и с некоторыми компромиссами. Фреймворк AVFoundation обеспечивает AVPlayer и AVQueuePlayer, которые упрощают управление очередью и предоставляют более расширенные параметры воспроизведения. Однако вы можете воспроизводить только загруженный контент без DRM (т.е. песни из Apple Music не будут работать).

Настройте плеер:

let audioPlayer = AVQueuePlayer()

// Play next song in queue.
NotificationCenter.default.addObserver(self, selector: #selector(didPlayToEndTime), name: .AVPlayerItemDidPlayToEndTime, object: nil)

// Recover from failed playback.
NotificationCenter.default.addObserver(self, selector: #selector(failedToPlayToEndTime(_:)), name: .AVPlayerItemFailedToPlayToEndTime, object: nil)

// Resume music after interruptions.
NotificationCenter.default.addObserver(self, selector: #selector(handleAudioSessionInterruption(_:)), name: .AVAudioSessionInterruption, object: AVAudioSession.sharedInstance())

Вставить новые элементы в очередь:

let media = MPMediaQuery.songs()
let mediaItem: MPMediaItem = media.items.first!

// MPMediaItem objects stored in iCloud or from Apple Music
// will not have a URL, therefore, they cannot be played.
guard let assetURL: URL = mediaItem.assetURL else { return }

let playerItem = AVPlayerItem(url: assetURL)
playerItem.seek(to: kCMTimeZero)
audioPlayer.insert(playerItem, after: nil)

В моем приложении музыкального плеера у меня есть Array носителей, чтобы упростить процесс переупорядочения, вставки и извлечения носителей, а также индекс для отслеживания воспроизводимой в данный момент дорожки. Затем я передаю носитель в AVQueuePlayer по одному или двум за раз, чтобы мне не приходилось связываться с его API для вставки / удаления носителя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...