使用mediaType视频修改PHAsset中的元数据失败

时间:2017-06-29 12:18:17

标签: ios swift avassetexportsession avasset photokit

我尝试使用PHAssetmediaType == .video添加/修改元数据我发现一些问题引用了类似的问题:

How to change video metadata using AVAssetWriter?

Add custom metadata to video using AVFoundation

关于这些问题中的答案,我构建了以下代码片段,它是PHAsset的扩展:

let options = PHVideoRequestOptions()
options.version = .original

PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {
    asset, audioMix, info in

    if asset != nil && asset!.isKind(of: AVURLAsset.self) {
        let urlAsset = asset as! AVURLAsset

        let start = CMTimeMakeWithSeconds(0.0, 1)
        let duration = asset!.duration                    


        var exportSession = AVAssetExportSession(asset: asset!, presetName: AVAssetExportPresetPassthrough)
        exportSession!.outputURL = urlAsset.url
        exportSession!.outputFileType = AVFileTypeAppleM4V
        exportSession!.timeRange = CMTimeRange(start: start, duration: duration)

        var modifiedMetadata = asset!.metadata

        let metadataItem = AVMutableMetadataItem()
        metadataItem.keySpace = AVMetadataKeySpaceQuickTimeUserData
        metadataItem.key = AVMetadataQuickTimeMetadataKeyRatingUser as NSString
        metadataItem.value = NSNumber(floatLiteral: Double(rating))

        modifiedMetadata.append(metadataItem)

        exportSession!.metadata = modifiedMetadata

        LogInfo("\(modifiedMetadata)")


        exportSession!.exportAsynchronously(completionHandler: {
            let status = exportSession?.status
            let success = status == AVAssetExportSessionStatus.completed
            if success {
                completion(true)
            } else {
                LogError("\(exportSession!.error!)")
                completion(false)
            }
        })
    }
})

执行此代码段时,exportSession失败并出现以下错误:

Error Domain=NSURLErrorDomain 
Code=-3000 "Cannot create file" 
UserInfo={NSLocalizedDescription=Cannot create file, 
NSUnderlyingError=0x1702439f0 
{Error Domain=NSOSStatusErrorDomain Code=-12124 "(null)"}}

1 个答案:

答案 0 :(得分:2)

我发现了自己的错误。要使用PHAsset MediaType修改MediaType.video的元数据,您可以使用以下代码段,其中selfPHAsset

首先,您需要创建一个PHContentEditingOutput,您可以从要修改的PHContentEditingInput请求PHAsset来执行此操作。更改PHAsset时,您还必须设置.adjustmentData的{​​{1}}值,否则PHContentEditingOutput阻止将失败。

.performChanges()

使用上面的代码段,您可以在修改以下代码段中的 self.requestContentEditingInput(with: options, completionHandler: { (contentEditingInput, _) -> Void in if contentEditingInput != nil { let adjustmentData = PHAdjustmentData(formatIdentifier: starRatingIdentifier, formatVersion: formatVersion, data: NSKeyedArchiver.archivedData(withRootObject: rating)) let contentEditingOutput = PHContentEditingOutput(contentEditingInput: contentEditingInput!) contentEditingOutput.adjustmentData = adjustmentData self.applyRatingToVideo(rating, contentEditingInput, contentEditingOutput, completion: { output in if output != nil { PHPhotoLibrary.shared().performChanged({ let request = PHAssetChangeRequest(for: self) request.contentEditingOutput = output }, completionHandler: { success, error in if !success { print("can't edit asset: \(String(describing: error))") } }) } }) } }) 后更改PHAsset,如何为用户评分设置元数据:

PHContentEditingOutput

请注意,如果您不删除与您要添加的标识符相同的private func applyRatingToVideo(_ rating: Int, input: PHContentEditingInput, output: PHContentEditingOutput, completion: @escaping (PHContentEditingOutput?) -> Void) { guard let avAsset = input.audiovisualAsset else { return } guard let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough) else { return } var mutableMetadata = exportSession.asset.metadata let metadataCopy = mutableMetadata for item in metadataCopy { if item.identifier == AVMetadataIdentifierQuickTimeMetadataRatingUser { mutableMetadata.remove(object: item) } } let metadataItem = AVMutableMetadataItem() metadataItem.identifier = AVMetadataIdentifierQuickTimeMetadataRatingUser metadataItem.keySpace = AVMetadataKeySpaceQuickTimeMetadata metadataItem.key = AVMetadataQuickTimeMetadataKeyRatingUser as NSString metadataItem.value = NSNumber(floatLiteral: Double(rating)) exportSession.outputURL = output.renderedContentURL mutableMetadata.append(metadataItem) exportSession.metadata = mutableMetadata exportSession.outputFileType = AVFileTypeQuickTimeMovie exportSession.shouldOptimizeForNetworkUse = true exportSession.exportAsynchronously(completionHandler: { if exportSession.status == .completed { completion(output) } else if exportSession.error != nil { completion(nil) } }) } AVMetadataItemAVAssetExportSession将为AVAsset设置多个具有相同标识符的项目。

注意:

现在,当您通过PHImageManager - 方法.requestAVAsset(forVideo:,options:,resultHandler:)访问视频时,您必须传递PHVideoRequestOptions - 对象,并将.version变量设置为.current 。它被设置为变量的默认值,但如果您将其更改为.original,您将从该方法获得未修改的视频。