2017-06-29 5 views
0

Ich versuche, das Hinzufügen/Ändern die Metadaten von einem PHAsset mit mediaType == .video fand ich einige Fragen zu einem ähnlichen Problem beziehen:Ändern von Metadaten von PHAsset mit Medientyp Video nicht

How to change video metadata using AVAssetWriter?

Add custom metadata to video using AVFoundation

auf den Bezug Antworten in diesen Fragen Ich baue das folgende Schnipsel, das eine Erweiterung eines PHAsset ist:

Wenn ich diesen Schnipsel ausführen, die exportSession failed die folgenden Fehler hat:

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

Antwort

1

ich meinen Fehler gefunden. So ändern Sie können die Metadaten eines PHAsset mit dem MediaTypeMediaType.video Sie das folgende Snippet verwenden, wo self ist die PHAsset:

Zuerst eine PHContentEditingOutput erstellen müssen, können Sie das tun, mit einer PHContentEditingInput von der Aufforderung an die PHAsset Sie ändern möchten . Wenn Sie einen PHAsset ändern, müssen Sie auch den .adjustmentData Wert des PHContentEditingOutput setzen oder der .performChanges() Block wird fehlschlagen. wenn Sie

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) 
     } 
    }) 
} 

Betrachten, dass:

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))") 
         } 
        }) 
       } 
      }) 
     } 
    }) 

Mit dem Snippet oben, Sie ändern Snippet die PHAsset nach dem PHContentEditingOutput in der folgenden Modifizieren Sie werden sehen, wie die Metadaten für einen User-Rating festlegen Entfernen Sie nicht die AVMetadataItem mit dem gleichen Bezeichner wie den, den Sie hinzufügen möchten, der AVAssetExportSession wird mehrere Elemente mit demselben Bezeichner für die AVAsset festlegen.

HINWEIS:

Wenn Sie jetzt das Video durch die PHImageManager zugreifen -Methode .requestAVAsset(forVideo:,options:,resultHandler:) Sie haben eine PHVideoRequestOptions -Objekt mit dem .version Variable auf .current zu übergeben. Es wird als Standardwert der Variablen festgelegt, aber wenn Sie es in .original ändern, erhalten Sie das unveränderte Video von dieser Methode.

Verwandte Themen