我正在使用基本viewController封装的摄像头,它具有用于回调的委托样式接口,所以我必须作为客户端执行的所有操作都是子类相机视图控制器,实现委托方法,并添加UI按钮。 我的问题是关于录制视频。视频录制在独特的后台任务上启动,以确保录制内容可以写入临时文件。这是对我的 private let sessionQueue = DispatchQueue(label: "com.andrewferrarone.sessionQueue")
会话队列完成:从另一个队列派发代表回调到主队列AVFoundation
public func startRecording()
{
guard let movieFileOutput = self.movieFileOutput else { return }
//get video preview layer's video orientation on main queue
guard let videoPreviewLayerOrientation = self.previewView.videoPreviewLayer?.connection.videoOrientation else {
print("handleRecord: videoPreviewLayer is nil")
return
}
self.sessionQueue.async {
if !movieFileOutput.isRecording {
if UIDevice.current.isMultitaskingSupported {
self.backgroundRecordingID = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
}
//update orientation on the movie file output video connection before recording
let movieFileOutputConnection = self.movieFileOutput?.connection(withMediaType: AVMediaTypeVideo)
movieFileOutputConnection?.videoOrientation = videoPreviewLayerOrientation
//start recording to a temporary file:
let outputFileName = UUID().uuidString
let outputFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent((outputFileName as NSString).appendingPathExtension("mov")!)
movieFileOutput.startRecording(toOutputFileURL: URL(fileURLWithPath: outputFilePath), recordingDelegate: self)
}
}
}
所以录音效果设置为后台任务分派到self.sessionQueue。当我停止录制时,我收到一个AVCaptureFileOutputRecordingDelegate
方法。在这种方法中,我想用文件路径回调我的委托,然后清理。如何在清除发生并删除临时文件之前,确保委托可以从临时文件路径持续记录?
public func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!)
{
//cleanup func for later
func cleanup()
{
let path = outputFileURL.path
if FileManager.default.fileExists(atPath: path) {
do {
try FileManager.default.removeItem(atPath: path)
}
catch let error {
print("Could not remove file at url: \(outputFileURL), error: \(error.localizedDescription)")
}
}
if let currentBackgroundRecordingID = self.backgroundRecordingID {
self.backgroundRecordingID = UIBackgroundTaskInvalid
if currentBackgroundRecordingID != UIBackgroundTaskInvalid {
UIApplication.shared.endBackgroundTask(currentBackgroundRecordingID)
}
}
}
var success = true
if error != nil {
print("Movie file finishing error: \(error)")
success = ((error as NSError).userInfo[AVErrorRecordingSuccessfullyFinishedKey] as AnyObject).boolValue
}
DispatchQueue.main.async {
self.delegate?.camera(self, didFinishRecordingToOutputFileAt: outputFileURL, success: success)
}
cleanup()
}
所以我打电话给我的委托回到主队列的结果,但我需要调用cleanup()
我应该叫回我的委托后立即做这个主队列?这是安全的吗?或者如果我以现在的方式离开它,那么我们在self.sessionQueue
,我不确定cleanup()
将在代表方法实现有时间持续记录之前发生。如果任何人都能给我一些关于正在发生的事情以及在这里最安全的事情的见解,那将会很棒。根据苹果,文档说,不要假设AVCaptureFileOutputRecordingDelegate didFinishRecordingToOutputFileAt
方法在特定的线程上被调用。感谢您的时间和帮助!