Can I get absolute URI of video on camera roll and mutate it from my app?

I've read some docs and tutorials and answering below based on that research.

Is it possible to operate on the video in place?

Yes (By copying it to temp dir) and No (to the original location where the video is actually stored)

Take a look at the following image and quote from official docs

enter image description here

Using PhotoKit, you can fetch and cache assets for display and playback, edit image and video content or manage collections of assets such as albums, Moments, and Shared Albums.

We don't have direct access to the location where the image/video is stored instead we get raw data or representation using PHAsset and Asset objects are immutable so we can't perform operations directly on it. We would need PHAssetChangeRequest to create, delete, change the metadata for, or edit the content of a Photos asset.

would I need to copy the video to a temp dir, operate on it, and then write back to the camera roll?

Yep, that's the way to go.


If you already fetched the assets, and have the PHFetchResult object try:

var video = PHAsset() // the video to be edited 

 if video.canPerform(.content) {  // check if the selected PHAsset can be edited

  video.requestContentEditingInput(with: nil, completionHandler: { editingInput, _ in

  let videoAsset = editingInput?.audiovisualAsset // get tracks and metadata of the video and start editing
  let videoURL = (videoAsset as? AVURLAsset)?.url // This might be nil so better use videoAsset

        /*
         Start editing your video here


        */

  guard let input = editingInput else { return }
  let output = PHContentEditingOutput(contentEditingInput: input)
  let outputURL = output.renderedContentURL // URL at which you write/export the edited video, it must be a .mov file
  let editedVideo = NSData()  // suppose your video fileName is editedVideo.mov, I used NSData since I don't know what final edited object will be.
  editedVideo.write(to: outputURL, atomically: false)

  PHPhotoLibrary.shared().performChanges({
  let changeRequest = PHAssetChangeRequest(for: video)
  changeRequest.contentEditingOutput = output
               })
            })

        }

Or if you're using default imagePicker, we can get tmp video url using:

 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

    let videoURL = info[UIImagePickerController.InfoKey.mediaURL] as! NSURL
    print(videoURL)  // file is already in tmp folder


     let video = info[UIImagePickerController.InfoKey.phAsset] as! PHAsset
        // implement the above code using this PHAsset 

   // your will still need to request photo library changes, and save the edited video and/or delete the older one

    }