修改元数据失败
我尝试添加/与mediaType == .video
修改从PHAsset
元数据,我发现了一些问题,指的一个类似的问题:修改元数据失败
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)"}}
我发现我错了。为了与MediaType
修改PHAsset
的元数据MediaType.video
你可以用下面的代码片段,其中self
是PHAsset
:
首先,你需要创建一个PHContentEditingOutput
你可以做到这一点,要求从PHContentEditingInput
的PHAsset
要修改。当更改PHAsset
时,还必须设置的值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)
}
})
}
考虑,如果你不要删除AVMetadataItem
与您想要添加的标识符相同的标识符,AVAssetExportSession
将为AVAsset
设置多个具有相同标识符的项目。
注:
现在,当您访问过你必须通过一个PHVideoRequestOptions
-object与.version
变量设置为.current
的PHImageManager
- 方法.requestAVAsset(forVideo:,options:,resultHandler:)
视频。它被设置为变量的默认值,但如果将其更改为.original
,则将从该方法获取未修改的视频。