gpt4 book ai didi

ios - 如何在 AVQueuePlayer 播放完 Que 中的所有内容后将其设置为开头

转载 作者:行者123 更新时间:2023-11-30 12:14:59 24 4
gpt4 key购买 nike

我有一个 AVQuePlayer,它正在下载用户发布到 firebase 的视频,然后通过 AVQuePlayer 按顺序播放它们。一切正常,直到视频队列播放所有视频,在这种情况下,如果您尝试重播队列,则会出现 SIGABRT 1 错误。我相信这是因为它正在寻找要播放的视频但不存在。我已经尝试在队列完成后重置playerItem数组,但没有成功。这是我到目前为止所拥有的。

从 Firebase 加载数据:

func loadStory() {
DataService.ds.REF_POSTS.observe(.value, with: { (snapshot) in
self.posts = []
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
for snap in snapshot {
if let dict = snap.value as? Dictionary<String, Any> {
let key = snap.key
let post = HotPosts(postID: key, postData: dict)
self.posts.append(post)
let media = post.mediaURL
let ref = Storage.storage().reference(forURL: media)
ref.downloadURL(completion: { (url, error) in
if error != nil {
print(error!)
} else {
self.videos.append(url!)
}
})

}
}
}
})
}

下载网址:

 func playStory() {


for vid in videos{


asset = AVAsset(url: vid)
let assetKeys = ["playable", "hasProtectedContent"]

let item = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: assetKeys)

item.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.old, .new], context: &myContext)

self.playerItem.append(item)

}

player = AVQueuePlayer(items: playerItem)
print(playerItem.count)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)


}

处理缓冲并在准备好时播放视频:

 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("playing1")
guard context == &myContext else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
print("playing2")
if keyPath == #keyPath(AVPlayerItem.status) {
let status: AVPlayerItemStatus
print("playing3")
if let statusNumber = change?[.newKey] as? NSNumber {
status = AVPlayerItemStatus(rawValue: statusNumber.intValue)!
} else {
status = .unknown
}

switch status {
case .readyToPlay:
print("We ARE IN THE CLEAR BOIIIIII")
player.play()
break

case .failed:
print("ITem Fialed")
break

case .unknown:
print("Could Not play the video")
break

}

}
}

最佳答案

尝试订阅此通知,看看它是否适合您的情况:

NotificationCenter.default.addObserver(self, selector: #selector(endOfAudio), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)

我还在一段 Apple 代码中发现了这一点,该代码说明了 avQueuePlayer 上某些 KVO 的使用 ( https://developer.apple.com/library/content/samplecode/avloopplayer/Listings/Projects_VideoLooper_VideoLooper_QueuePlayerLooper_swift.html )

/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information

Abstract:
An object that uses AVQueuePlayer to loop a video.
*/

// MARK: Convenience

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

player.addObserver(self, forKeyPath: ObserverContexts.playerStatusKey, options: .new, context: &ObserverContexts.playerStatus)
player.addObserver(self, forKeyPath: ObserverContexts.currentItemKey, options: .old, context: &ObserverContexts.currentItem)
player.addObserver(self, forKeyPath: ObserverContexts.currentItemStatusKey, options: .new, context: &ObserverContexts.currentItemStatus)

isObserving = true
}

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

player.removeObserver(self, forKeyPath: ObserverContexts.playerStatusKey, context: &ObserverContexts.playerStatus)
player.removeObserver(self, forKeyPath: ObserverContexts.currentItemKey, context: &ObserverContexts.currentItem)
player.removeObserver(self, forKeyPath: ObserverContexts.currentItemStatusKey, context: &ObserverContexts.currentItemStatus)

isObserving = false
}

// MARK: KVO

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &ObserverContexts.playerStatus {
guard let newPlayerStatus = change?[.newKey] as? AVPlayerStatus else { return }

if newPlayerStatus == AVPlayerStatus.failed {
print("End looping since player has failed with error: \(player?.error)")
stop()
}
}
else if context == &ObserverContexts.currentItem {
guard let player = player else { return }

if player.items().isEmpty {
print("Play queue emptied out due to bad player item. End looping")
stop()
}
else {
// If `loopCount` has been set, check if looping needs to stop.
if numberOfTimesToPlay > 0 {
numberOfTimesPlayed = numberOfTimesPlayed + 1

if numberOfTimesPlayed >= numberOfTimesToPlay {
print("Looped \(numberOfTimesToPlay) times. Stopping.");
stop()
}
}

/*
Append the previous current item to the player's queue. An initial
change from a nil currentItem yields NSNull here. Check to make
sure the class is AVPlayerItem before appending it to the end
of the queue.
*/
if let itemRemoved = change?[.oldKey] as? AVPlayerItem {
itemRemoved.seek(to: kCMTimeZero)

stopObserving()
player.insert(itemRemoved, after: nil)
startObserving()
}
}
}
else if context == &ObserverContexts.currentItemStatus {
guard let newPlayerItemStatus = change?[.newKey] as? AVPlayerItemStatus else { return }

if newPlayerItemStatus == .failed {
print("End looping since player item has failed with error: \(player?.currentItem?.error)")
stop()
}
}
else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
}

关于ios - 如何在 AVQueuePlayer 播放完 Que 中的所有内容后将其设置为开头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45537378/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com