gpt4 book ai didi

ios - 当AVPlayer项为 ".readyToPlay"时如何仅播放videoPreviewLayer

转载 作者:行者123 更新时间:2023-11-30 10:58:24 35 4
gpt4 key购买 nike

我正在努力实现与 snapchat 相同的目标。也就是说,当用户完成拍摄视频并进入预览 View 时,视频会卡住一秒钟左右,直到视频准备好播放为止,然后开始播放。我正在努力实现同样的目标。以下是我尝试过的,

            while playerItem1.status == .unknown {
print("1111121232432431243123241432143243214324321")
if playerItem1.status == .readyToPlay {

playerQueue = AVQueuePlayer(playerItem: playerItem1)
self.playerQueue?.play()

playerLayer = AVPlayerLayer(player: playerQueue)
playerLayer.frame = (camPreview?.bounds)!
playerLayer?.layoutIfNeeded()
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

camPreview?.layer.insertSublayer(playerLayer, above: previewLayer)

playerLooper = AVPlayerLooper(player: playerQueue, templateItem: playerItem1)
}
}

然而这会导致 xcode 崩溃,因为它似乎永远不会结束。我不明白这一点,因为在某些时候状态应该变成 .readyToPlay,因为如果我不理会它,它就会这样做。

主要是我想这样做,因为目前当您放开我的代码中的捕获按钮时,屏幕会卡住然后进行转换。我希望它卡住视频而不是捕获屏幕。

    extension ViewController: AVCaptureFileOutputRecordingDelegate {
//MARK: - Protocal stubs
func capture(_ captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAt fileURL: URL!, fromConnections connections: [Any]!) { print("bruh? MMMM") }

func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) {
}

func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {

if (error != nil) {
print("Error recording movie11: \(error!.localizedDescription)")
} else {
newViewVideoPlayback()

switchIcon.isHidden = true
switchWhiteUI.isHidden = true
switchCamButton.isHidden = true
camWhiteLine.isHidden = true

// let videoRecorded = outputURL! as URL
// playerItem1 = AVPlayerItem(url: videoRecorded)


if !captureSession.isRunning {
DispatchQueue.global(qos: .background).async {
self.startRunningCaptureSession()
}
}
}

}
let videoRecorded = outputURL! as URL
playerItem1 = AVPlayerItem(url: videoRecorded)

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

override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {

// Only handle observations for the playerItemContext
guard context == &playerItemContext else {
super.observeValue(forKeyPath: keyPath,
of: object,
change: change,
context: context)
return
}

if keyPath == #keyPath(AVPlayerItem.status) {
let status: AVPlayerItem.Status
if let statusNumber = change?[.newKey] as? NSNumber {
status = AVPlayerItem.Status(rawValue: statusNumber.intValue)!
} else {
status = .unknown
}

// Switch over status value
switch status {
case .readyToPlay:
// Player item is ready to play.

playerQueue = AVQueuePlayer(playerItem: playerItem1)
self.playerQueue?.play()

playerLayer = AVPlayerLayer(player: playerQueue)
playerLayer.frame = (camPreview?.bounds)!
playerLayer?.layoutIfNeeded()
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

camPreview?.layer.insertSublayer(playerLayer, above: previewLayer)

playerLooper = AVPlayerLooper(player: playerQueue, templateItem: playerItem1)

case .failed: break
// Player item failed. See error.
case .unknown: break
// Player item is not yet ready.
}
}
}

}

最佳答案

来自Docs

When a player item is created, its status is AVPlayerItem.Status.unknown, meaning its media hasn’t been loaded and has not yet been enqueued for playback. Associating a player item with an AVPlayer immediately begins enqueuing the item’s media and preparing it for playback. When the player item’s media has been loaded and is ready for use, its status will change to AVPlayerItem.Status.readyToPlay. You can observe this change using key-value observing.

因此,您需要监听状态,而不是制作一个 while 循环,该循环会压垮系统,直到状态发生变化,这也在 Docs 中。

private var playerItemContext = 0
playerItem.addObserver(self,
forKeyPath: #keyPath(AVPlayerItem.status),
options: [.old, .new],
context: &playerItemContext)

override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {

// Only handle observations for the playerItemContext
guard context == &playerItemContext else {
super.observeValue(forKeyPath: keyPath,
of: object,
change: change,
context: context)
return
}

if keyPath == #keyPath(AVPlayerItem.status) {
let status: AVPlayerItemStatus
if let statusNumber = change?[.newKey] as? NSNumber {
status = AVPlayerItemStatus(rawValue: statusNumber.intValue)!
} else {
status = .unknown
}

// Switch over status value
switch status {
case .readyToPlay:
// Player item is ready to play.
case .failed:
// Player item failed. See error.
case .unknown:
// Player item is not yet ready.
}
}
}
<小时/>
extension ViewController: AVCaptureFileOutputRecordingDelegate {
//MARK: - Protocal stubs
func capture(_ captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAt fileURL: URL!, fromConnections connections: [Any]!) { print("bruh? MMMM") }

func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) {
}

func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {

if (error != nil) {
print("Error recording movie11: \(error!.localizedDescription)")
} else {
newViewVideoPlayback()

switchIcon.isHidden = true
switchWhiteUI.isHidden = true
switchCamButton.isHidden = true
camWhiteLine.isHidden = true

let videoRecorded = outputURL! as URL
playerItem1 = AVPlayerItem(url: videoRecorded)
playerItem1.addObserver(self,
forKeyPath: #keyPath(AVPlayerItem.status),
options: [.old, .new],
context: &playerItemContext)
playerQueue = AVQueuePlayer(playerItem: playerItem1)

if !captureSession.isRunning {
DispatchQueue.global(qos: .background).async {
self.startRunningCaptureSession()
}
}
}
}
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {

// Only handle observations for the playerItemContext
guard context == &playerItemContext else {
super.observeValue(forKeyPath: keyPath,
of: object,
change: change,
context: context)
return
}

if keyPath == #keyPath(AVPlayerItem.status) {
let status: AVPlayerItem.Status
if let statusNumber = change?[.newKey] as? NSNumber {
status = AVPlayerItem.Status(rawValue: statusNumber.intValue)!
} else {
status = .unknown
}

// Switch over status value
switch status {
case .readyToPlay:
playerLayer = AVPlayerLayer(player: playerQueue)
playerLayer.frame = (camPreview?.bounds)!
playerLayer?.layoutIfNeeded()
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
camPreview?.layer.insertSublayer(playerLayer, above: previewLayer)
playerLooper = AVPlayerLooper(player: playerQueue, templateItem: playerItem1)
// Player item is ready to play.
self.playerQueue?.play(
case .failed: break
// Player item failed. See error.
case .unknown: break
// Player item is not yet ready.
}
}
}
}

关于ios - 当AVPlayer项为 ".readyToPlay"时如何仅播放videoPreviewLayer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53686445/

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