Browse Source

修改摄像头预览逻辑

harry 3 năm trước cách đây
mục cha
commit
8d8b5dceba

+ 21 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/flip.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "flip@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/flip.imageset/flip@3x.png


+ 11 - 1
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenBaseManager.swift

@@ -8,6 +8,7 @@
 import Foundation
 import GPUImage
 import BFCommonKit
+import BFMediaKit
 
 
 class BFRecordScreenBaseManager : NSObject{
@@ -34,7 +35,8 @@ class BFRecordScreenBaseManager : NSObject{
     var recording = false
     // MARK: -
     func resetEnv(){
-        
+        dele?.currentAssetProgress = currentAssetProgress
+        progreddL?.text = CMTimeGetSeconds(currentAssetProgress).formatDurationToHMS()
     }
     
     func startRecord(){
@@ -57,6 +59,14 @@ class BFRecordScreenBaseManager : NSObject{
         
     }
     
+    func changeRecordMaterail(){
+        
+    }
+    
+    func deleteRecord(at: CMTime) {
+        
+    }
+    
     func clean(){
         GPUImageContext.sharedFramebufferCache().purgeAllUnassignedFramebuffers()
     }

+ 243 - 23
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenCameraManager.swift

@@ -47,6 +47,8 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
     //当前摄像的序号
     var currVideoIndex = 0
     
+    var currPlayTime : CMTime = .zero
+    
     fileprivate var timerr:Timer?
    
     var movieWrite : GPUImageMovieWriter?
@@ -54,12 +56,65 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
     lazy var camera : GPUImageStillCamera? = {
         let camera = GPUImageStillCamera(sessionPreset: AVCaptureSession.Preset.hd1920x1080.rawValue, cameraPosition: AVCaptureDevice.Position.back)
         camera?.outputImageOrientation = UIInterfaceOrientation.portrait
-//        camera?.addAudioInputsAndOutputs()
         camera?.delegate = self
         return camera
         
     }()
     
+    var avplayerTimeObserver: NSKeyValueObservation?
+    
+    lazy var avplayer : AVPlayer = {
+        let p = AVPlayer(playerItem: nil)
+        avplayerTimeObserver = p.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 100), queue: DispatchQueue.global(), using: {[weak self] currTime in
+            
+            guard let wself = self else { return }
+            
+            wself.currentAssetProgress = CMTime(seconds: (currTime + wself.currPlayTime).seconds, preferredTimescale: 1000)
+//            BFLog(1, message: "camera currTime: \(currTime.seconds)")
+            DispatchQueue.main.async {[weak self] in
+                guard let wself = self else { return }
+                
+                wself.locationTo(time: wself.currentAssetProgress)
+            }
+            
+        }) as? NSKeyValueObservation
+        
+        NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: p.currentItem, queue: .main) { [weak self] _ in
+            guard let wself = self else {
+                return
+            }
+            BFLog(1, message: "endPlay:\(wself.currentAssetProgress.seconds), 总时长:\(wself.recordItem?.materialDuraion.seconds)")
+    
+            // 如果离结束大于0.7s,代表还有下一段视频
+            if ((wself.recordItem?.materialDuraion ?? .zero) - wself.currentAssetProgress).seconds > 0.7 {
+                // 直接加33ms下一帧的时间去找视频播放,因为结束比实际时长要早一点点
+                wself.currentAssetProgress = wself.currentAssetProgress + CMTime(seconds: 0.033, preferredTimescale: 1000)
+                wself.play()
+            
+            }else{
+                // 播放到末尾了
+                wself.dele?.pause()
+            }
+        }
+        
+        return p
+    }()
+    
+    lazy var playerLayer : AVPlayerLayer = {
+        let layer = AVPlayerLayer(player: avplayer)
+        layer.frame = UIScreen.main.bounds
+        return layer
+    }()
+    
+// MARK: 重放
+    
+    deinit {
+        if avplayerTimeObserver != nil {
+            avplayer.removeTimeObserver(avplayerTimeObserver)
+            avplayerTimeObserver?.invalidate()
+        }
+        
+    }
     
     override func resetEnv(){
         guard let camera = camera else {
@@ -68,9 +123,24 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
         }
         cameraProgressV?.recordItem = recordItem
         cameraProgressV?.collectionV.reloadData()
-        cameraProgressV?.isHidden = true
-        currVideoIndex = 0
+        
+        initplayer()
 
+        if let count = recordItem?.voiceStickers.count, count > 0 {
+            currentAssetProgress = recordItem!.materialDuraion
+            currVideoIndex = count
+            cameraProgressV?.isHidden = false
+            progreddL?.isHidden = false
+            progreddL?.text = CMTimeGetSeconds(currentAssetProgress).formatDurationToHMS()
+            cameraProgressV?.collectionV.scrollRectToVisible(CGRect(x: (cameraProgressV?.collectionV.contentSize.width)! - 1, y: (cameraProgressV?.collectionV.contentSize.height)! - 1, width: 1, height: 1), animated: false)
+
+
+        }else {
+            currVideoIndex = 0
+            cameraProgressV?.isHidden = true
+            progreddL?.isHidden = true
+        }
+        
         camera.startCapture()
         initerlizeWriter()
 
@@ -86,6 +156,18 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
                 BFRecordScreenCameraManager.firstOpenCamera = false
             })
         }
