AVPlayer в UICollectionViewCell не воспроизводится/кадр playerLayer не соответствует границам ячейкиIOS

Программируем под IOS
Ответить
Anonymous
 AVPlayer в UICollectionViewCell не воспроизводится/кадр playerLayer не соответствует границам ячейки

Сообщение Anonymous »

У меня есть UICollectionViewCell, который должен воспроизводить видео с удаленного URL-адреса. Я создаю AVPlayer, добавляю AVPlayerLayer в представление контейнера внутри ячейки и пытаюсь загрузить ресурс асинхронно. Однако:
Видео не воспроизводится.
Кадр playerLayer имеет неправильный размер в соответствии с контейнером (vw_playVideo) — LayoutSubviews устанавливает его неправильно / слой имеет неправильные границы.
Я также вижу некоторые предупреждения консоли (например, CUICatalog: указано неверное имя актива: '') и предупреждения аудио/аудиосистемы ранее.
Ниже указан точный класс ячеек, который я использую:

Код: Выделить всё

import UIKit
import AVKit

class ProfileImageCVC: UICollectionViewCell {

@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var vw_playVideo: UIView!
@IBOutlet weak var img_thumbnail: UIImageView!

private var playerLayer: AVPlayerLayer?
private var player: AVPlayer?

override func awakeFromNib() {
super.awakeFromNib()
}

override func layoutSubviews() {
super.layoutSubviews()
playerLayer?.frame = vw_playVideo.bounds
playerLayer?.videoGravity = .resizeAspectFill
}

func PauseVideo() {
if player != nil {
player?.pause()
}
}

func playVideo() {
if player != nil {
player?.play()
}
}

func configureVideo(with urlString: String) {
guard let url = URL(string: urlString) else { return }

// these two lines are currently before player is created (left as in my code)
player?.automaticallyWaitsToMinimizeStalling = true
player?.currentItem?.preferredForwardBufferDuration = 1

player = AVPlayer(url: url)
playerLayer = AVPlayerLayer(player: player)

guard let playerLayer = playerLayer else { return }

playerLayer.videoGravity = .resizeAspectFill
vw_playVideo.layer.addSublayer(playerLayer)
layoutIfNeeded()

NotificationCenter.default.addObserver(
self,
selector: #selector(playerDidFinishPlaying),
name: .AVPlayerItemDidPlayToEndTime,
object: player?.currentItem
)

player?.currentItem?.asset.loadValuesAsynchronously(forKeys: ["playable"]) {
DispatchQueue.main.async {
self.player?.seek(to: .zero, completionHandler: { _ in
print("{\"now playing\"}")
self.vw_playVideo.stopSkeletonAnimation()
self.vw_playVideo.isSkeletonable = false
// self.player?.play()
})
}
}
}

@objc private func playerDidFinishPlaying() {
player?.seek(to: .zero)
player?.play()
}

deinit {
NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
}
}

Среда
Версия Xcode: (добавьте свою версию Xcode)
Цель iOS: (добавьте версию iOS)
Устройство: iPhone / Simulator
Протестированный URL-адрес видео: (добавьте использованный URL-адрес примера)
Что я ожидаю
playerLayer должен соответствовать vw_playVideo.bounds и отобразить видео.
Видео должно начать воспроизводиться, как только ресурс будет готов (или когда я вызову player.play()).
Что происходит на самом деле
В ячейке отображается пустая область (миниатюра может быть видна), видео не воспроизводится автоматически.
playerLayer имеет неправильный размер/не отображается. LayoutSubviews(), кажется, работает, но границы слоев остаются неправильными.
Консоль содержит несвязанные предупреждения, такие как CUICatalog: указано неверное имя ресурса: '' (не уверен, связано ли это) и более ранние аудиожурналы.
Что я пробовал
Настроить player?.automaticallyWaitsToMinimizeStalling на false или true.
Вызов player?.play() в завершении loadValuesAsynchronous (закомментировано выше).
Вызов layoutIfNeeded() и установка playerLayer.frame = vw_playVideo.bounds сразу после добавления слоя.
Перенос настройки аудиосессии на уровень приложения.
Наблюдение playerItem.status через KVO (не показано выше).
Обеспечение configureVideo вызывается в основном потоке.
Журналы/предупреждения консоли
CUICatalog: указано неверное имя актива: ''
LoudnessManager.mm:1215 IsHardwareSupported: plist не загружен, возвращается false
HALC_ProxyIOContext.cpp:1623 HALC_ProxyIOContext::IOWorkLoop: пропуск цикла из-за перегрузки
(Рис) сигнализирует err=-12900 ...
> сигнализирует err=-12852 ...
Вопросы
Почему размер playerLayer не соответствует границам ячейки vw_playVideo? (Я устанавливаю playerLayer?.frame = vw_playVideo.bounds в LayoutSubviews.)
Почему видео не начинает воспроизводиться даже после того, как метод assets.loadValuesAsynchronous(forKeys: ["playable"]) завершается и я вызываю seek(to:)/play()?
Каков правильный жизненный цикл и размещение для создания AVPlayer, AVPlayerItem, AVPlayerLayer внутри ячейки многократного использования, чтобы она работала плавно (и не складывала слои/наблюдатели утечек) при повторном использовании ячеек?
Являются ли предупреждения консоли Fig/LoudnessManager/CUICatalog признаками более глубокой проблемы или не связаны с ней?
Соответствующие примечания/подсказки, которые я видел в ответах
Я подозреваю, что я создаю проигрыватель до того, как ячейка получит окончательный макет, или не очищаю предыдущие слои/наблюдатели на повторное использование.
Я также могу установить player?.automaticallyWaitsToMinimizeStalling и PreferenceForwardBufferDuration для нулевого проигрывателя (я оставил все как есть выше).
Любая помощь или минимальный пример, показывающий правильный шаблон для UICollectionViewCell, который воспроизводит URL-адрес AVPlayer, будут оценены.
image
введите описание изображения здесь

Подробнее здесь: https://stackoverflow.com/questions/798 ... atching-ce
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»