Recording video to specific album

275 views Asked by At

I am creating an album in the users photo library, now I want to save a video there. I am saving the video to a file using:

let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let filePath = documentsURL.URLByAppendingPathComponent("video")

Now I want to take the video, and save it to an album. I've found lots on saving to the camera roll, but nothing on saving to an album. Can it be done, and if so, how?

1

There are 1 answers

1
Joe Pagliaro On

Assuming you have a PHAssetCollection specifying the album, you can use this PHAssetCollection extension:

extension PHAssetCollection {

    private func isCameraRollAlbum() -> Bool
    {
        let query = PHAssetCollection.fetchAssetCollections(with: .smartAlbum,
                                                            subtype: .smartAlbumUserLibrary,
                                                            options: nil)
        let result: PHAssetCollection? = query.firstObject

        return self == result
    }

    func save(videoURL: URL, completion: @escaping (URL?, String?) -> ()) {

        let isCameraRoll = isCameraRollAlbum()

        DispatchQueue.global(qos: .userInteractive).asyncAfter(deadline: .now()) {

            PHPhotoLibrary.shared().performChanges({
                if let assetRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL) {
                    if isCameraRoll == false, let placeholder = assetRequest.placeholderForCreatedAsset {
                        let albumChangeRequest = PHAssetCollectionChangeRequest(for: self)
                        albumChangeRequest?.addAssets([placeholder] as NSArray)
                    }
                }
            }, completionHandler: { (success, error) in

                if success == false {
                    completion(nil, error?.localizedDescription)
                }
                else {
                    completion(videoURL, nil)
                }

            })
        }
    }
}

Remarks:

Method 'isCameraRollAlbum' was defined because it was found that the use of placeholders for the whole photo album doesn't work, and you only need to use

PHAssetChangeRequest.creationRequestForAssetFromVideo

to save a video to the whole photo library.

Using a background thread is not necessary.

Example usage, it is assumed a video named 'Video.mov' is in the Documents directory of the app. This will save it to the 'Camera Roll' album but a PHAssetCollection for any album can be specified:

    let docsurl = try! FileManager.default.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

    let videoURL = docsurl.appendingPathComponent("Video.mov")

    let fetchResult = PHAssetCollection.fetchAssetCollections(with:.smartAlbum,subtype:.smartAlbumUserLibrary,options: nil)

    if let allMediaAlbum = fetchResult.firstObject {

        allMediaAlbum.save(videoURL: videoURL) { (url, message) in
            print("message = \(String(describing: message))")
        }
    }

For example, you can use this extension to obtain the PHAssetCollection for an album with a given name 'title':

class func getAlbum(title: String, completionHandler: @escaping (PHAssetCollection?) -> ()) {

    DispatchQueue.global(qos: .userInteractive).asyncAfter(deadline: .now()) {
        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "title = %@", title)
        let collections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)

        if let album = collections.firstObject {
            completionHandler(album)
        } else {
            completionHandler(nil)
        }

    }

}

Example usage, saving video 'Video.mov' to album named 'My Umbrella':

    let docsurl = try! FileManager.default.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

    let albumName = "My Umbrella"

    let videoURL = docsurl.appendingPathComponent("Video.mov")

    PHAssetCollection.getAlbum(title: albumName) { (album) in
        if let album = album {
            album.save(videoURL: videoURL, completion: { (url, error) in
                if let url = url {
                    print("Video '\(url.lastPathComponent) saved to '\(albumName)'")
                }
                else {
                    print("Error: \(String(describing: error))")
                }
            })
        }
    }

(Keep in mind that the photos library can have multiple albums by the same name.)