如何从 PHAsset 获取视频的缩略图?

How to get thumbnail for video from PHAsset?

我正在尝试使用从用户相机胶卷中提取的视频和照片缩略图填充 aa UICollectionView。我在数组 images 中以 PHAsset 的形式加载相机胶卷中的所有媒体,如此处声明:

var images = [PHAsset]()

if-then 循环检查 PHAsset 是图像还是视频。如果它是图像,它只是将它添加到 collection 视图。但是,我不确定如何将视频的缩略图添加到 collection 视图。感谢任何帮助。

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoLibraryCollectionViewCell", for: indexPath) as! PhotoLibraryCollectionViewCell
    let asset = images[indexPath.row]

    if asset.mediaType == PHAssetMediaType.image {
        let manager = PHImageManager.default()
        let option = PHImageRequestOptions()
        var thumbnail = UIImage()
        option.isSynchronous = true
        manager.requestImage(for: asset, targetSize: CGSize(width: 138, height: 138), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in
            thumbnail = result!
        })
        cell.imageView.image = thumbnail
    } else {
        // code to add the thumbnail of the video to the collection view
    }

    return cell
  }

编辑: 我尝试删除 if-then 方法,但 collection 视图根本不显示视频缩略图。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoLibraryCollectionViewCell", for: indexPath) as! PhotoLibraryCollectionViewCell

    let asset = images[indexPath.row]
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    var thumbnail = UIImage()
    option.isSynchronous = true
    option.isNetworkAccessAllowed = true
    manager.requestImage(for: asset, targetSize: CGSize(width: 138, height: 138), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in
        thumbnail = result!
    })
    cell.imageView.image = thumbnail

    return cell
}

如果您查看下面的 link,我的相机胶卷中显然有一段视频,但它没有显示在 collection 视图中: https://imgur.com/a/5GfDm

您可以尝试使用 PHCachingImageManager,如 Apple sample project

let cachingImageManager = PHCachingImageManager()

在加载项目调用之前的某处尝试加载缓存

func updateCache() {
    //Update the size here
    let size: CGSize = CGSize(width: 138, height: 138)

    cachingImageManager.startCachingImages(for: images, targetSize: size, contentMode: .aspectFit, options: nil)
}

然后加载图像和视频的缩略图会像这样

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoLibraryCollectionViewCell", for: indexPath) as! PhotoLibraryCollectionViewCell

    let asset = images[indexPath.row]

    let size = CGSize(width: 138, height: 138)

    let option = PHImageRequestOptions()
    option.isSynchronous = true

    cachingImageManager.requestImage(for: asset, targetSize: size, contentMode: .aspectFit, options: option) { image, info in
        cell.imageView.image = image
    }

    return cell
}

注意:从 PHAsset 加载图像而不缓存可能会导致内存问题

您可能需要创建另一个 PHCachingImageManager 以防图像数组中的项目发生变化

使用 PHAsset 时 requestImage(for:targetSize:contentMode:options:resultHandler:) 适用于照片和视频。

From Apple documentation:

You can use this method for both photo and video assets for a video asset, an image request provides a thumbnail image or poster frame.

所以只需删除 if 语句并调用请求两种类型的缩略图。

let manager = PHImageManager.default()
        let option = PHImageRequestOptions()
        var thumbnail = UIImage()
        option.isSynchronous = true
        manager.requestImage(for: asset, targetSize: CGSize(width: 138, height: 138), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in
            thumbnail = result!
        })
        cell.imageView.image = thumbnail

编辑: 确保允许网络访问

options.isNetworkAccessAllowed = true