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;
}







0















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.










share|improve this question





























    0















    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.










    share|improve this question

























      0












      0








      0








      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.










      share|improve this question














      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 3 at 20:18









      Brody HigbyBrody Higby

      244




      244
























          1 Answer
          1






          active

          oldest

          votes


















          0














          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






          share|improve this answer
























            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            0














            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






            share|improve this answer




























              0














              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






              share|improve this answer


























                0












                0








                0







                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






                share|improve this answer













                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







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 21 at 2:19









                Giraff WombatGiraff Wombat

                15




                15
































                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Mossoró

                    Can't read property showImagePicker of undefined in react native iOS

                    Pushsharp Apns notification error: 'InvalidToken'