AVPlayerLooper черная вспышка после каждой итерацииIOS

Программируем под IOS
Ответить
Гость
 AVPlayerLooper черная вспышка после каждой итерации

Сообщение Гость »

Я использую пример кода от Apple для воспроизведения видео на фоне UICollectionViewCell.

Я использую AVPlayerLooper, поскольку это повтор одного и того же видео.

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

Вот код:

Протокол от Apple

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

protocol Looper {

init(videoURL: URL, loopCount: Int)

func start(in layer: CALayer)

func stop()
}
Класс Player Looper, предоставленный Apple

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

// Code from Apple
class PlayerLooper: NSObject, Looper {
// MARK: Types

private struct ObserverContexts {
static var isLooping = 0

static var isLoopingKey = "isLooping"

static var loopCount = 0

static var loopCountKey = "loopCount"

static var playerItemDurationKey = "duration"
}

// MARK: Properties

private var player: AVQueuePlayer?

private var playerLayer: AVPlayerLayer?

private var playerLooper: AVPlayerLooper?

private var isObserving = false

private let numberOfTimesToPlay: Int

private let videoURL: URL

// MARK: Looper

required init(videoURL: URL, loopCount: Int) {
self.videoURL = videoURL
self.numberOfTimesToPlay = loopCount

super.init()
}

func start(in parentLayer: CALayer) {
player = AVQueuePlayer()
player?.isMuted = true
playerLayer = AVPlayerLayer(player: player)

guard let playerLayer = playerLayer else { fatalError("Error creating player layer") }
playerLayer.frame = parentLayer.bounds
parentLayer.addSublayer(playerLayer)

let playerItem = AVPlayerItem(url: videoURL)
playerItem.asset.loadValuesAsynchronously(forKeys: [ObserverContexts.playerItemDurationKey], completionHandler: {()->Void in
/*
The asset invokes its completion handler on an arbitrary queue when
loading is complete.  Because we want to access our AVPlayerLooper
in our ensuing set-up, we must dispatch our handler to the main queue.
*/
DispatchQueue.main.async(execute: {
guard let player = self.player else { return }

var durationError: NSError? = nil
let durationStatus = playerItem.asset.statusOfValue(forKey: ObserverContexts.playerItemDurationKey, error: &durationError)
guard durationStatus == .loaded else { fatalError("Failed to load duration property with error: \(String(describing: durationError))") }

self.playerLooper = AVPlayerLooper(player: player, templateItem: playerItem)
self.startObserving()
player.play()
})
})
}

func stop() {
player?.pause()
stopObserving()

playerLooper?.disableLooping()
playerLooper = nil

playerLayer?.removeFromSuperlayer()
playerLayer = nil

player = nil
}

// MARK: Convenience

private func startObserving() {
guard let playerLooper = playerLooper, !isObserving else { return }

playerLooper.addObserver(self, forKeyPath: ObserverContexts.isLoopingKey, options: .new, context: &ObserverContexts.isLooping)
playerLooper.addObserver(self, forKeyPath: ObserverContexts.loopCountKey, options: .new, context: &ObserverContexts.loopCount)

isObserving = true
}

private func stopObserving() {
guard let playerLooper = playerLooper, isObserving else { return }

playerLooper.removeObserver(self, forKeyPath: ObserverContexts.isLoopingKey, context: &ObserverContexts.isLooping)
playerLooper.removeObserver(self, forKeyPath: ObserverContexts.loopCountKey, context: &ObserverContexts.loopCount)

isObserving = false
}

// MARK: KVO

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &ObserverContexts.isLooping {
if let loopingStatus = change?[.newKey] as? Bool, !loopingStatus {
print("Looping ended due to an error")
}
}
else if context == &ObserverContexts.loopCount {
guard let playerLooper = playerLooper else { return }

if numberOfTimesToPlay > 0 && playerLooper.loopCount >= numberOfTimesToPlay - 1 {
print("Exceeded loop limit of \(numberOfTimesToPlay) and disabling looping");
stopObserving()
playerLooper.disableLooping()
}
}
else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
}
Инициализация петлителя ячеек просмотра моей коллекции

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

var looper: Looper? {
didSet {
configLooper()
}
}
func configLooper() {
looper?.start(in: layer)

}
Делегат представления моей коллекции для инициализации ячейки

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

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FirstLaunchCollectionViewCell
let videoURL = Bundle.main.url(forResource: "video3", withExtension: "MOV")
cell.looper = PlayerLooper(videoURL: videoURL!, loopCount: -1)
return cell
}
Для параметра LoopCount установлено значение -1, поэтому видео воспроизводится бесконечное количество раз.

Я пробовал использовать файлы меньшего размера, но в конце каждой итерации по-прежнему отображается черная рамка.

Кто-нибудь знает, что может быть причиной? это, или есть лучший подход? Исходный код Apple можно найти здесь

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

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

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

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

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

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