BFVideoThumbImageFetchHelper.swift 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. //
  2. // BFVideoThumbImageFetchHelper.swift
  3. // BFRecordScreenKit
  4. //
  5. // Created by 胡志强 on 2021/12/3.
  6. //
  7. import AVFoundation
  8. import BFCommonKit
  9. import Foundation
  10. /// 视频分解成帧
  11. /// - parameter fileUrl : 视频地址
  12. /// - parameter fps : 自定义帧数 每秒内取的帧数
  13. /// - parameter firstImagesCount : 获取首先N张连续视频帧后先返回给调用方使用作为缓冲
  14. /// - parameter splitCompleteClosure : 回调
  15. func splitVideoFileUrlFps(urlAsset: AVURLAsset, fps: Double, firstImagesCount:Int = 0, splitCompleteClosure: @escaping ((Bool, [UIImage]) -> Void)) {
  16. var splitImages = [UIImage]()
  17. var times = [NSValue]()
  18. let start = 0
  19. let end = Int(urlAsset.duration.seconds * Float64(fps))
  20. for i in start...end {
  21. let timeValue = NSValue(time: CMTimeMake(value: Int64(i * 1000), timescale: Int32(fps * 1000)))
  22. times.append(timeValue)
  23. }
  24. let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
  25. imgGenerator.requestedTimeToleranceBefore = CMTime.zero
  26. imgGenerator.requestedTimeToleranceAfter = CMTime.zero
  27. imgGenerator.appliesPreferredTrackTransform = true
  28. let timesCount = times.count
  29. var cocu = 0
  30. // 获取每一帧的图片
  31. imgGenerator.generateCGImagesAsynchronously(forTimes: times) { _, image, _, result, _ in
  32. cocu += 1
  33. switch result {
  34. case AVAssetImageGenerator.Result.cancelled:
  35. BFLog(1, message: "splitVideo: cancel")
  36. case AVAssetImageGenerator.Result.failed:
  37. BFLog(1, message: "splitVideo: failed")
  38. case AVAssetImageGenerator.Result.succeeded:
  39. let framImg = UIImage(cgImage: image!)
  40. splitImages.append(framImg)
  41. // BFLog(1, message: "aaa: \(requestedTime.seconds) - \(actualTime.seconds)")
  42. @unknown default:
  43. break
  44. }
  45. if cocu == firstImagesCount {
  46. splitCompleteClosure(false, splitImages)
  47. }
  48. if cocu == timesCount { // 最后一帧时 回调赋值
  49. splitCompleteClosure(true, splitImages)
  50. BFLog(1, message: "splitVideo: complete")
  51. }
  52. }
  53. }
  54. /// 视频分解成帧
  55. /// - parameter fileUrl : 视频地址
  56. /// - parameter fps : 自定义帧数 每秒内取的帧数
  57. /// - parameter splitCompleteClosure : 回调
  58. func getThumbImageAtTime(urlAsset: AVURLAsset, time: CMTime) -> UIImage? {
  59. let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
  60. imgGenerator.requestedTimeToleranceBefore = CMTime.zero
  61. imgGenerator.requestedTimeToleranceAfter = CMTime.zero
  62. var cgImg = try? imgGenerator.copyCGImage(at: time, actualTime: nil)
  63. if cgImg == nil {
  64. imgGenerator.requestedTimeToleranceBefore = CMTime.positiveInfinity
  65. imgGenerator.requestedTimeToleranceAfter = CMTime.positiveInfinity
  66. cgImg = try? imgGenerator.copyCGImage(at: time, actualTime: nil)
  67. }
  68. return cgImg == nil ? nil : UIImage(cgImage: cgImg!)
  69. }