当试图从PHAsset获取AVAssetExportSession的输出时,获得空结果

时间:2021-09-12 23:54:00

I'm attempting to build a small toy iOS app that merges two video assets from the user's photos library. I've gotten to the point where I have merged the videos using an AVMutableComposition instance and now I need to export the composition. I am doing so with the following code:

我正在尝试构建一个小型的iOS玩具应用程序,将用户的照片库中的两个视频资产合并在一起。我已经到了使用AVMutableComposition实例合并视频的地步,现在我需要导出合成。我这样做的代码如下:

func saveEditedComposition(_ composition: AVMutableComposition) {
    let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let savePath = (documentDirectory as NSString).strings(byAppendingPaths: ["mergeVideo.mov"])[0]
    let url = NSURL(fileURLWithPath: savePath)

    // Set up exporter
    guard let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else { return }
    exporter.outputURL = url as URL
    exporter.outputFileType = AVFileTypeQuickTimeMovie
    exporter.shouldOptimizeForNetworkUse = true

    // Perform the export
    exporter.exportAsynchronously(completionHandler: { () -> Void in
        // Upon completion of the export, 
        DispatchQueue.global().async {
            if exporter.status == .completed {
                let fetchResult = PHAsset.fetchAssets(withALAssetURLs: [exporter.outputURL!], options: nil))
                let phAsset = fetchResult.firstObject! // Crashes here, returning nil.
            }
        }
    })
}

The problem is, when the completionHandler is run, I am able to see that my exporter has completed without error (if exporter.status == .completed {), but when I try to access the asset at exporter.outputURL, it returns an empty PHFetchResult<PHAsset>. Can anyone see what I'm doing wrong here?

问题是,在运行completionHandler时,我可以看到我的出口商已经完成了,没有错误(如果出口商)。状态== .completed{),但当我试图访问出口商处的资产时。outputURL返回一个空的PHFetchResult 。有人能看出我做错了什么吗?

1 个解决方案

#1


1  

You're exporting the video to the file system (the Documents directory), yet fetching from the camera roll/ALAssetsLibrary.

您将视频导出到文件系统(文档目录),但从摄像机卷/ALAssetsLibrary中获取。

It depends on what you need to do with the exported file. If it needs to be in the ALAssetsLibrary, you can use

这取决于您需要对导出文件做什么。如果它需要在阿拉斯加,你可以使用

ALAssetsLibrary().writeVideoAtPath(toSavedPhotosAlbum: exporter.outputURL!) { alAssetURL, error in      
}

However ALAssetsLibrary is now deprecated and you are supposed to use PHPhotoLibrary. I don't know the Photos framework, but I think it works like this:

然而,ALAssetsLibrary现在已被废弃,您应该使用PHPhotoLibrary。我不知道照片框架,但我认为它是这样的:

var placeHolder: PHObjectPlaceholder?

PHPhotoLibrary.shared().performChanges({
    let changeRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: exporter.outputURL!)
    if let changeRequest = changeRequest {
        // maybe set date, location & favouriteness here?
        placeHolder = changeRequest.placeholderForCreatedAsset
    }
}) { success, error in
    placeHolder?.localIdentifier    // should identify asset from now on?
}

If you don't need the video to live in the camera roll, then you can work directly with the file in exporter.outputURL!.

如果您不需要视频在相机卷中生存,那么您可以直接使用exporter.outputURL文件。

#1


1  

You're exporting the video to the file system (the Documents directory), yet fetching from the camera roll/ALAssetsLibrary.

您将视频导出到文件系统(文档目录),但从摄像机卷/ALAssetsLibrary中获取。

It depends on what you need to do with the exported file. If it needs to be in the ALAssetsLibrary, you can use

这取决于您需要对导出文件做什么。如果它需要在阿拉斯加,你可以使用

ALAssetsLibrary().writeVideoAtPath(toSavedPhotosAlbum: exporter.outputURL!) { alAssetURL, error in      
}

However ALAssetsLibrary is now deprecated and you are supposed to use PHPhotoLibrary. I don't know the Photos framework, but I think it works like this:

然而,ALAssetsLibrary现在已被废弃,您应该使用PHPhotoLibrary。我不知道照片框架,但我认为它是这样的:

var placeHolder: PHObjectPlaceholder?

PHPhotoLibrary.shared().performChanges({
    let changeRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: exporter.outputURL!)
    if let changeRequest = changeRequest {
        // maybe set date, location & favouriteness here?
        placeHolder = changeRequest.placeholderForCreatedAsset
    }
}) { success, error in
    placeHolder?.localIdentifier    // should identify asset from now on?
}

If you don't need the video to live in the camera roll, then you can work directly with the file in exporter.outputURL!.

如果您不需要视频在相机卷中生存,那么您可以直接使用exporter.outputURL文件。