Ios 使用mediaType视频修改PHAsset中的元数据失败
我尝试使用Ios 使用mediaType视频修改PHAsset中的元数据失败,ios,swift,avassetexportsession,avasset,photokit,Ios,Swift,Avassetexportsession,Avasset,Photokit,我尝试使用mediaType==从PHAsset添加/修改元数据。视频我发现了一些与类似问题相关的问题: 关于这些问题的答案,我构建了以下片段,它是PHAsset的扩展: let options = PHVideoRequestOptions() options.version = .original PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {
mediaType==从PHAsset
添加/修改元数据。视频我发现了一些与类似问题相关的问题:
关于这些问题的答案,我构建了以下片段,它是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)"}}
我发现了我的错误。要使用MediaType
MediaType.video
修改phaset
的元数据,可以使用以下代码段,其中self
是phaset
:
首先,您需要创建一个PHContentEditingOutput
,您可以通过从要修改的PHAsset
请求一个PHContentEditingOutput
。更改相位集时
还必须设置PHContentEditingOutput
的.adjustmentData
值,否则.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))")
}
})
}
})
}
})
在上面的代码段中,修改PHContentEditingOutput
后,您将更改PHAsset
,在下面的代码段中,您将看到如何为用户评级设置元数据:
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)
}
})
}
请考虑,如果不删除与要添加的标识符相同的AVMetadataItem
,则AVAssetExportSession
将为AVAsset
设置具有相同标识符的多个项
注意:
当您现在通过PHImageManager
-方法.requestAVAsset(forVideo:,options:,resultandler:)
访问视频时,您必须传递一个PHVideoRequestOptions
-对象,其中.version
变量设置为.current
。它被设置为变量的默认值,但如果将其更改为.original
,则将从该方法获得未修改的视频