使用AVAssetWriter
捕获视频时会发生此错误。但是,在finishWriting
内部调用AVAssetWriter endVideoCapture
之后,又没有再次开始写入的调用,为什么会出现这种情况呢?
正如您在委托函数captureOutput
中看到的那样,我们在尝试附加到资产编写者之前检查记录状态。 endVideoCapture.
可选(错误域= AVFoundationErrorDomain代码= -11862"不能 在结束会议后附加媒体数据" UserInfo = {NSLocalizedFailureReason =应用程序遇到了 编程错误。,NSLocalizedDescription =操作不是 允许,NSDebugDesc
func startVideoCapture() {
// Get capture resolution
let resolution = getCaptureResolution()
// Return if capture resolution not set
if resolution.width == 0 || resolution.height == 0 {
printError("Error starting capture because resolution invalid")
return
}
// If here, start capture
assetWriter = createAssetWriter(Int(resolution.width), outputHeight: Int(resolution.height))
let recordingClock = captureSession.masterClock
assetWriter!.startWriting()
assetWriter!.startSession(atSourceTime: CMClockGetTime(recordingClock!))
// Update time stamp
startTime = CACurrentMediaTime()
// Update <recording> flag & notify delegate
recording = true
delegate?.cameraDidStartVideoCapture()
}
func createAssetWriter(_ outputWidth: Int, outputHeight: Int) -> AVAssetWriter? {
// Update <outputURL> with temp file to hold video
let tempPath = gFile.getUniqueTempPath(gFile.MP4File)
outputURL = URL(fileURLWithPath: tempPath)
// Return new asset writer or nil
do {
// Create asset writer
let newWriter = try AVAssetWriter(outputURL: outputURL, fileType: AVFileTypeMPEG4)
// Define video settings
let videoSettings: [String : AnyObject] = [
AVVideoCodecKey : AVVideoCodecH264 as AnyObject,
AVVideoWidthKey : outputWidth as AnyObject,
AVVideoHeightKey : outputHeight as AnyObject,
]
// Add video input to writer
assetWriterVideoInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: videoSettings)
assetWriterVideoInput!.expectsMediaDataInRealTime = true
newWriter.add(assetWriterVideoInput!)
// Define audio settings
let audioSettings : [String : AnyObject] = [
AVFormatIDKey : NSInteger(kAudioFormatMPEG4AAC) as AnyObject,
AVNumberOfChannelsKey : 2 as AnyObject,
AVSampleRateKey : NSNumber(value: 44100.0 as Double)
]
// Add audio input to writer
assetWriterAudioInput = AVAssetWriterInput(mediaType: AVMediaTypeAudio, outputSettings: audioSettings)
assetWriterAudioInput!.expectsMediaDataInRealTime = true
newWriter.add(assetWriterAudioInput!)
// Return writer
print("Created asset writer for \(outputWidth)x\(outputHeight) video")
return newWriter
} catch {
printError("Error creating asset writer: \(error)")
return nil
}
}
func endVideoCapture() {
// Update flag to stop data capture
recording = false
// Return if asset writer undefined
if assetWriter == nil {
return
}
// If here, end capture
// -- Mark inputs as done
assetWriterVideoInput!.markAsFinished()
assetWriterAudioInput!.markAsFinished()
// -- Finish writing
assetWriter!.finishWriting() {
self.assetWriterDidFinish()
}
}
func assetWriterDidFinish() {
print("Asset writer finished with status: \(getAssetWriterStatus())")
// Return early on error & tell delegate
if assetWriter!.error != nil {
printError("Error finishing asset writer: \(assetWriter!.error)")
delegate?.panabeeCameraDidEndVideoCapture(videoURL: nil, videoDur: 0, error: assetWriter!.error)
logEvent("Asset Writer Finish Error", userData: ["Error" : assetWriter!.error.debugDescription])
return
}
// If here, no error so extract video properties & tell delegate
let videoAsset = AVURLAsset(url: outputURL, options: nil)
let videoDur = CMTimeGetSeconds(videoAsset.duration)
let videoTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0]
print("Camera created video. Duration: \(videoDur). Size: \(videoTrack.naturalSize). Transform: \(videoTrack.preferredTransform). URL: \(outputURL).")
// Tell delegate
delegate?.cameraDidEndVideoCapture(videoURL: outputURL.path, videoDur: videoDur, error: assetWriter!.error)
// Reset <assetWriter> to nil
assetWriter = nil
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
// Return if not recording
if !recording {
return
}
// If here, capture data
// Write video data?
if captureOutput == videoOutput && assetWriterVideoInput!.isReadyForMoreMediaData {
assetWriterVideoQueue!.async {
self.assetWriterVideoInput!.append(sampleBuffer)
}
}
// No, write audio data?
if captureOutput == audioOutput && assetWriterAudioInput!.isReadyForMoreMediaData {
assetWriterAudioQueue!.async {
self.assetWriterAudioInput!.append(sampleBuffer)
}
}
}