Преглед изворни кода

Merge branch 'dev' of https://git.yishihui.com/iOS/BFRecordScreenKit into dev
合并代码

jsonwang пре 3 година
родитељ
комит
69c5157dd6

+ 38 - 27
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenController.swift

@@ -1100,23 +1100,26 @@ public class BFRecordScreenController: BFBaseViewController {
                             if mod.startCMTime.seconds >= model.startCMTime.seconds {
                                 mod.startCMTime = mod.startCMTime + duration
                                 mod.endCMTime = mod.endCMTime + duration
+                                
+                                //对应的字幕进行后移修改
+                                let titleList = recordItem.titleStickers.filter({ title in
+                                    title.recordId == mod.recordId
+                                })
+                                titleList.forEach { t in
+                                    t.timelineIn = t.timelineIn + duration
+                                    t.timelineOut = t.timelineOut + duration
+                                }
+                                //对应的变声进行后移修改
+                                let voiceList = recordItem.voiceChangeStickers.filter({ voice in
+                                    voice.recordId == mod.recordId
+                                })
+                                voiceList.forEach { mod in
+                                    mod.startCMTime = mod.startCMTime + duration
+                                    mod.endCMTime = mod.endCMTime + duration
+                                }
                             }
                         })
-                        
-                        recordItem.voiceChangeStickers.forEach({ mod in
-                            if mod.startCMTime.seconds >= model.startCMTime.seconds {
-                                mod.startCMTime = mod.startCMTime + duration
-                                mod.endCMTime = mod.endCMTime + duration
-                            }
-                        })
-
-                        recordItem.titleStickers.forEach({ mod in
-                            if mod.timelineIn.seconds >= model.startCMTime.seconds {
-                                mod.timelineIn = mod.timelineIn + duration
-                                mod.timelineOut = mod.timelineOut + duration
-                            }
-                        })
-                        
+   
                     }
                 }
                 