+        
+        super.resetEnv()
+    }
+    
+    func initplayer(){
+        
+        guard let preView = playView else {
+            return
+        }
+                
+        preView.layer.addSublayer(playerLayer)
+        
     }
     
     override func startRecord(){
@@ -94,6 +176,7 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
             return
         }
         
+        playerLayer.removeFromSuperlayer()
 
         super.startRecord()
 
@@ -102,11 +185,10 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
         
         videoModel = PQEditVisionTrackMaterialsModel()
         videoModel.thumImgs = [UIImage]()
-        videoModel.timelineIn = currentAssetProgress.seconds
-        videoModel.timelineOut = currentAssetProgress.seconds
+        videoModel.timelineCMIn = currentAssetProgress
+        videoModel.timelineCMOut = currentAssetProgress
         currVideoIndex = recordItem?.videoStickers.count ?? 0
         
-        
         // 为了第一时间能更新collection view数据
         if !BFRecordScreenCameraManager.firstOpenCamera{
             recordItem?.videoStickers.append(videoModel)
@@ -122,12 +204,12 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
             }
             //MARK: 进度计时器
 
-            let currDur = CMTime(seconds: wself.videoModel.timelineIn + movieWrite.duration.seconds, preferredTimescale: 1000)
+            let currDur = wself.videoModel.timelineCMIn + movieWrite.duration
             wself.currentAssetProgress = currDur
-            wself.videoModel.timelineOut = currDur.seconds
+            wself.videoModel.timelineCMOut = currDur
             wself.recordProgressCallBack?(currDur)
             wself.updateUI(progress: currDur)
-            BFLog(1, message: "currTime: \(wself.currentAssetProgress.seconds)")
+//            BFLog(1, message: "currTime: \(wself.currentAssetProgress.seconds)")
         })
         RunLoop.current.add(timerr!, forMode: .common)
     }
@@ -137,7 +219,7 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
         
         timerr?.invalidate()
         timerr = nil
