2017-06-29 98 views
0

我嘗試添加/與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)"}} 

回答

1

我發現我錯了。爲了與MediaType修改PHAsset的元數據MediaType.video你可以用下面的代碼片段,其中selfPHAsset

首先,你需要創建一個PHContentEditingOutput你可以做到這一點,要求從PHContentEditingInputPHAsset要修改。當更改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變量設置爲.currentPHImageManager - 方法.requestAVAsset(forVideo:,options:,resultHandler:)視頻。它被設置爲變量的默認值,但如果將其更改爲.original,則將從該方法獲取未修改的視頻。