@@ -1131,10 +1134,10 @@ public class BFRecordScreenController: BFBaseViewController {
                 // 录制结束回调给主工程页面(埋点之类功能)
                 wself.recordEndHandle?(model)
 
-                if wself.currMediaType != .Video {
+                if wself.currMediaType != .Video,  CMTimeCompare(model.endCMTime, wself.itemModels[wself.currItemModelIndex].materialDuraion) == 0{
                     wself.isEndPlay = true
                 }
-                
+//
                 DispatchQueue.main.async { [weak self] in
                     guard let wself = self else { return }
 
@@ -1157,7 +1160,9 @@ public class BFRecordScreenController: BFBaseViewController {
                     wself.resetCurrentProgress()
                 }
 
-                wself.currentPlayRecordIndex = -3 // 刚录音完,不需要播放录音
+                if wself.currMediaType == .Video {
+                    wself.currentPlayRecordIndex = -3 // 刚录音完,不需要播放录音
+                }
                 BFLog(3, message: "重置播放index-\(#function) = \(wself.currentPlayRecordIndex)")
                 recorderManager?.voiceModel = nil
                 
@@ -1223,7 +1228,7 @@ public class BFRecordScreenController: BFBaseViewController {
                 let currShowSubtitle = recordItem.titleStickers[showSubtitleIndex]
                 
                 if CMTimeCompare(currShowSubtitle.timelineIn, time) <= 0, CMTimeCompare(currShowSubtitle.timelineOut, time) > 0 {
-                    // 已存在字幕
+                    // 已存在不同的字幕
                     if subtitleLabel.text != currShowSubtitle.text {
                         subtitleLabel.text = currShowSubtitle.text
                         setSubtitleStyle(settingModel: subtitleSettingView.subtitle.setting)
@@ -1573,7 +1578,10 @@ public class BFRecordScreenController: BFBaseViewController {
             recorderManager?.cancelTitleService()
         }
         
-        events.removeLast()
+        if currMediaType != .Camera{
+            events.removeLast()
+        }
+        
         // 删除文件
         recorderManager?.deleteFile(outfile: voiceModel?.wavFilePath ?? "")
         var subtitleCount = itemModels[currItemModelIndex].titleStickers.count
@@ -1857,6 +1865,7 @@ public class BFRecordScreenController: BFBaseViewController {
                 changeWithDrawBtnLayout(event.type)
             } else {
                 changeWithDrawBtnLayout(0)
+                withDrawBtn.isEnabled = false
             }
             searchStopAtRecordRange()
             let itemModel = itemModels[currItemModelIndex]
@@ -2135,9 +2144,9 @@ public class BFRecordScreenController: BFBaseViewController {
     func play() {
         //如果当前段有没有转完的发音人显示 Loadingview
         if(!voiceChangeStickerFinish(itemIndex: currItemModelIndex,isShowLoadView: true)){
-          
             return
         }
+
         BFLog(1, message: "开始播放 \(currentAssetProgress.seconds)")
         recorderManager?.voiceModel = nil
         events.append(WithDrawModel(type: 1, timestamp: currentAssetProgress, recordItem: rscurrentManager.recordItem!))
@@ -2365,7 +2374,7 @@ public class BFRecordScreenController: BFBaseViewController {
             DispatchQueue.main.async { [weak self] in
                 guard let wself = self else { return }
                 
-                wself.indirectionView?.setProgress(start: startTime, progress: max(0, progress))
+                wself.indirectionView?.setProgress(start: startTime, progress: max(0, progress), isInsert:wself.currMediaType == .Image)
             }
         }
     }
@@ -2381,9 +2390,9 @@ public class BFRecordScreenController: BFBaseViewController {
             withDrawBtn.setTitle("record_recover".BFLocale, for: .normal)
         case 2:
             withDrawBtn.setTitle("record_undo".BFLocale, for: .normal)
-        case 0:
-            withDrawBtn.isEnabled = false
-            fallthrough
+//        case 0:
+//            withDrawBtn.isEnabled = false
+//            fallthrough
         default:
             withDrawBtn.setTitle("record_back".BFLocale, for: .normal)
         }
@@ -2477,7 +2486,7 @@ public class BFRecordScreenController: BFBaseViewController {
         if isRecording, currMediaType == .Image {
             let startTime = recorderManager?.voiceModel?.startCMTime ?? .zero
             // 使用播放器的进度来画线,因为进度是跟着播放器来了
-            indirectionView?.setProgress(start: startTime, progress: progress)
+            indirectionView?.setProgress(start: startTime, progress: progress, isInsert: true)
         }
         if currMediaType == .Image {
             imageRecordProgress(isRecord: true, progress: progress)
@@ -2645,7 +2654,7 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
                 guard let wself = self else { return }
 
                 /// 重绘录音进度视图
-//                wself.resetAllIndirectionView()
+                wself.resetAllIndirectionView()
                 // 重绘录音进度
                 wself.recordBtn.isEnabled = true
                 wself.searchStopAtRecordRange()
@@ -2710,6 +2719,8 @@ public extension BFRecordScreenController {
             recordStartPlayTime = currentAssetProgress
             currenStartPlayTime = CMTime.zero
         }
+        
+        // 音
         playRecord(at: time, periodicTimeObserver: { [weak self] currentT, _ in
             
             guard let wself = self else { return }

+ 68 - 3
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenImageManager.swift

@@ -7,9 +7,13 @@
 
 import Foundation
 import CoreMedia
+import AVFoundation
+import BFCommonKit
 
 class BFRecordScreenImageManager : BFRecordScreenBaseManager{
     
+    fileprivate var timerr:Timer?
+    var isPlaying = false
     override func resetEnv() {
         // 重置指针
         currentAssetProgress = .zero
@@ -22,7 +26,67 @@ class BFRecordScreenImageManager : BFRecordScreenBaseManager{
     }
     
     override func play() {
-        dele?.startPlayRecord(time: currentAssetProgress)
+        // 找到当前要播放的音频
+        timerr?.invalidate()
+        
+        if ((recordItem?.materialDuraion ?? .zero) - currentAssetProgress).seconds < 0.05 {
+            currentAssetProgress = .zero
+        }
+
+        checkCurrentPlayStatus()
+        
+        let startPlayTime = Date()
+        let startProgress = currentAssetProgress
+        
+        timerr = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: {[weak self] _ in
+            guard let wself = self else { return }
+            // MARK: 进度计时器
+            let currTime = startProgress + CMTime(seconds: Date().timeIntervalSince(startPlayTime), preferredTimescale: 1000)
+            wself.dele?.progreddL.text = String(format: "%@", max(0, min(currTime.seconds, (wself.recordItem?.materialDuraion.seconds ?? 0))).formatDurationToHMS())
+            wself.currentAssetProgress = min(currTime, (wself.recordItem?.materialDuraion ?? .zero))
+            wself.dele?.progressThumV.progress = wself.currentAssetProgress
+            wself.dele?.updateSubtitle(time: wself.currentAssetProgress)
+            
+            if currTime.seconds >= (wself.recordItem?.materialDuraion.seconds ?? 0) {
+                wself.dele?.pause()
+                wself.isPlaying = false
+                return
+            }
+            
+            wself.checkCurrentPlayStatus()
+        })
+        RunLoop.current.add(timerr!, forMode: .common)
+    }
+    
+    func checkCurrentPlayStatus(){
+        if let voice = recordItem?.voiceStickers.first(where: { mod in
+            (mod.startCMTime - currentAssetProgress).seconds <= 0.05 && (mod.endCMTime - currentAssetProgress).seconds > 0.05
+        }){
+            let su = (recordPlayer?.currentItem?.asset as? AVURLAsset)?.url.lastPathComponent != (voice.wavFilePath as NSString?)?.lastPathComponent
+            if (recordPlayer?.currentItem == nil) || su || (!su && !isPlaying){
+                if su { // 我需要换源地址
+                    recordPlayer?.pause()
+                    recordPlayer?.replaceCurrentItem(with: AVPlayerItem(url: URL(fileURLWithPath: voice.wavFilePath)))
+                }
+                isPlaying = true
+                let tt = max(CMTime.zero, currentAssetProgress - voice.startCMTime)
+                BFLog(1, message: "tt:\(tt.seconds)")
+                recordPlayer?.seek(to: tt , toleranceBefore: CMTime(seconds: 1, preferredTimescale: 10000), toleranceAfter: CMTime(seconds: 1, preferredTimescale: 10000), completionHandler: {[weak self] isfinished in
+                    guard let wself = self else { return }
+                    
+                    wself.recordPlayer?.play()
+//                    if isfinished {
+//                    }
+                })
+            }
+            
+        }
+    }
+    
+    override func pause() {
+        timerr?.invalidate()
+        timerr = nil
+        
     }
     
     override func deleteRecord(at: CMTime) {
@@ -49,7 +113,6 @@ class BFRecordScreenImageManager : BFRecordScreenBaseManager{
             // 更新进度
             dele?.resetCurrentProgress()
             
-            
             for (index, item) in recordItem.voiceStickers.enumerated() {
                 if index >= dele?.isStopAtRecordRange ?? 0 {
                     // 注:开始时间减去duration or 等一前一段录音的结束时间
@@ -83,6 +146,8 @@ class BFRecordScreenImageManager : BFRecordScreenBaseManager{
     override func clean() {
         super.clean()
         filter.removeTarget(playView)
-        
     }
+    
+    //MARK: - 播放逻辑
+    
 }

+ 30 - 11
BFRecordScreenKit/Classes/RecordScreen/View/BFIndirectionProgressView.swift

@@ -82,23 +82,38 @@ class BFIndirectionProgressView: UIView {
     ///   - _:
     ///   - start: 开始录制的时间
     ///   - progress: 当前录制时长
-    func setProgress(start: CMTime = .zero, progress: Float64) {
+    func setProgress(start: CMTime = .zero, progress: Float64, isInsert:Bool = false) {
         if start.seconds * percenWidth >= frame.width {
             frame.size.width = (superview as? UIScrollView)?.contentSize.width ?? 0
         }
 
         detectionAndCreateItem(start: start, progress: progress)
-        if let currentItem = currentItem {
-            let oldwidth = currentItem.frame.width
-            currentItem.frame.size.width = progress < 0 ? 0 : progress * percenWidth
-            BFLog(message: "当前view:\(String(describing: currentItem))")
-            
-            // 插入后后边的视图后移
-            subviews.forEach { subv in
-                if currentItem.frame.maxX < subv.frame.maxX {
-                    subv.frame = subv.frame.offsetBy(dx: (currentItem.width) - oldwidth, dy: 0)
+
+        if isInsert {
+            if let currentItem = currentItem {
+                let oldwidth = currentItem.frame.width
+                currentItem.frame.size.width = progress < 0 ? 0 : progress * percenWidth
+                BFLog(message: "当前view:\(String(describing: currentItem))")
+                
+                // 插入后后边的视图后移
+                subviews.forEach { subv in
+                    if currentItem.frame.maxX < subv.frame.maxX {
+                        subv.frame = subv.frame.offsetBy(dx: (currentItem.width) - oldwidth, dy: 0)
+                    }
                 }
             }
+        }else {
+            // 视频录制
+            currentItem?.frame.size.width = progress < 0 ? 0 : progress * percenWidth
+            BFLog(message: "当前view:\(String(describing: currentItem))")
+            let vc = subviews.first { [weak self] sub in
+                (self?.currentItem?.frame.minX ?? 0) < sub.frame.minX && sub.frame.minX < (self?.currentItem?.frame.maxX ?? 0)
+            }
+            if vc != nil {
+                deletedView = vc
+                vc?.removeFromSuperview()
+                BFLog(message: "添加覆盖view-添加:deletedView = \(String(describing: deletedView))")
+            }
         }
     }
 
@@ -108,7 +123,7 @@ class BFIndirectionProgressView: UIView {
         BFLog(message: "检测并创建item:\(start)")
         if currentItem == nil {
             deletedView = nil
-//            subviews[curr]
+
             currentItem = createItemView(minX: start.seconds * percenWidth)
             if subviews.count > 1 {
                 let vvs = subviews.sorted { v1, v2 in
@@ -162,6 +177,10 @@ class BFIndirectionProgressView: UIView {
     func resetCurrentItem(start: CGFloat, end: CGFloat) {
         currentItem?.frame.origin.x = start * percenWidth
         currentItem?.frame.size.width = (end - start) * percenWidth
+
+        if subviews.max(by: {$0.rightX < $1.rightX}) == currentItem {
+            (currentItem as? BFThumImageView)?.isHiddenBord = true
+        }
         currentItem = nil
         BFLog(message: "重置currentItem:\(start)")
     }