Kann ich den absoluten URI des Videos auf der Kamerarolle abrufen und von meiner App aus mutieren?

8

Ich möchte einen Vorgang für ein Video in der iPhone-Kamerarolle ausführen und benötige einen absoluten URI, da ich ffmpeg nativ in meiner App verwenden werde.

Ist es möglich, das Video an Ort und Stelle zu bearbeiten? oder müsste ich das video in ein tmp-verzeichnis kopieren, bearbeiten und dann auf die kamerarolle zurückschreiben?

Hunterp
quelle

Antworten:

7

Ich habe einige Dokumente und Tutorials gelesen und unten auf der Grundlage dieser Forschung geantwortet.

Ist es möglich, das Video an Ort und Stelle zu bearbeiten?

Ja (durch Kopieren in das temporäre Verzeichnis) und Nein (an den ursprünglichen Speicherort, an dem das Video tatsächlich gespeichert ist)

Schauen Sie sich das folgende Bild an und zitieren Sie aus offiziellen Dokumenten

Geben Sie hier die Bildbeschreibung ein

Mit PhotoKit können Sie Assets für die Anzeige und Wiedergabe abrufen und zwischenspeichern , Bild- und Videoinhalte bearbeiten oder Sammlungen von Assets wie Alben, Momenten und freigegebenen Alben verwalten.

Wir haben keinen direkten Zugriff auf den Speicherort des Bilds / Videos, stattdessen erhalten wir Rohdaten oder Darstellungen mit PHAsset, und Asset-Objekte sind unveränderlich, sodass wir keine Operationen direkt daran ausführen können. Wir benötigen PHAssetChangeRequest , um den Inhalt eines Fotos-Assets zu erstellen, zu löschen, die Metadaten zu ändern oder den Inhalt zu bearbeiten.

Muss ich das Video in ein temporäres Verzeichnis kopieren, es bearbeiten und dann auf die Kamerarolle zurückschreiben?

Ja, das ist der richtige Weg.

Sahil Manchanda
quelle
Natürlich kann ein Benutzer ein Bild / Video an Ort und Stelle bearbeiten. Der Benutzer wird lediglich mit einer Warnung aufgefordert, die Änderungen zu bestätigen. Siehe die PHAsset-Klasse.
K4747Z
4
@ K4747Z Einverstanden. Aber damit meinte ich direkt den ursprünglichen Ort, an dem das Video tatsächlich gespeichert ist.
Sahil Manchanda
Aber wenn wir versuchen, das bearbeitete Video zu ersetzen, werden Sie beim Löschen des nicht bearbeiteten Videos um die Erlaubnis zum Löschen gebeten photos, oder? ...... was seltsam aussehen mag, finden Sie das nicht?
Nayan Dave
2
@NayanDave Wir müssen das Originalvideo nicht löschen. Wenn Sie sich die PHAssetChangeRequest-Klasse ansehen, haben sie "den Inhalt des Fotos-Assets bearbeiten" erwähnt. Dies ist unser Fall: Bearbeiten Sie das Video. Daher wird der Benutzer nur einmal dazu aufgefordert.
Sahil Manchanda
1
Bam danke !!
Hunterp
3

Wenn Sie die Assets bereits abgerufen haben und das PHFetchResult-Objekt verwenden, versuchen Sie Folgendes:

var video = PHAsset() // the video to be edited 

 if video.canPerform(.content) {  // check if the selected PHAsset can be edited

  video.requestContentEditingInput(with: nil, completionHandler: { editingInput, _ in

  let videoAsset = editingInput?.audiovisualAsset // get tracks and metadata of the video and start editing
  let videoURL = (videoAsset as? AVURLAsset)?.url // This might be nil so better use videoAsset

        /*
         Start editing your video here


        */

  guard let input = editingInput else { return }
  let output = PHContentEditingOutput(contentEditingInput: input)
  let outputURL = output.renderedContentURL // URL at which you write/export the edited video, it must be a .mov file
  let editedVideo = NSData()  // suppose your video fileName is editedVideo.mov, I used NSData since I don't know what final edited object will be.
  editedVideo.write(to: outputURL, atomically: false)

  PHPhotoLibrary.shared().performChanges({
  let changeRequest = PHAssetChangeRequest(for: video)
  changeRequest.contentEditingOutput = output
               })
            })

        }

Wenn Sie den Standard-imagePicker verwenden, können Sie die tmp-Video-URL mithilfe folgender Adresse abrufen:

 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

    let videoURL = info[UIImagePickerController.InfoKey.mediaURL] as! NSURL
    print(videoURL)  // file is already in tmp folder


     let video = info[UIImagePickerController.InfoKey.phAsset] as! PHAsset
        // implement the above code using this PHAsset 

   // your will still need to request photo library changes, and save the edited video and/or delete the older one

    }
K4747Z
quelle
0

Ich implementiere so etwas in meinem Projekt. Ich hoffe, es wird Ihnen helfen.

Ich zeige alle Elemente in der Sammlungsansicht und führe eine Aktion bei der Auswahl aus. Sie können auch die URL des ausgewählten Videos abrufen

func getVideoFromCameraRoll() {
    let options = PHFetchOptions()
    options.sortDescriptors = [ NSSortDescriptor(key: "creationDate", ascending: false) ]
    options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.video.rawValue)
    videos = PHAsset.fetchAssets(with: options)
    videoLibraryCV.reloadData()
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return videos.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
    let asset = videos!.object(at: indexPath.row)
    let width: CGFloat = 150
    let height: CGFloat = 150
    let size = CGSize(width:width, height:height)
    cell.layer.borderWidth = 0.5
    cell.layer.borderColor = UIColor.lightGray.cgColor
    PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: PHImageContentMode.aspectFit, options: nil)
    {   (image, userInfo) -> Void in

        let imageView = cell.viewWithTag(1) as! UIImageView
        imageView.image = image

        let labelView = cell.viewWithTag(2) as! UILabel
        labelView.text = String(format: "%02d:%02d",Int((asset.duration / 60)),Int(asset.duration) % 60)
    }
    return cell
}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
 let asset = photos!.object(at: indexPath.row)
 guard(asset.mediaType == PHAssetMediaType.Video)
 else {
  print("Not a valid video media type")
  return
 }

 PHCachingImageManager().requestAVAssetForVideo(asset, options: nil, resultHandler: {
  (asset: AVAsset ? , audioMix : AVAudioMix ? , info : [NSObject: AnyObject] ? ) in
  let asset = asset as!AVURLAsset
  print(asset.URL) // Here is video URL
 })

}

Ich hoffe es wird für dich funktionieren ... :)

Shivam Parmar
quelle