我正在尝试达到手套的作用。也就是说,当用户完成拍摄视频并进入预览视图时,该视频将被冻结一秒钟左右,直到该视频准备好播放为止,此时它将开始播放。我正尝试达到同样的效果。贝娄是我尝试过的
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
,因为如果我不理会它,它就会这样做。我主要是想这样做,因为当前当您在我的代码中放开CaptureButton时,屏幕冻结,然后过渡。我希望它冻结视频而不是捕获屏幕。
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
创建播放器项目后,其状态为AVPlayerItem.Status.unknown,这表示其媒体尚未加载且尚未排队播放。将播放器项目与AVPlayer关联后,立即开始使该项目的媒体入队,并准备进行播放。当播放器项目的媒体已加载并可以使用时,其状态将更改为AVPlayerItem.Status.readyToPlay。您可以使用键值观察来观察此更改。
因此,您需要侦听状态,而不是进行可能会使系统不知所措的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/