¿Puedo obtener el URI absoluto del video en el carrete y mutarlo desde mi aplicación?

8

Quiero realizar una operación en un video en el carrete de la cámara del iPhone, y necesito un URI absoluto ya que usaré ffmpeg de forma nativa dentro de mi aplicación.

¿Es posible operar en el video en su lugar? ¿o necesitaría copiar el video en un directorio tmp, operarlo y luego escribir de nuevo en el carrete de la cámara?

Hunterp
fuente

Respuestas:

7

He leído algunos documentos y tutoriales y respondo a continuación en función de esa investigación.

¿Es posible operar en el video en su lugar?

Sí (al copiarlo en el directorio temporal) y No (a la ubicación original donde realmente se almacena el video)

Echa un vistazo a la siguiente imagen y cita de documentos oficiales

ingrese la descripción de la imagen aquí

Con PhotoKit, puede buscar y almacenar en caché los activos para mostrar y reproducir, editar contenido de imagen y video o administrar colecciones de activos como álbumes, Momentos y Álbumes compartidos.

No tenemos acceso directo a la ubicación donde se almacena la imagen / video, en su lugar obtenemos datos sin procesar o representación usando PHAsset y los objetos de Activo son inmutables, por lo que no podemos realizar operaciones directamente en él. Necesitaríamos PHAssetChangeRequest para crear, eliminar, cambiar los metadatos o editar el contenido de un activo de Fotos.

¿necesitaría copiar el video en un directorio temporal, operarlo y luego escribir de nuevo en el carrete de la cámara?

Sí, ese es el camino a seguir.

Sahil Manchanda
fuente
Por supuesto, un usuario puede editar una imagen / video en su lugar, solo se le pedirá al usuario una alerta que le diga que confirme los cambios. Ver la clase PHAsset.
K4747Z
44
@ K4747Z De acuerdo. Pero con eso, me refería directamente a la ubicación original donde realmente se almacena el video.
Sahil Manchanda
Pero si tratamos de reemplazar el video editado, cuando se elimine el video no editado, pedirá permiso para eliminarlo photos, ¿verdad? ... lo que puede parecer extraño, ¿no crees que?
Nayan Dave
2
@NayanDave no necesitamos eliminar el video original. si nos fijamos en la clase PHAssetChangeRequest, mencionaron "editar el contenido del activo de Fotos" y este es nuestro caso: edite el video. por lo tanto, se le solicitará al usuario solo una vez.
Sahil Manchanda
1
Bam gracias !!
hunterp
3

Si ya buscó los activos y tiene el objeto PHFetchResult intente:

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

        }

O si está usando imagePicker predeterminado, podemos obtener la url de video tmp usando:

 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
fuente
0

Implemento algo como esto en mi proyecto, espero que te ayude.

Muestro todos los elementos en la vista de colección y realizo acciones en la selección, también puede obtener la URL del video seleccionado

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

}

Espero que funcione para ti ... :)

Shivam Parmar
fuente