Explorar el Código

缓冲缩略图

harry hace 3 años
padre
commit
d8a11e9f72

+ 78 - 0
BFRecordScreenKit/Classes/BFRecordItemModel.swift

@@ -132,4 +132,82 @@ public class BFRecordItemModel: NSObject {
             dealedDurationRanges.append(SplitRecordRange(isRecord: false, range: range, index: -1))
         }
     }
+    
+    /// 视频分解成帧
+    /// - parameter fps                          : 自定义帧数 每秒内取的帧数
+    /// - parameter firstImagesCount             : 获取首先N张连续视频帧后先返回给调用方使用作为缓冲
+    /// - parameter splitCompleteClosure    : 回调
+    func splitVideoFileUrlFps(fps: Double, firstImagesCount:Int = 0, splitCompleteClosure: @escaping ((Bool, [UIImage]) -> Void)) {
+        guard let localPath = localPath else {
+            return
+        }
+
+        var splitImages = [UIImage]()
+
+        var times = [NSValue]()
+
+        let urlAsset = AVURLAsset(url: URL(fileURLWithPath: localPath))
+        let start = 0
+        let end = Int(urlAsset.duration.seconds * Float64(fps))
+
+        for i in start...end {
+            let timeValue = NSValue(time: CMTimeMake(value: Int64(i * 1000), timescale: Int32(fps * 1000)))
+
+            times.append(timeValue)
+        }
+
+        let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
+        imgGenerator.requestedTimeToleranceBefore = CMTime.zero
+        imgGenerator.requestedTimeToleranceAfter = CMTime.zero
+        imgGenerator.appliesPreferredTrackTransform = true
+        let timesCount = times.count
+        var cocu = 0
+        // 获取每一帧的图片
+        imgGenerator.generateCGImagesAsynchronously(forTimes: times) { _, image, _, result, _ in
+            cocu += 1
+            switch result {
+            case AVAssetImageGenerator.Result.cancelled:
+                BFLog(1, message: "splitVideo: cancel")
+
+            case AVAssetImageGenerator.Result.failed:
+                BFLog(1, message: "splitVideo: failed")
+
+            case AVAssetImageGenerator.Result.succeeded:
+                let framImg = UIImage(cgImage: image!)
+                splitImages.append(framImg)
+    //            BFLog(1, message: "aaa: \(requestedTime.seconds) - \(actualTime.seconds)")
+            @unknown default:
+                break
+            }
+            
+            if cocu == firstImagesCount {
+                splitCompleteClosure(false, splitImages)
+            }
+            
+            if cocu == timesCount { // 最后一帧时 回调赋值
+                splitCompleteClosure(true, splitImages)
+                BFLog(1, message: "splitVideo: complete")
+            }
+        }
+    }
+
+    /// 视频分解成帧
+    /// - parameter fileUrl                 : 视频地址
+    /// - parameter fps                     : 自定义帧数 每秒内取的帧数
+    /// - parameter splitCompleteClosure    : 回调
+    func getThumbImageAtTime(urlAsset: AVURLAsset, time: CMTime) -> UIImage? {
+        let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
+        imgGenerator.requestedTimeToleranceBefore = CMTime.zero
+        imgGenerator.requestedTimeToleranceAfter = CMTime.zero
+
+        var cgImg = try? imgGenerator.copyCGImage(at: time, actualTime: nil)
+        if cgImg == nil {
+            imgGenerator.requestedTimeToleranceBefore = CMTime.positiveInfinity
+            imgGenerator.requestedTimeToleranceAfter = CMTime.positiveInfinity
+            cgImg = try? imgGenerator.copyCGImage(at: time, actualTime: nil)
+        }
+
+        return cgImg == nil ? nil : UIImage(cgImage: cgImg!)
+    }
+
 }

+ 13 - 10
BFRecordScreenKit/Classes/RecordScreen/View/BFVideoThumbProgressView.swift

@@ -16,6 +16,7 @@ class BFVideoThumbProgressView: UIView {
     var recordItem: BFRecordItemModel? {
         didSet {
             // 指针回归
+            BFLog(1, message: "new recorditem")
             progress = 0
             if recordItem?.mediaType == .VIDEO {
                 dealWithVideoThumb()
@@ -122,21 +123,23 @@ class BFVideoThumbProgressView: UIView {
             }
             
             let fps = Double(count) / dur
-            splitVideoFileUrlFps(urlAsset: videoAsset, fps: fps, firstImagesCount: Int(ceil(width/2.0/thumbImageWidth))) { [weak self] hadGetAll, images in
-                guard let sself = self, let recordItem = sself.recordItem else {
+            recordItem!.splitVideoFileUrlFps(fps: fps, firstImagesCount: Int(ceil(width/2.0/thumbImageWidth))) { [weak self, weak recordItem] hadGetAll, images in
+                guard let sself = self, let sitem = recordItem else {
                     return
                 }
-                BFLog(1, message: "获取缩略图:\(hadGetAll), \(Date().timeIntervalSince(date))")
-                recordItem.thumbImgs.removeAll()
-                recordItem.thumbImgs.append(contentsOf: images)
+
+                BFLog(1, message: "获取缩略图:\(hadGetAll), \(Date().timeIntervalSince(date)), \( sitem.localPath ?? "aa")")
+                sitem.thumbImgs.removeAll()
+                sitem.thumbImgs.append(contentsOf: images)
                 
                 // 不足数则补充足够帧数
-                while (hadGetAll && recordItem.thumbImgs.count < count && images.count > 0) {
-                    recordItem.thumbImgs.append(images.last!)
+                while (hadGetAll && sitem.thumbImgs.count < count && images.count > 0) {
+                    sitem.thumbImgs.append(images.last!)
                 }
-                
-                if recordItem.localPath?.contains(videoAsset.url.lastPathComponent) ?? false {
-                    sself.addThumbImages(images: recordItem.thumbImgs)
+                if sitem.localPath == sself.recordItem!.localPath {
+                    sself.addThumbImages(images: sitem.thumbImgs)
+                }else{
+                    BFLog(1, message: "thumbImgs.count:\(sitem.thumbImgs.count)")
                 }
             }
         }