Capturing video and saving it via AVAssetWriter
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I want to save AVAssetWriter output to the camera roll, I'm currently saving it to the documents directory.
I have tried to use the UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:) . I am currently using AVAssetWriter to write to the .documentsdirectotry. However, when I try to write, it fails silently. To write, I'll call startRecording() and I'll call stopRecording() to finish writing.
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)
}
}
}
The current implementation sets up the camera and preview, but then nothing is saved to the output.
It should save to the .documentDirectory, however, it's not saving. I would like to instead get it to save to the camera roll, but I'm not sure where exactly I should call UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:).
The problem is likely in my extension delegate.
Thank you in advance for your help.
ios avfoundation avassetwriter avcapture avcaptureoutput
add a comment |
I want to save AVAssetWriter output to the camera roll, I'm currently saving it to the documents directory.
I have tried to use the UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:) . I am currently using AVAssetWriter to write to the .documentsdirectotry. However, when I try to write, it fails silently. To write, I'll call startRecording() and I'll call stopRecording() to finish writing.
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)
}
}
}
The current implementation sets up the camera and preview, but then nothing is saved to the output.
It should save to the .documentDirectory, however, it's not saving. I would like to instead get it to save to the camera roll, but I'm not sure where exactly I should call UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:).
The problem is likely in my extension delegate.
Thank you in advance for your help.
ios avfoundation avassetwriter avcapture avcaptureoutput
add a comment |
I want to save AVAssetWriter output to the camera roll, I'm currently saving it to the documents directory.
I have tried to use the UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:) . I am currently using AVAssetWriter to write to the .documentsdirectotry. However, when I try to write, it fails silently. To write, I'll call startRecording() and I'll call stopRecording() to finish writing.
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)
}
}
}
The current implementation sets up the camera and preview, but then nothing is saved to the output.
It should save to the .documentDirectory, however, it's not saving. I would like to instead get it to save to the camera roll, but I'm not sure where exactly I should call UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:).
The problem is likely in my extension delegate.
Thank you in advance for your help.
ios avfoundation avassetwriter avcapture avcaptureoutput
I want to save AVAssetWriter output to the camera roll, I'm currently saving it to the documents directory.
I have tried to use the UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:) . I am currently using AVAssetWriter to write to the .documentsdirectotry. However, when I try to write, it fails silently. To write, I'll call startRecording() and I'll call stopRecording() to finish writing.
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)
}
}
}
The current implementation sets up the camera and preview, but then nothing is saved to the output.
It should save to the .documentDirectory, however, it's not saving. I would like to instead get it to save to the camera roll, but I'm not sure where exactly I should call UISaveVideoAtPathToSavedPhotosAlbum(_:_:_:_:).
The problem is likely in my extension delegate.
Thank you in advance for your help.
ios avfoundation avassetwriter avcapture avcaptureoutput
ios avfoundation avassetwriter avcapture avcaptureoutput
asked Jan 3 at 20:18
Brody HigbyBrody Higby
244
244
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
I am not familiar with UISaveVideoAtPathToSavedPhotosAlbum. But browsing stack overflow and git, many people use PHPhotoLibrary and so do I. Regardless of url, code below adds the video to photoLibrary.
https://developer.apple.com/documentation/photokit/phassetchangerequest/1624057-creationrequestforassetfromvideo
1) Info.plist
Add new key-value pair by + button. Select "Privary - Photo Library Usage Description" as a key. Set value something like "save video in photo library"
2) code
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")
}
}
}
Hope this helps.
GW
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54029217%2fcapturing-video-and-saving-it-via-avassetwriter%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I am not familiar with UISaveVideoAtPathToSavedPhotosAlbum. But browsing stack overflow and git, many people use PHPhotoLibrary and so do I. Regardless of url, code below adds the video to photoLibrary.
https://developer.apple.com/documentation/photokit/phassetchangerequest/1624057-creationrequestforassetfromvideo
1) Info.plist
Add new key-value pair by + button. Select "Privary - Photo Library Usage Description" as a key. Set value something like "save video in photo library"
2) code
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")
}
}
}
Hope this helps.
GW
add a comment |
I am not familiar with UISaveVideoAtPathToSavedPhotosAlbum. But browsing stack overflow and git, many people use PHPhotoLibrary and so do I. Regardless of url, code below adds the video to photoLibrary.
https://developer.apple.com/documentation/photokit/phassetchangerequest/1624057-creationrequestforassetfromvideo
1) Info.plist
Add new key-value pair by + button. Select "Privary - Photo Library Usage Description" as a key. Set value something like "save video in photo library"
2) code
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")
}
}
}
Hope this helps.
GW
add a comment |
I am not familiar with UISaveVideoAtPathToSavedPhotosAlbum. But browsing stack overflow and git, many people use PHPhotoLibrary and so do I. Regardless of url, code below adds the video to photoLibrary.
https://developer.apple.com/documentation/photokit/phassetchangerequest/1624057-creationrequestforassetfromvideo
1) Info.plist
Add new key-value pair by + button. Select "Privary - Photo Library Usage Description" as a key. Set value something like "save video in photo library"
2) code
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")
}
}
}
Hope this helps.
GW
I am not familiar with UISaveVideoAtPathToSavedPhotosAlbum. But browsing stack overflow and git, many people use PHPhotoLibrary and so do I. Regardless of url, code below adds the video to photoLibrary.
https://developer.apple.com/documentation/photokit/phassetchangerequest/1624057-creationrequestforassetfromvideo
1) Info.plist
Add new key-value pair by + button. Select "Privary - Photo Library Usage Description" as a key. Set value something like "save video in photo library"
2) code
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")
}
}
}
Hope this helps.
GW
answered Jan 21 at 2:19
Giraff WombatGiraff Wombat
15
15
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54029217%2fcapturing-video-and-saving-it-via-avassetwriter%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown