Bladeren bron

add image record

wenweiwei 3 jaren geleden
bovenliggende
commit
5f33ac499f

+ 159 - 53
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenController.swift

@@ -28,12 +28,12 @@ public class BFRecordScreenController: BFBaseViewController {
     // MARK: - 录制参数
 
     public var assets = [PHAsset]()
-
     var currItemModelIndex = 0
     public var itemModels = [BFRecordItemModel]()
     var showSubtitleIndex = 0
     //    var shouldPlayRecordIndex:Int = -1          // 当前应该播放的录音资源序号
     var currentPlayRecordIndex: Int = -1 // >= 0 :当前正在播放的录音资源序号; -3: 刚录音完,不需要播放录音; -1:初始化阶段
+    public var displayLink: CADisplayLink? // 图片素材播放控制
     var isRecording = false { // 是否正在录音
         didSet {
             withDrawBtn.isHidden = isRecording
@@ -396,7 +396,7 @@ public class BFRecordScreenController: BFBaseViewController {
         // add by ak 取 nsl token
         BFRecordScreenViewModel.getNlsAccessToken { [weak self] token, appkey in
             BFLog(message: "nls appkey is \(appkey), token is \(token)")
-            self?.speechTranscriberUtil = PQSpeechTranscriberUtil(token, appid: appkey)
+//            self?.speechTranscriberUtil = PQSpeechTranscriberUtil(token, appid: appkey)
         }
 
         view.backgroundColor = .black
@@ -699,9 +699,6 @@ public class BFRecordScreenController: BFBaseViewController {
 
 //        movie?.startProcessing()
 //        assetPlayer?.volume = 0
-
-        assetPlayer?.play()
-
         DispatchQueue.global().async { [weak self] in
             guard let sself = self else {
                 return
@@ -710,6 +707,13 @@ public class BFRecordScreenController: BFBaseViewController {
             sself.speechTranscriberUtil?.startTranscriber()
             sself.speechTranscriberUtil?.currItemModelIndex = Int32(sself.currItemModelIndex)
         }
+        if itemModels[currItemModelIndex].mediaType == .VIDEO {
+            assetPlayer?.play()
+        } else {
+            recorderManager.audioRecorder?.recorderProgross = { [weak self] progress in
+                self?.imageRecordProgress(progress: progress)
+            }
+        }
     }
 
     @objc func endRecord() {
@@ -905,7 +909,7 @@ public class BFRecordScreenController: BFBaseViewController {
 
     // MARK: - 音视频处理
 
-    func playRecord(at currentT: CMTime) {
+    func playRecord(at currentT: CMTime, periodicTimeObserver: @escaping (_ time: CMTime, _ currentItem: AVPlayerItem) -> Void, didPlayToEndTime: @escaping (_ currentT: CMTime, _ currentItem: AVPlayerItem) -> Void,playFailut: @escaping () -> Void) {
         if currentPlayRecordIndex == -3 { // 刚录音完,不需要播放
             return
         }
@@ -943,16 +947,22 @@ public class BFRecordScreenController: BFBaseViewController {
             NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: newItem, queue: .main) { [weak self] _ in
                 self?.hadPrepareToPlayRecord = false
                 self?.currentPlayRecordIndex = -1
+                didPlayToEndTime(currentT, newItem)
             }
+           _ = recordPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 100), queue: DispatchQueue.global()) { [weak self] time in
+                periodicTimeObserver(time, newItem)
+            } as? NSKeyValueObservation
         }
         if recordPlayer?.currentItem?.duration.timescale == 0 {
             BFLog(1, message: "时间timescale  == 0")
+            playFailut()
+            return
         }
         synced(currentPlayRecordIndex) { [weak self] in
             guard let self = self else {
                 return
             }
-            BFLog(1, message: "判断是否开始录音播放** hadPrepareToPlayRecord:\(hadPrepareToPlayRecord), currentPlayRecordIndex:\(currentPlayRecordIndex), isNormalPlaying :\(self.isNormalPlaying)")
+            BFLog(1, message: "判断是否开始录音播放** hadPrepareToPlayRecord:\(hadPrepareToPlayRecord), currentPlayRecordIndex:\(currentPlayRecordIndex), isNormalPlaying :\(self.isNormalPlaying),\(recordPlayer?.currentItem?.duration.timescale),\(CMTimeGetSeconds(currentT) >= recordedAudio.startTime),\(CMTimeGetSeconds(currentT) <= recordedAudio.endTime - 0.2)")
 
             if !hadPrepareToPlayRecord,
                recordPlayer?.currentItem?.duration.timescale != 0,
@@ -999,17 +1009,21 @@ public class BFRecordScreenController: BFBaseViewController {
     func play() {
         BFLog(1, message: "开始播放 \(currentAssetProgress.seconds)")
         isNormalPlaying = true
-//        assetPlayer?.volume = 0.2
-        movie?.startProcessing()
-        if isEndPlay {
-            isEndPlay = false
-            assetPlayer?.seek(to: CMTime.zero)
-            progressThumV.progress = 0
-            currentPlayRecordIndex = -1
-            recordBtn.isHidden = false
+        if itemModels[currItemModelIndex].mediaType == .VIDEO {
+            // assetPlayer?.volume = 0.2
+            movie?.startProcessing()
+            if isEndPlay {
+                isEndPlay = false
+                assetPlayer?.seek(to: CMTime.zero)
+                progressThumV.progress = 0
+                currentPlayRecordIndex = -1
+                recordBtn.isHidden = false
+            }
+            assetPlayer?.play()
+        } else {
+            // 处理图片音频播放
+            imageRecordPlay()
         }
-
-        assetPlayer?.play()
     }
 
     func pause() {
@@ -1084,25 +1098,18 @@ public class BFRecordScreenController: BFBaseViewController {
             assetPlayer = AVPlayer(playerItem: item)
             assetPlayer?.volume = 0
             avplayerTimeObserver = assetPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 100), queue: DispatchQueue.global()) { [weak self] time in
-                //    进度监控
-                self?.currentAssetProgress = CMTime(seconds: time.seconds, preferredTimescale: 1000)
-                BFLog(1, message: "curr:\(CMTimeGetSeconds(self?.currentAssetProgress ?? .zero))")
-                if CMTimeGetSeconds(item?.duration ?? CMTime.zero) > 0 {
-                    DispatchQueue.main.async { [weak self] in
-                        self?.progreddL.text = String(format: "%@", CMTimeGetSeconds(time).formatDurationToHMS())
-                        let su = !(self?.isDragingProgressSlder ?? false) || (self?.isRecording ?? false && self?.isNormalPlaying ?? false)
-                        if su {
-                            self?.progressThumV.progress = time.seconds
-                        }
-                        self?.updateSubtitle(time: time)
-                    }
-                }
-
+                // 进度监控
+                self?.periodicTimeObserver(item: item, time: time)
                 if self?.isNormalPlaying ?? false {
                     // 播放对应的录音音频
-                    self?.playRecord(at: time)
+                    self?.playRecord(at: time, periodicTimeObserver: { currentT, currentItem in
+                        BFLog(message: "播放一段进度:\(currentT),\(currentItem)")
+                    }, didPlayToEndTime: { startT, currentItem in
+                        BFLog(message: "播放一段结束:\(startT),\(currentItem)")
+                    }, playFailut: {
+                        
+                    })
                 }
-
             } as? NSKeyValueObservation
         }
 
@@ -1120,6 +1127,24 @@ public class BFRecordScreenController: BFBaseViewController {
         }
     }
 
+    /// 音视频播放进度-视频跟图片单独处理
+    /// - Parameter CMTime: <#CMTime description#>
+    func periodicTimeObserver(item: AVPlayerItem?, time: CMTime) {
+        // 进度监控
+        currentAssetProgress = CMTime(seconds: time.seconds, preferredTimescale: 1000)
+        BFLog(1, message: "curr:\(CMTimeGetSeconds(currentAssetProgress))")
+        if CMTimeGetSeconds(item?.duration ?? CMTime.zero) > 0 {
+            DispatchQueue.main.async { [weak self] in
+                self?.progreddL.text = String(format: "%@", CMTimeGetSeconds(time).formatDurationToHMS())
+                let su = !(self?.isDragingProgressSlder ?? false) || (self?.isRecording ?? false && self?.isNormalPlaying ?? false)
+                if su {
+                    self?.progressThumV.progress = time.seconds
+                }
+                self?.updateSubtitle(time: time)
+            }
+        }
+    }
+
     func cleanMovieTarget() {
         movie?.cancelProcessing()
         movie?.targets().forEach { target in
@@ -1135,13 +1160,19 @@ public class BFRecordScreenController: BFBaseViewController {
     // MARK: - 录音对应图像绘制
 
     func changeProgress(progress: Float) {
-        if let duration = assetPlayer?.currentItem?.duration {
-            currentAssetProgress = CMTime(value: CMTimeValue(progress * Float(CMTimeGetSeconds(duration)) * 1000), timescale: 1000)
-            DispatchQueue.main.async { [weak self] in
-                self!.progreddL.text = String(format: "%@", CMTimeGetSeconds(self!.currentAssetProgress).formatDurationToHMS())
+        if itemModels[currItemModelIndex].mediaType == .VIDEO {
+            if let duration = assetPlayer?.currentItem?.duration {
+                currentAssetProgress = CMTime(value: CMTimeValue(progress * Float(CMTimeGetSeconds(duration)) * 1000), timescale: 1000)
+                DispatchQueue.main.async { [weak self] in
+                    self!.progreddL.text = String(format: "%@", CMTimeGetSeconds(self!.currentAssetProgress).formatDurationToHMS())
+                }
+                assetPlayer!.seek(to: currentAssetProgress, toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000)) { _ in
+                }
             }
-
-            assetPlayer!.seek(to: currentAssetProgress, toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000)) { _ in
+        } else {
+            if itemModels[currItemModelIndex].materialDuraion > 0 {
+                currentAssetProgress = CMTime(value: CMTimeValue(progress * Float(itemModels[currItemModelIndex].materialDuraion) * 1000), timescale: 1000)
+                BFLog(message: "progress = \(progress),currentAssetProgress = \(currentAssetProgress)")
             }
         }
     }
@@ -1154,16 +1185,21 @@ public class BFRecordScreenController: BFBaseViewController {
             sself.progressThumV.progessIndicateBackV.subviews.forEach { vv in
                 vv.removeFromSuperview()
             }
-
             let totalDur = sself.itemModels[sself.currItemModelIndex].materialDuraion
-            if totalDur > 0, sself.itemModels[sself.currItemModelIndex].voiceStickers.count > 0 {
-                let width = sself.progressThumV.progessIndicateBackV.width
-                let height = sself.progressThumV.progessIndicateBackV.height
-                sself.itemModels[sself.currItemModelIndex].voiceStickers.forEach { model in
-                    let lineV = UIView(frame: CGRect(x: model.startTime * Double(width) / totalDur, y: 0, width: (model.endTime - model.startTime) * Double(width) / totalDur, height: Double(height)))
-                    lineV.backgroundColor = ThemeStyleColor
-                    sself.progressThumV.progessIndicateBackV.addSubview(lineV)
+            let height = sself.progressThumV.progessIndicateBackV.height
+            if sself.itemModels[sself.currItemModelIndex].mediaType == .VIDEO {
+                if totalDur > 0, sself.itemModels[sself.currItemModelIndex].voiceStickers.count > 0 {
+                    let width = sself.progressThumV.progessIndicateBackV.width
+                    sself.itemModels[sself.currItemModelIndex].voiceStickers.forEach { model in
+                        let lineV = UIView(frame: CGRect(x: model.startTime * Double(width) / totalDur, y: 0, width: (model.endTime - model.startTime) * Double(width) / totalDur, height: Double(height)))
+                        lineV.backgroundColor = ThemeStyleColor
+                        sself.progressThumV.progessIndicateBackV.addSubview(lineV)
+                    }
                 }
+            } else {
+                let lineV = UIView(frame: CGRect(x: 0, y: 0, width: totalDur * sself.progressThumV.thumbImageWidth / 2, height: Double(height)))
+                lineV.backgroundColor = ThemeStyleColor
+                sself.progressThumV.progessIndicateBackV.addSubview(lineV)
             }
         }
     }
@@ -1219,9 +1255,9 @@ extension BFRecordScreenController: PQSpeechTranscriberUtilDelegate {
     }
 }
 
-// MARK: - Delegate
+// MARK: - UICollectionViewDelegate
 
-/// Delegate
+/// UICollectionViewDelegate
 extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate {
     public func collectionView(_: UICollectionView, numberOfItemsInSection _: Int) -> Int {
         return itemModels.count
@@ -1248,8 +1284,12 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
                 self?.setVideoPlay(item: recordItem.playItem, imageView: cell?.playView)
             }
         }
-        cell.btnClickHandle = { [weak self] sender, _ in
-            self?.playVideo(btn: sender)
+        cell.btnClickHandle = { [weak self] sender, tempItem in
+            if tempItem?.mediaType == .VIDEO {
+                self?.playVideo(btn: sender)
+            } else {
+                self?.imageRecordPlay()
+            }
         }
         cell.recordItem = recordItem
         return cell
@@ -1263,7 +1303,7 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
             // 暂停
             pause()
             // 暂停状态
-            let lastCell: BFVideoCoverViewCell? = collectionView.cellForItem(at: IndexPath(item: currItemModelIndex, section: 0)) as? BFVideoCoverViewCell
+            let lastCell: BFImageCoverViewCell? = collectionView.cellForItem(at: IndexPath(item: currItemModelIndex, section: 0)) as? BFImageCoverViewCell
             lastCell?.playBtn.isSelected = false
             // 更新当前page
             currItemModelIndex = page
@@ -1272,7 +1312,7 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
             progressThumV.recordItem = recordItem
             progressThumV.isHidden = false
             if recordItem.mediaType == .VIDEO {
-                let currCell: BFVideoCoverViewCell? = collectionView.cellForItem(at: IndexPath(item: currItemModelIndex, section: 0)) as? BFVideoCoverViewCell
+                let currCell: BFImageCoverViewCell? = collectionView.cellForItem(at: IndexPath(item: currItemModelIndex, section: 0)) as? BFImageCoverViewCell
                 setAudioPlay(item: recordItem.playItem)
                 setVideoPlay(item: recordItem.playItem, imageView: currCell?.playView)
             }
@@ -1289,3 +1329,69 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
         }
     }
 }
+
+// MARK: - 处理图片素材
+
+/// 处理图片素材
+public extension BFRecordScreenController {
+    /// 处理图片音频的播放
+    func imageRecordPlay() {
+        if itemModels[currItemModelIndex].mediaType == .IMAGE {
+            isNormalPlaying = true
+            playRecord(at: currentAssetProgress, periodicTimeObserver: { [weak self] currentT, currentItem in
+                BFLog(message: "播放一段进度:\(currentT),\(currentItem)")
+                self?.imageRecordProgress(progress:CMTimeGetSeconds(currentT))
+            }, didPlayToEndTime: { [weak self] startT, currentItem in
+                BFLog(message: "播放一段结束:\(startT),\(currentItem)")
+                self?.imageRecordPlay()
+            }) {[weak self]  in
+                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
+                    self?.imageRecordPlay()
+                }
+            }
+        }
+    }
+
+    /// 处理图片素材录音
+    func imageRecordProgress(progress: Float64) {
+        BFLog(message: "图片录音进度:\(progress)")
+        if itemModels[currItemModelIndex].mediaType == .IMAGE {
+            currentAssetProgress = CMTime(seconds: progress, preferredTimescale: 1000)
+            DispatchQueue.main.async { [weak self] in
+                self?.progreddL.text = String(format: "%@", progress.formatDurationToHMS())
+                self?.progressThumV.progress = progress
+                self?.updateSubtitle(time: CMTime(value: CMTimeValue(progress), timescale: 1))
+            }
+        }
+    }
+
+    // 开始计时
+    func startTimer() {
+        if displayLink == nil {
+            // 创建对象
+            displayLink = CADisplayLink(target: self, selector: #selector(displayLinkChange(_:)))
+            // 设置触发频率 这个周期可以通过frameInterval属性设置,CADisplayLink的selector每秒调用次数=60/frameInterval。比如当frameInterval设为2,每秒调用就变成30次
+            if #available(iOS 10.0, *) {
+                displayLink?.preferredFramesPerSecond = 1
+            } else {
+                displayLink?.frameInterval = 1
+            }
+            // 加入循环
+            displayLink?.add(to: RunLoop.main, forMode: RunLoop.Mode.default)
+        }
+    }
+
+    // 停止计时
+    func stopTimer() {
+        if displayLink != nil {
+            displayLink?.isPaused = true
+            // 将定时器移除主循环
+            displayLink?.remove(from: RunLoop.main, forMode: RunLoop.Mode.default)
+            // 停止定时器
+            displayLink?.invalidate()
+            displayLink = nil
+        }
+    }
+
+    @objc internal func displayLinkChange(_: CADisplayLink) {}
+}

+ 24 - 3
BFRecordScreenKit/Classes/RecordScreen/View/BFImageCoverViewCell.swift

@@ -10,7 +10,17 @@ import GPUImage
 import UIKit
 
 open class BFImageCoverViewCell: UICollectionViewCell {
-    var btnClickHandle:((_ sender:UIButton,_ recordItem: BFRecordItemModel?) -> Void)?
+    var btnClickHandle: ((_ sender: UIButton, _ recordItem: BFRecordItemModel?) -> Void)?
+
+    public lazy var playBtn: UIButton = {
+        let btn = UIButton(type: .custom)
+        btn.setImage(imageInRecordScreenKit(by: "preview_play"), for: .normal)
+        let vv = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
+        btn.setImage(vv.graphicsGetImage(), for: .selected)
+        btn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
+        return btn
+    }()
+
     lazy var playView: GPUImageView = {
         let playView = GPUImageView(frame: bounds)
         return playView
@@ -31,15 +41,17 @@ open class BFImageCoverViewCell: UICollectionViewCell {
         return cell
     }
 
-    public override func prepareForReuse() {
+    override public func prepareForReuse() {
         super.prepareForReuse()
         filter.removeTarget(playView)
         picture.removeTarget(filter)
+        playBtn.isSelected = false
     }
 
     override public init(frame: CGRect) {
         super.init(frame: frame)
         contentView.addSubview(playView)
+        contentView.addSubview(playBtn)
     }
 
     public required init?(coder _: NSCoder) {
@@ -64,8 +76,17 @@ open class BFImageCoverViewCell: UICollectionViewCell {
         filter.addTarget(playView)
         picture.processImage()
     }
-    
+
     public func addLayout() {
         playView.frame = contentView.bounds
+        playBtn.frame = CGRect(origin: CGPoint.zero, size: CGSize(width: 100, height: 100))
+        playBtn.center = contentView.center
+    }
+
+    @objc func btnClick(sender: UIButton) {
+        sender.isSelected = !sender.isSelected
+        if btnClickHandle != nil {
+            btnClickHandle!(sender, recordItem)
+        }
     }
 }

+ 1 - 40
BFRecordScreenKit/Classes/RecordScreen/View/BFVideoCoverViewCell.swift

@@ -10,49 +10,10 @@ import UIKit
 import GPUImage
 
 open class BFVideoCoverViewCell: BFImageCoverViewCell {
-    public lazy var playBtn: UIButton = {
-        let btn = UIButton(type: .custom)
-        btn.setImage(imageInRecordScreenKit(by: "preview_play"), for: .normal)
-        let vv = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
-        btn.setImage(vv.graphicsGetImage(), for: .selected)
-        btn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
-        return btn
-    }()
-    
+
     @objc public class func gpuVideoViewCell(collectionView: UICollectionView, indexPath: IndexPath) -> BFVideoCoverViewCell {
         let cell: BFVideoCoverViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: BFVideoCoverViewCell.self), for: indexPath) as! BFVideoCoverViewCell
         return cell
     }
 
-    public override func prepareForReuse() {
-        super.prepareForReuse()
-        playBtn.isSelected = false
-    }
-
-    override public init(frame: CGRect) {
-        super.init(frame: frame)
-        contentView.addSubview(playBtn)
-    }
-    
-    public required init?(coder _: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-    
-    public override func addData() {
-        super.addData()
-
-    }
-
-    public override func addLayout() {
-        super.addLayout()
-        playBtn.frame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: 100, height: 100))
-        playBtn.center = contentView.center
-    }
-    
-    @objc func btnClick(sender: UIButton) {
-        sender.isSelected = !sender.isSelected
-        if btnClickHandle != nil {
-            btnClickHandle!(sender,recordItem)
-        }
-    }
 }

+ 60 - 17
BFRecordScreenKit/Classes/RecordScreen/View/BFVideoThumbProgressView.swift

@@ -15,10 +15,12 @@ import UIKit
 class BFVideoThumbProgressView: UIView {
     var recordItem: BFRecordItemModel? {
         didSet {
+            // 指针回归
+            progress = 0
             if recordItem?.mediaType == .VIDEO {
-                dealWithVideoThub()
+                dealWithVideoThumb()
             } else if recordItem?.mediaType == .IMAGE {
-                dealWithImageThub()
+                dealWithImageThumb()
             }
         }
     }
@@ -34,10 +36,7 @@ class BFVideoThumbProgressView: UIView {
 
     var progress: Double = 0 {
         didSet {
-            if let second = recordItem?.videoAsset?.duration.seconds, second > 0 {
-                let w = progressView.contentSize.width - width
-                progressView.contentOffset = CGPoint(x: progress * Double(w) / second, y: 0)
-            }
+            updateProgress(progress: progress)
         }
     }
 
@@ -90,7 +89,8 @@ class BFVideoThumbProgressView: UIView {
         }
     }
 
-    func dealWithVideoThub() {
+    /// 处理视频缩略图
+    func dealWithVideoThumb() {
         guard let videoAsset = recordItem?.videoAsset else {
             return
         }
@@ -98,19 +98,22 @@ class BFVideoThumbProgressView: UIView {
         if dur > 0 {
             let fps = Double(fetchThumbStrategy.frameNumberOfVideo(assetDuration: dur)) / dur
             splitVideoFileUrlFps(urlAsset: videoAsset, fps: fps) { [weak self] images in
-                self?.addThubImages(images: images)
+                self?.addThumbImages(images: images)
             }
         }
     }
 
-    func dealWithImageThub() {
+    /// 处理图片缩略图
+    func dealWithImageThumb() {
         guard let image = recordItem?.coverImg else {
             return
         }
-        addThubImages(images: Array(repeating: image, count: 3))
+        addThumbImages(images: Array(repeating: image, count: 10))
     }
 
-    func addThubImages(images: [UIImage]) {
+    /// 添加缩略图
+    /// - Parameter images: <#images description#>
+    func addThumbImages(images: [UIImage]) {
         if images.count > 0 {
             thumbImgs = images
             DispatchQueue.main.async { [weak self] in
@@ -147,33 +150,73 @@ class BFVideoThumbProgressView: UIView {
             }
         }
     }
+
+    /// 更新进度
+    /// - Parameter progress: <#progress description#>
+    func updateProgress(progress: Double = 0) {
+        if recordItem?.mediaType == .VIDEO {
+            if let second = recordItem?.videoAsset?.duration.seconds, second > 0 {
+                let w = progressView.contentSize.width - width
+                progressView.contentOffset = CGPoint(x: progress * Double(w) / second, y: 0)
+            }
+        } else if recordItem?.mediaType == .IMAGE {
+//            if (recordItem?.materialDuraion ?? 0) > progress {
+            progressView.setContentOffset(CGPoint(x: progress * thumbImageWidth / 2.0, y: 0), animated: true)
+//            }
+        }
+    }
 }
 
 extension BFVideoThumbProgressView: UIScrollViewDelegate {
     func scrollViewDidScroll(_ scrollView: UIScrollView) {
-        if isDrag {
-            let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
-            dragScrollProgressHandle?(false, Float(dur))
+        if recordItem?.mediaType == .VIDEO {
+            if isDrag {
+                let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
+                dragScrollProgressHandle?(false, Float(dur))
+            }
+        } else if recordItem?.mediaType == .IMAGE {
+            if scrollView.contentOffset.x > CGFloat(recordItem?.materialDuraion ?? 0) * thumbImageWidth / 2.0 {
+                scrollView.contentOffset = CGPoint(x: CGFloat(recordItem?.materialDuraion ?? 0) * thumbImageWidth / 2.0, y: 0)
+            }
+            if isDrag {
+                let dur = scrollView.contentOffset.x / thumbImageWidth / 2
+                dragScrollProgressHandle?(false, Float(dur))
+            }
         }
     }
 
     func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
         isDrag = true
-        let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
+        var dur: CGFloat = 0
+        if recordItem?.mediaType == .VIDEO {
+            dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
+        } else {
+            dur = scrollView.contentOffset.x / thumbImageWidth / 2
+        }
         dragStartHandle?()
         dragScrollProgressHandle?(true, Float(dur))
     }
 
     func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
         if !decelerate {
-            let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
+            var dur: CGFloat = 0
+            if recordItem?.mediaType == .VIDEO {
+                dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
+            } else {
+                dur = scrollView.contentOffset.x / thumbImageWidth / 2
+            }
             isDrag = false
             dragEndHandle?(Float(dur))
         }
     }
 
     func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
-        let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
+        var dur: CGFloat = 0
+        if recordItem?.mediaType == .VIDEO {
+            dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
+        } else {
+            dur = scrollView.contentOffset.x / thumbImageWidth / 2
+        }
         isDrag = false
         dragEndHandle?(Float(dur))
     }