[英]Capturing video and saving it via AVAssetWriter
我想将AVAssetWriter
输出保存到相机胶卷,目前正在将其保存到documents目录。
我试图使用UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:)
。 我目前正在使用AVAssetWriter
写入.documentsdirectotry
。 但是,当我尝试写时,它会静默失败。 要编写,我将调用startRecording()
并调用stopRecording()
完成编写。
let captureSession = AVCaptureSession()
var videoOutput = AVCaptureVideoDataOutput()
var assetWriter: AVAssetWriter!
var assetWriterInput: AVAssetWriterInput!
var isCameraSetup = false
var hasStartedWritingCurrentVideo = false
var isWriting = false
let queue = DispatchQueue(label: "com.name.camera-queue")
// Camera preview setup code
//Setting up Asset Writer to save videos
public func setUpAssetWriter() {
do {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
let outputURL = URL(fileURLWithPath: documentsPath!).appendingPathComponent("test.m4v")
assetWriter = try! AVAssetWriter(outputURL: outputURL, fileType: .mp4)
assetWriterInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoOutput.recommendedVideoSettingsForAssetWriter(writingTo: .mp4))
assetWriterInput.expectsMediaDataInRealTime = true
if assetWriter.canAdd(assetWriterInput) {
assetWriter.add(assetWriterInput)
} else {
print("no input added")
}
assetWriter.startWriting()
} catch let error {
debugPrint(error.localizedDescription)
}
}
public func tearDownAssetWriter() {
assetWriter = nil
assetWriterInput = nil
}
public func startWriting(){
if isWriting{ return }
setUpAssetWriter()
hasStartedWritingCurrentVideo = false
isWriting = true
}
public func finishWriting(_ completion: @escaping (URL) -> Void) {
if isWriting == false { return }
isWriting = false
assetWriterInput.markAsFinished()
let url = self.assetWriter.outputURL
assetWriter.finishWriting {
completion(url)
self.tearDownAssetWriter()
}
hasStartedWritingCurrentVideo = false
}
// MARK: Starts the capture session
public func start() {
if !captureSession.isRunning {
captureSession.startRunning()
}
}
public func stop() {
if captureSession.isRunning {
captureSession.stopRunning()
}
}
// MARK: Records after camera is set up
public func startRecording() {
startWriting()
isWriting = true
}
public func stopRecording() {
assetWriterInput.markAsFinished()
assetWriter.finishWriting {
[weak self] in return
}
}
}
extension VideoCapture: AVCaptureVideoDataOutputSampleBufferDelegate {
public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
// Because lowering the capture device's FPS looks ugly in the preview,
// we capture at full speed but only call the delegate at its desired
// framerate.
let timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
let deltaTime = timestamp - lastTimestamp
if deltaTime >= CMTimeMake(value: 1, timescale: Int32(fps)) {
lastTimestamp = timestamp
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
delegate?.videoCapture(self, didCaptureVideoFrame: imageBuffer, timestamp: timestamp)
}
// Asset Writer
guard let assetWriter = assetWriter, let assetWriterInput = assetWriterInput else { return }
if isWriting == false{ return }
if self.assetWriter.status == .failed {
setUpAssetWriter()
hasStartedWritingCurrentVideo = false
}
if hasStartedWritingCurrentVideo == false && output === videoOutput { return }
if hasStartedWritingCurrentVideo == false {
hasStartedWritingCurrentVideo = true
let sourceTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
assetWriter.startSession(atSourceTime: sourceTime)
}
if output === videoOutput && assetWriterInput.isReadyForMoreMediaData{
if isWriting == false{return}
assetWriterInput.append(sampleBuffer)
}
}
}
当前的实现设置了摄像头和预览,但是没有任何内容保存到输出中。 它应该保存到.documentDirectory,但是不保存。 我想取而代之将其保存到相机胶卷,但是我不确定应该在哪里准确调用UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:)
。 我的扩展代表中可能有此问题。
预先感谢您的帮助。
我不熟悉UISaveVideoAtPathToSavedPhotosAlbum。 但是浏览堆栈溢出和git时,很多人都使用PHPhotoLibrary,我也是如此。无论URL如何,下面的代码都会将视频添加到photoLibrary中。
1)Info.plist通过+按钮添加新的键值对。 选择“ Privary-Photo Library使用说明”作为键。 设置值,例如“将视频保存在照片库中”
2)代码
fileWriter.finishWriting(completionHandler: {
let status = PHPhotoLibrary.authorizationStatus()
//no access granted yet
if status == .notDetermined || status == .denied{
PHPhotoLibrary.requestAuthorization({auth in
if auth == .authorized{
saveInPhotoLibrary(url)
}else{
print("user denied access to photo Library")
}
})
//access granted by user already
}else{
saveInPhotoLibrary(url)
}
})
private func saveInPhotoLibrary(_ url:URL){
PHPhotoLibrary.shared().performChanges({
//add video to PhotoLibrary here
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url)
}) { completed, error in
if completed {
print("save complete! path : " + url.absoluteString)
}else{
print("save failed")
}
}
}
希望这可以帮助。 GW
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.