私は、コールバック用のデリゲートスタイルのインターフェイスを持つ、基本viewControllerでラップされたカメラで作業しているので、クライアントとして行う必要があります。カメラビューコントローラ、デリゲートメソッドを実装し、UIボタンを追加します。 私の質問は、ビデオを録画することです。独自のバックグラウンドタスクでビデオ録画が開始され、録画を一時ファイルに書き込むことができます。デリゲートコールバックを別のキューからメインキューにディスパッチ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に派遣バックグラウンドタスクとして設定され:これは私の private let sessionQueue = DispatchQueue(label: "com.andrewferrarone.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()
が起こるかどうかはわかりません。誰が私に何が起こっているのか、そしてここでやるのが一番安全なことについていくらかの洞察を与えることができれば、それは素晴らしいことです。 Appleによると、ドキュメントには、特定のスレッドでAVCaptureFileOutputRecordingDelegate didFinishRecordingToOutputFileAt
メソッドが呼び出されているとは限りません。あなたの時間と助けてくれてありがとう!私はそれがこのような状況を処理する標準的な方法になると思います
DispatchQueue.main.async {
self.delegate?.camera(self, didFinishRecordingToOutputFileAt: outputFileURL, success: success)
self.sessionQueue.async {
cleanup()
}
}
:どの程度