-        BFLog(1, message: " 拍摄时长 \(Date().timeIntervalSince(startTime))")
+//        BFLog(1, message: " 拍摄时长 \(Date().timeIntervalSince(startTime))")
         let su = BFRecordScreenCameraManager.firstOpenCamera
         movieWrite?.finishRecording(completionHandler: {[weak self] in
             guard let wself = self else { return }
@@ -146,19 +228,22 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
                 if !su {
                     if let finalPath = PQBridgeObject.p_setupFileRename(vpath), finalPath.count > 0 {
                         let dur = AVURLAsset(url: URL(fileURLWithPath: finalPath))
-                        wself.videoModel.timelineOut = wself.videoModel.timelineIn + dur.duration.seconds
-                        BFLog(1, message: "拍摄文件时长:\(wself.videoModel.timelineIn)~\(wself.videoModel.timelineOut),  \(dur.duration.seconds)")
+                        wself.videoModel.timelineCMOut = wself.videoModel.timelineCMIn + CMTime(seconds: dur.duration.seconds, preferredTimescale: 1000)
+                        BFLog(1, message: "拍摄文件时长:\(wself.videoModel.timelineCMIn.seconds)~\(wself.videoModel.timelineCMOut.seconds),  \(dur.duration.seconds)")
                         wself.videoModel.locationPath = finalPath
-                        wself.currentAssetProgress = CMTime(seconds: wself.videoModel.timelineOut, preferredTimescale: 1000)
+                        wself.currentAssetProgress = wself.videoModel.timelineCMOut
+                        wself.recordEndCallBack?(true, wself.videoModel)
+
                     }else{
                         // 录制失败后恢复原样
                         wself.revertLast()
                         cShowHUB(superView: nil, msg: "录制失败,未能生成文件")
+                        wself.recordEndCallBack?(false, nil)
+
                     }
                     DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                         wself.updateUI(progress:  wself.currentAssetProgress)
                     }
-                    wself.recordEndCallBack?(true, wself.videoModel)
 
                 }else{
                     wself.hasInitCallBack?()
@@ -172,22 +257,160 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
     
     // 录制失败 , 不足一秒时恢复上一次状态
     func revertLast(){
-        videoModel.timelineOut = videoModel.timelineIn
-        currentAssetProgress = CMTime(seconds: videoModel.timelineOut, preferredTimescale: 1000)
+        videoModel.timelineCMOut = videoModel.timelineCMIn
+        currentAssetProgress = videoModel.timelineCMOut
         recordItem?.thumbImgs.removeAll(where: { img in
             videoModel.thumImgs?.contains(img) ?? false
         })
+        DispatchQueue.main.async {[weak self] in
+            guard let wself = self else { return }
+            
+            wself.cameraProgressV?.collectionV.reloadData()
+        }
         videoModel.thumImgs?.removeAll()
+        recordItem?.videoStickers.removeLast()
         
-        cameraProgressV?.collectionV.reloadData()
     }
     
+    // 使用avplayer进行播放视频和音频
     override func play() {
+        guard let preView = playView else {
+            return
+        }
+        if playerLayer.superlayer == nil {
+            preView.layer.addSublayer(playerLayer)
+        }
+
         camera?.pauseCapture()
+        
+        // 100ms以内的重头开始播放
+        if (recordItem?.materialDuraion.seconds)! - currentAssetProgress.seconds < 0.1 {
+            currentAssetProgress = .zero
+            currPlayTime = .zero
+            locationTo(time: currentAssetProgress)
+
+        }
+        
+        if assetPlayer?.currentItem != nil {
+            assetPlayer?.play()
+            recordPlayer?.play()
+        }else{
+            
+        }
+        
+        // 播放视频
+        if let mod = recordItem?.videoStickers.first(where: { m in
+            CMTimeCompare(m.timelineCMIn, currentAssetProgress) <= 0 && CMTimeCompare(m.timelineCMOut, currentAssetProgress) > 0
+        }){
+            avplayer.replaceCurrentItem(with: AVPlayerItem(url: URL(fileURLWithPath: mod.locationPath)))
+            currPlayTime = mod.timelineCMIn
+
+            let tt = currentAssetProgress - currPlayTime
+            BFLog(1, message: "asset - tt: \(tt.seconds), curr:\(currentAssetProgress.seconds)")
+            avplayer.seek(to: tt, toleranceBefore: CMTime(seconds: 1, preferredTimescale: 1000), toleranceAfter: CMTime(seconds: 1, preferredTimescale: 1000)) { [weak avplayer] isFinished in
+                if isFinished {
+                    avplayer?.play()
+                }
+            }
+            
+            playRecordVoice(tt)
+        }
+    }
+    
+    func playRecordVoice(_ tt:CMTime){
+        // 播放音频
+        if let mod = recordItem?.voiceStickers.first(where: { m in
+            CMTimeCompare(m.startCMTime, currentAssetProgress) <= 0 && CMTimeCompare(m.endCMTime, currentAssetProgress) > 0
+        }){
+            recordPlayer?.replaceCurrentItem(with: AVPlayerItem(url: URL(fileURLWithPath: mod.wavFilePath)))
+            
+            BFLog(1, message: "record - tt: \(tt.seconds), curr:\(currentAssetProgress.seconds)")
+            recordPlayer?.seek(to: tt, toleranceBefore: CMTime(seconds: 1, preferredTimescale: 1000), toleranceAfter: CMTime(seconds: 1, preferredTimescale: 1000)) { [weak recordPlayer] isFinished in
+                if isFinished {
+                    recordPlayer?.play()
+                }
+            }
+        }
+    }
+    
+    
+    // 定位到某个时间点,相应进度条的UI更新
+    func locationTo(time:CMTime) {
+        var toTime = CMTime(seconds: time.seconds, preferredTimescale: 1000)
+        if CMTimeCompare(time, recordItem!.materialDuraion) > 0 {
+            toTime = recordItem!.materialDuraion
+            currentAssetProgress = toTime
+        }
+        progreddL?.text = CMTimeGetSeconds(currentAssetProgress).formatDurationToHMS()
+
+        cameraProgressV?.collectionV.contentOffset = CGPoint(x: currentAssetProgress.seconds * 70.0 / 5.0, y: 0)
+        
+    }
+    override func deleteRecord(at: CMTime) {
+        if let videoS = recordItem?.videoStickers.enumerated().first(where: { mod in
+            CMTimeCompare(mod.1.timelineCMIn, at) <= 0 && CMTimeCompare(mod.1.timelineCMOut, at) >= 0
+        }), let item = recordItem {
+            
+            item.thumbImgs.removeAll(where: { img in
+                videoS.1.thumImgs?.contains(img) ?? false
+            })
+            item.videoStickers.remove(at: videoS.0)
+            
+            let currDuration = videoS.1.timelineCMOut - videoS.1.timelineCMIn
+            item.materialDuraion = item.materialDuraion - currDuration
+            currentAssetProgress = videoS.1.timelineCMIn
+            
+            // 更新音频的时间点
+            for model in item.voiceStickers {
+                if CMTimeCompare(currentAssetProgress, model.startCMTime) < 0 {
+                    model.startCMTime = model.startCMTime - currDuration
+                    model.endCMTime = model.endCMTime - currDuration
+                    BFLog(1, message: "camera删除后更新voice time:\(model.startCMTime.seconds) ~ \(model.endCMTime.seconds)")
+                    item.titleStickers.forEach { tm in
+                        if tm.recordId == model.recordId {
+                            tm.timelineIn = tm.timelineIn - currDuration
+                            tm.timelineOut = tm.timelineOut - currDuration
+                        }
+                    }
+                }
+            }
+            // 更新录像的时间点
+            for model in item.videoStickers {
+                if CMTimeCompare(currentAssetProgress, model.timelineCMIn) < 0 {
+                    model.timelineCMIn =  model.timelineCMIn - currDuration
+                    model.timelineCMOut = model.timelineCMOut - currDuration
+                    BFLog(1, message: "camera删除后更新video time:\(model.timelineCMIn.seconds) ~ \(model.timelineCMOut.seconds)")
+
+                }
+            }
+        }
+    }
+
+    override func changeRecordMaterail(){
+        //
+        
+        if recordItem?.videoStickers.count ?? 0 == 0 {
+            currentAssetProgress = .zero
+            resetEnv()
+        } else {
+            cameraProgressV?.collectionV.reloadData()
+            cameraProgressV?.collectionV.contentOffset = CGPoint(x: currentAssetProgress.seconds * 70.0 / 5.0, y: 0)
+            progreddL?.text = CMTimeGetSeconds(currentAssetProgress).formatDurationToHMS()
+
+            cameraProgressV?.isHidden = false
+            
+            if currentAssetProgress == .zero {
+                // 按钮为删除
+            }
+        }
     }
     
     override func pause() {
-        camera?.resumeCameraCapture()
+        avplayer.pause()
+        recordPlayer?.pause()
+        if currentAssetProgress == recordItem?.materialDuraion {
+            camera?.resumeCameraCapture()
+        }
     }
     
     override func clean() {
@@ -206,10 +429,10 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
             if wself.recordItem?.thumbImgs.count ?? 0 > 0 {
                 wself.cameraProgressV?.updateCellWidth(index: wself.recordItem!.thumbImgs.count - 1, progress: progress)
             }
-            
         }
     }
     
+    // 添加新的缩略图
     func addNewThumb(){
         if let progressThumV = cameraProgressV {
 //            progressThumV.collectionV.reloadData()
@@ -217,10 +440,7 @@ class BFRecordScreenCameraManager : BFRecordScreenBaseManager{
         }
     }
     
-    func beginRecord(startTime:CMTime) {
-
-    }
-    
+    // 初始化 movieWrite
     func initerlizeWriter(){
         if FileManager.default.fileExists(atPath: vpath){
             try? FileManager.default.removeItem(atPath: vpath)

+ 90 - 60
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenController.swift

@@ -24,6 +24,9 @@ struct WithDrawModel {
     var deletedVoices: [(PQVoiceModel, Int)]?
     // add by ak 保存删除的字幕数据用于恢复
     var deletedTittles: [PQEditSubTitleModel]?
+    //
+    var deletedCameras: [PQEditVisionTrackMaterialsModel]?
+
 }
 
 public class BFRecordScreenController: BFBaseViewController {
@@ -62,6 +65,20 @@ public class BFRecordScreenController: BFBaseViewController {
             guard let wself = self else { return }
             wself.recordBtn.isEnabled = true
         }
+        
+        // MARK: 摄像头结束回调
+        m.recordEndCallBack = { [weak self] isSuccess, sticker in
+            guard let wself = self, let sticker = sticker else { return }
+            
+            if isSuccess{
+                wself.currentAssetProgress = sticker.timelineCMOut
+                let dur = wself.rscmanager.recordItem?.videoStickers.reduce(0, { partialResult, mod in
+                    (mod.timelineCMOut - mod.timelineCMIn).seconds + partialResult
+                })
+                wself.rscmanager.recordItem?.materialDuraion = CMTime(seconds: dur ?? 0, preferredTimescale: 1000)
+                BFLog(1, message: "camera:\(sticker.timelineCMIn.seconds) ~ \(sticker.timelineCMOut.seconds)")
+            }
+        }
         return m
     }()
     var rscurrentManager = BFRecordScreenBaseManager()
@@ -83,7 +100,6 @@ public class BFRecordScreenController: BFBaseViewController {
                 progressThumV.isHidden = false
                 cameraProgressThumV.isHidden = true
                 progreddL.isHidden = false
-                rscurrentManager.progressThumV = progressThumV
 
             case .Video:
                 rscurrentManager = rsvmanager
@@ -91,7 +107,6 @@ public class BFRecordScreenController: BFBaseViewController {
                 progressThumV.isHidden = false
                 cameraProgressThumV.isHidden = true
                 progreddL.isHidden = false
-                rscurrentManager.progressThumV = progressThumV
 
             case .Camera:
                 rscurrentManager = rscmanager
@@ -105,41 +120,34 @@ public class BFRecordScreenController: BFBaseViewController {
             default:
                 break
             }
-            rscurrentManager.dele = self
+            
             if let cell = collectionView.cellForItem(at: IndexPath(item: currItemModelIndex, section: 0)) as? BFImageCoverViewCell {
                 if (cell as? BFCameraCoverViewCell) != nil {
                     cell.playView.setInputRotation(GPUImageRotationMode(rawValue: 2), at: 0)
                     progressThumV.isHidden = true
-                    if let rendV = (rscurrentManager as? BFRecordScreenCameraManager)?.rendView {
-                        rendV.removeFromSuperview()
-                        cell.playView.addSubview(rendV)
-                        rendV.snp.makeConstraints { make in
-                            make.edges.equalToSuperview()
-                        }
-                        
-                        // MARK: 摄像头结束回调
-                        (rscurrentManager as? BFRecordScreenCameraManager)?.recordEndCallBack = { [weak self] _, sticker in 
-                            guard let wself = self, let sticker = sticker else { return }
-                            
-                            wself.currentAssetProgress = CMTime(seconds: sticker.timelineOut , preferredTimescale: 1000)
-//                            if isSuccess, let sticker = sticker {
-//                                itemModel.videoStickers.append(sticker)
-//                            }
-                        }
+
+                    rscmanager.rendView.removeFromSuperview()
+                    cell.playView.addSubview(rscmanager.rendView)
+                    rscmanager.rendView.snp.makeConstraints { make in
+                        make.edges.equalToSuperview()
                     }
                     
+                  
+                    
                 } else {
                     cell.playView.setInputRotation(GPUImageRotationMode(rawValue: 0), at: 0)
-//                    if itemModel.mediaType == .Video {
-//                        rsvmanager.assetPlayer
-//                    }
+                    progressThumV.isHidden = false
                 }
                 rscurrentManager.playView = cell.playView
-                rscurrentManager.progreddL = progreddL
-                
-                rscurrentManager.recordItem = itemModel
-                rscurrentManager.resetEnv()
             }
+            
+            rscurrentManager.progreddL = progreddL
+            rscurrentManager.recordPlayer = recordPlayer
+            rscurrentManager.progressThumV = progressThumV
+            rscurrentManager.dele = self
+
+            rscurrentManager.recordItem = itemModel
+            rscurrentManager.resetEnv()
 
         }
     }
@@ -499,8 +507,15 @@ public class BFRecordScreenController: BFBaseViewController {
 
     deinit {
         NotificationCenter.default.removeObserver(self)
-        avplayerTimeObserver?.invalidate()
-        recordPlayerTimeObserver?.invalidate()
+        if avplayerTimeObserver != nil {
+            assetPlayer.removeTimeObserver(avplayerTimeObserver)
+            avplayerTimeObserver?.invalidate()
+        }
+        if recordPlayerTimeObserver != nil {
+            recordPlayer.removeTimeObserver(recordPlayerTimeObserver)
+            recordPlayerTimeObserver?.invalidate()            
+        }
+        
         if isRecording {
             recorderManager?.stopRecord(isCancel: true)
         }
@@ -788,7 +803,7 @@ public class BFRecordScreenController: BFBaseViewController {
                 let showText = ((payload?["result"]) as? String) ?? ""
                 newSubtitle.text = showText
 //                newSubtitle.audioFilePath = audioFilePath ?? ""
-                BFLog(1, message: "添加字幕数据 timelineIn \(newSubtitle.timelineIn.seconds) timelineOut \(newSubtitle.timelineOut.seconds) text: \(newSubtitle.text) 音频路径为:\(audioFilePath ?? "bb") 传入的地址:\(currentVoice.wavFilePath ?? "aa")")
+                BFLog(1, message: "添加字幕数据 timelineIn \(newSubtitle.timelineIn.seconds) timelineOut \(newSubtitle.timelineOut.seconds) text: \(newSubtitle.text)")
                 newSubtitle.setting = self?.subtitleSettingView.subtitle.setting ?? BFSubTitileSettingModel()
                 currentItem.titleStickers.append(newSubtitle)
             }
@@ -863,12 +878,16 @@ public class BFRecordScreenController: BFBaseViewController {
 
                 if wself.itemModels[wself.currItemModelIndex].mediaType != .Video {
                     var duration: CMTime = .zero
-                    wself.itemModels[wself.currItemModelIndex].voiceStickers.forEach { temp in
-                        BFLog(1, message: "录制结束-最终:\(temp.wavFilePath ?? "")-\(temp.startCMTime.seconds)-\(temp.endCMTime.seconds)-\(temp.endCMTime.seconds - temp.startCMTime.seconds)")
-                        temp.duration = "\(temp.endCMTime.seconds - temp.startCMTime.seconds)"
-                        duration = duration + temp.endCMTime - temp.startCMTime
+                    if wself.itemModels[wself.currItemModelIndex].mediaType == .Image{
+                        wself.itemModels[wself.currItemModelIndex].voiceStickers.forEach { temp in
+                            BFLog(1, message: "录制结束-最终:\(temp.wavFilePath ?? "")-\(temp.startCMTime.seconds)-\(temp.endCMTime.seconds)-\(temp.endCMTime.seconds - temp.startCMTime.seconds)")
+                            temp.duration = "\(temp.endCMTime.seconds - temp.startCMTime.seconds)"
+                            duration = duration + temp.endCMTime - temp.startCMTime
+                        }
+                        wself.itemModels[wself.currItemModelIndex].materialDuraion = duration
+                        
                     }
-                    wself.itemModels[wself.currItemModelIndex].materialDuraion = duration
+                    
                     self?.isEndPlay = true
                     // 录制结束显示播放按钮
                     wself.playBtn.isSelected = wself.itemModels[wself.currItemModelIndex].voiceStickers.count <= 0
@@ -931,7 +950,7 @@ public class BFRecordScreenController: BFBaseViewController {
     /// 更新字幕,在回放时使用
     /// - Parameter time: 当前播放的进度
     func updateSubtitle(time: CMTime) {
-        BFLog(message: "currTime is \(CMTimeGetSeconds(time))")
+        BFLog(1, message: "currTime is \(CMTimeGetSeconds(time))")
         if isRecording || !subtitleSettingView.subtitle.setting.subtitleIsShow || currentPlayRecordIndex == -3 {
             // currentPlayRecordIndex == -3 代表刚录完音,不要找字幕,会因为小幅度回退seek导致上一个字幕出现
             if subtitleLabel.text?.count ?? 0 > 0 {
@@ -1119,11 +1138,14 @@ public class BFRecordScreenController: BFBaseViewController {
             event.deletedTittles = deleteTitles(voiceModel: model)
             events.append(event)
 
+            rscurrentManager.deleteRecord(at: currentAssetProgress)
+
             // 注:删除录音后图片素材需要回撤指针进度,同时后面录音往前挪
             if itemModels[currItemModelIndex].mediaType == .Image {
                 let currDuration = model.endCMTime - model.startCMTime
                 itemModels[currItemModelIndex].materialDuraion = itemModels[currItemModelIndex].materialDuraion - currDuration
                 currentAssetProgress = model.startCMTime
+                
                 // 更新进度
                 resetCurrentProgress()
                 for (index, item) in itemModels[currItemModelIndex].voiceStickers.enumerated() {
@@ -1145,12 +1167,20 @@ public class BFRecordScreenController: BFBaseViewController {
                 /// 重绘录音进度视图
                 resetAllIndirectionView()
 
+                
+                
+            }
+            
+            rscurrentManager.changeRecordMaterail()
+            
+            if itemModels[currItemModelIndex].mediaType != .Video{
                 // 判断是否无录音了
                 if itemModels[currItemModelIndex].materialDuraion == .zero {
                     playBtn.isSelected = true
                     playBtn.isHidden = playBtn.isSelected
                 }
             }
+
             searchStopAtRecordRange()
             changeWithDrawBtnLayout(3)
         }
@@ -1225,22 +1255,24 @@ public class BFRecordScreenController: BFBaseViewController {
         }
         beginOnStartBtn = false
 
-        BFLog(1, message: "停止录音-")
+        BFLog(1, message: "停止录音- \(currentAssetProgress.seconds)")
         recordBtn.isEnabled = false
         DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak self] in
             self?.recordBtn.isEnabled = true
         }
 
         rscurrentManager.endRecord()
+        
         isRecording = false
 //        progressThumV.progressView.isUserInteractionEnabled = true
 //        collectionView.isScrollEnabled = true
 
         UIApplication.shared.keyWindow?.isUserInteractionEnabled = true
-        recorderManager?.stopRecord(isCancel: false)
 
-        if currentAssetProgress.seconds - (recorderManager?.voiceModel?.startCMTime.seconds ?? 0) >= 1.0 {
+        if currentAssetProgress.seconds - (recorderManager?.voiceModel?.startCMTime.seconds ?? 0) > 1.0 {
+            recorderManager?.stopRecord(isCancel: false)
         } else {
+            recorderManager?.stopRecord(isCancel: true)
             changeProgress(changCMTime: recorderManager?.voiceModel?.startCMTime ?? .zero)
         }
 
@@ -1707,7 +1739,8 @@ public class BFRecordScreenController: BFBaseViewController {
                 BFLog(3, message: "播放结束")
                 didPlayToEndTime((shouldPlayRecordIndex, recordedAudio), newItem)
             }
-            recordPlayerTimeObserver?.invalidate()
+//            recordPlayer.removeTimeObserver(recordPlayerTimeObserver as Any)
+//            recordPlayerTimeObserver?.invalidate()
             recordPlayerTimeObserver = recordPlayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 1000), queue: DispatchQueue.global()) { [weak self, weak recordPlayer] time in
                 guard let wself = self, let rPlay = recordPlayer else {
                     BFLog(3, message: "wself为空")
@@ -1814,25 +1847,22 @@ public class BFRecordScreenController: BFBaseViewController {
         recorderManager?.voiceModel = nil
 
         itemModels[currItemModelIndex].titleStickers.sort { m1, m2 in
-            m1.timelineIn < m2.timelineIn
+            CMTimeCompare(m1.timelineIn, m2.timelineIn) < 0
         }
 
         isNormalPlaying = true
-        if isEndPlay || (itemModels[currItemModelIndex].mediaType == .Image && CMTimeCompare(currentAssetProgress, itemModels[currItemModelIndex].materialDuraion) >= 0) {
+        if isEndPlay || (itemModels[currItemModelIndex].mediaType != .Video && CMTimeCompare(currentAssetProgress, itemModels[currItemModelIndex].materialDuraion) >= 0) {
             isEndPlay = false
             assetPlayer.seek(to: CMTime.zero)
             progressThumV.progress = 0
             currentPlayRecordIndex = -1
             BFLog(3, message: "重置播放index-\(#function) = \(currentPlayRecordIndex)")
-            if itemModels[currItemModelIndex].mediaType == .Video {
-                recordBtn.isHidden = false
-            }
+
             currentAssetProgress = CMTime.zero
         }
         
         rscurrentManager.play()
         
-
         deleteRecordBtn.isHidden = true
 
         subtitleBtn.isHidden = true
@@ -1845,11 +1875,11 @@ public class BFRecordScreenController: BFBaseViewController {
         BFLog(1, message: "暂停播放")
         isNormalPlaying = false
 
-        // ---- 修复暂停播放回退问题
-        avplayerTimeObserver?.invalidate()
-        avplayerTimeObserver = nil
-        recordPlayerTimeObserver?.invalidate()
-        recordPlayerTimeObserver = nil
+//        // ---- 修复暂停播放回退问题
+//        avplayerTimeObserver?.invalidate()
+//        avplayerTimeObserver = nil
+//        recordPlayerTimeObserver?.invalidate()
+//        recordPlayerTimeObserver = nil
         // ----
 
         subtitleBtn.isHidden = false
@@ -1934,14 +1964,14 @@ public class BFRecordScreenController: BFBaseViewController {
         } else {
             assetPlayer.replaceCurrentItem(with: item)
             BFLog(message: "设置播放器item-替换:\(String(describing: item))")
-//            assetPlayer.volume = noSpeakVolume
-            avplayerTimeObserver?.invalidate()
             avplayerTimeObserver = assetPlayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 1000), queue: DispatchQueue.global()) { [weak self] time in
                 // 进度监控
-                self?.periodicTimeObserver(item: item, time: time)
-                if self?.isNormalPlaying ?? false {
+                guard let wself = self else { return }
+                
+                wself.periodicTimeObserver(item: item, time: time)
+                if wself.isNormalPlaying {
                     // 播放录音
-                    self?.startPlayRecord(time: time)
+                    wself.startPlayRecord(time: time)
                 }
             } as? NSKeyValueObservation
         }
@@ -2051,7 +2081,7 @@ public class BFRecordScreenController: BFBaseViewController {
                 }
             }
         } else {
-            currentAssetProgress = isBack ? CMTime(value: CMTimeValue(newProgress * 1000), timescale: 1000) : (progress != -1 ? CMTime(value: CMTimeValue(newProgress * Float(itemModels[currItemModelIndex].materialDuraion.seconds) * 1000), timescale: 1000) : changCMTime)
+            currentAssetProgress = isBack ? CMTime(seconds: Double(newProgress), preferredTimescale: 1000) : ((progress != -1) ? CMTime(seconds: (Double(newProgress) * itemModels[currItemModelIndex].materialDuraion.seconds), preferredTimescale: 1000) : changCMTime)
             if currentAssetProgress.seconds > itemModels[currItemModelIndex].materialDuraion.seconds {
                 currentAssetProgress = itemModels[currItemModelIndex].materialDuraion
             }
@@ -2068,7 +2098,7 @@ public class BFRecordScreenController: BFBaseViewController {
 
     // 画进度线
     func drawProgressIndication(progress: Double) {
-        if indirectionView == nil {
+        if itemModels[currItemModelIndex].mediaType != .Camera, indirectionView == nil {
             var percenWidth: CGFloat = 0
             if itemModels[currItemModelIndex].mediaType == .Image {
                 percenWidth = progressThumV.thumbImageWidth / 2.0
@@ -2258,9 +2288,7 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
             }
             // 更新缩略图
             //            progressThumV.isHidden = false
-            progreddL.text = "00:00"
-            // 重置指针
-            currentAssetProgress = .zero
+            
             searchStopAtRecordRange()
             // 切换要更新当前录制index,避免在录制完以后切换素材这种时候为-3会拦截
             currentPlayRecordIndex = -1
@@ -2388,6 +2416,8 @@ public extension BFRecordScreenController {
     /// 重绘录音进度视图
     func resetAllIndirectionView() {
         if itemModels[currItemModelIndex].mediaType == .Camera {
+            rscmanager.cameraProgressV?.collectionV.reloadData()
+            rscmanager.locationTo(time: currentAssetProgress)
             return
         }
         // 重绘录音进度视图

+ 6 - 1
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenImageManager.swift

@@ -10,7 +10,10 @@ import Foundation
 class BFRecordScreenImageManager : BFRecordScreenBaseManager{
     
     override func resetEnv() {
-        
+        // 重置指针
+        currentAssetProgress = .zero
+        super.resetEnv()
+
     }
     
     override func startRecord() {
@@ -21,6 +24,8 @@ class BFRecordScreenImageManager : BFRecordScreenBaseManager{
         dele?.startPlayRecord(time: currentAssetProgress)
     }
     
+    override func changeRecordMaterail() {}
+    
     override func clean() {
         super.clean()
         filter.removeTarget(playView)

+ 5 - 1
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenVideoManager.swift

@@ -35,8 +35,12 @@ class BFRecordScreenVideoManager : BFRecordScreenBaseManager{
         movie?.startProcessing()
         movieIsProcessing = true
         
+        // 重置指针
+        currentAssetProgress = .zero
+        
         dele?.setAudioPlay(item: playerItem)
-//        assetPlayer?.seek(to: .zero, toleranceBefore: CMTime(value: 1, timescale: 1_000_000), toleranceAfter: CMTime(value: 1, timescale: 1_000_000))
+        
+        super.resetEnv()
 
     }
     

+ 6 - 4
BFRecordScreenKit/Classes/RecordScreen/View/ProgressView/BFCameraProgressView.swift

@@ -69,7 +69,7 @@ class BFCameraProgressView: BFProgressBaseView {
             
             let p = CGPoint(x: progress.seconds * 70 / 5.0, y: 0)
             collectionV.contentOffset = p
-            BFLog(1, message: "px0: \(p.x)")
+//            BFLog(1, message: "updateCellWidth: \(progress.seconds)")
         }
     }
 }
@@ -97,7 +97,7 @@ extension BFCameraProgressView: UICollectionViewDelegateFlowLayout, UICollection
                 if let (ind, _) = sticker.thumImgs?.enumerated().first(where: { ele in
                     ele.1 == img
                 }) {
-                    size = CGSize(width: max(0, min(((sticker.timelineOut - sticker.timelineIn) / 5.0  -  CGFloat(ind))*70.0, 70.0)), height: 50.0)
+                    size = CGSize(width: max(0, min(((sticker.timelineCMOut - sticker.timelineCMIn).seconds / 5.0  -  CGFloat(ind))*70.0, 70.0)), height: 50.0)
                 }
                 
                 if size.width < 0 {
@@ -105,9 +105,11 @@ extension BFCameraProgressView: UICollectionViewDelegateFlowLayout, UICollection
                     size = .zero
                 }
 
-                BFLog(1, message: "curr size - row:\(indexPath.row), \(size.width)")
+//                BFLog(1, message: "curr size - row:\(indexPath.row), \(size.width)")
             }
         }
+//        BFLog(1, message: "size:\(size.width)")
+
         return size
     }
     
@@ -129,7 +131,7 @@ extension BFCameraProgressView: UICollectionViewDelegateFlowLayout, UICollection
         }
         
         imgview?.image = recordItem?.thumbImgs[indexPath.row]
-        BFLog(1, message: "cell manke: \(indexPath.row)")
+//        BFLog(1, message: "cell manke: \(indexPath.row)")
         return cell
     }
 }

+ 1 - 1
BFRecordScreenKit/Classes/RecordScreen/View/ProgressView/BFVideoThumbProgressView.swift

@@ -16,7 +16,7 @@ class BFVideoThumbProgressView: BFProgressBaseView {
     override var recordItem: BFRecordItemModel? {
         didSet {
             // 指针回归
-            BFLog(1, message: "new recorditem")
+//            BFLog(1, message: "new recorditem")
             progress = 0
             if recordItem?.mediaType == .Video {
                 dealWithVideoThumb()