Browse Source

1.update podfile

wenweiwei 3 years ago
parent
commit
6d656efb37

+ 2 - 1
.gitignore

@@ -35,4 +35,5 @@ Carthage/Build
 # `pod install` in .travis.yml
 #
 # Pods/
-Example/Pods/*
+Example/Pods/*
+Example/Podfile.lock

+ 50 - 0
BFRecordScreenKit/Classes/BFIntroduceToolView.swift

@@ -0,0 +1,50 @@
+//
+//  BFIntroduceToolView.swift
+//  BFRecordScreenKit
+//
+//  Created by 胡志强 on 2021/11/26.
+//
+
+import Foundation
+import UIKit
+
+class BFIntroduceToolView: UIView {
+    
+    var choosedToolHandle:((UIView) -> Void)?
+    
+    fileprivate let toolImgs = ["", "", ""]
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override init(frame: CGRect) {
+        super.init(frame: CGRect(x: 0, y: 0, width: 40, height: 40*toolImgs.count))
+        isUserInteractionEnabled = true
+        clipsToBounds = true
+        
+        for i in 0 ..< toolImgs.count {
+            let btn = UIButton(frame: CGRect(x: 0, y: i * 40, width: 40, height: 40))
+            btn.backgroundColor = UIColor.randomColor()
+            btn.setTitle("\(i)", for: .normal)
+            btn.setImage(imageInRecordScreenKit(by: toolImgs[i]), for: .normal)
+            btn.addTarget(self, action: #selector(toolAction(btn:)), for: .touchUpInside)
+            addSubview(btn)
+        }
+        
+        
+        
+    }
+    
+    @objc func toolAction(btn:UIButton) {
+        let v = UILabel(frame: CGRect(x: 0, y: 0, width: 10, height: 40))
+        v.backgroundColor = UIColor.randomColor()
+        v.layer.shadowColor = UIColor.black.cgColor
+        v.layer.shadowRadius = 3
+            
+        choosedToolHandle?(v)
+    
+        
+    }
+    
+}

+ 46 - 4
BFRecordScreenKit/Classes/BFRecordExport.swift.swift → BFRecordScreenKit/Classes/BFRecordExport.swift

@@ -1,9 +1,9 @@
 //
-//  BFRecordExport.swift.swift
+//  BFRecordExport.swift
 //  BFRecordScreenKit
 //
 //  Created by 胡志强 on 2021/11/25.
-//
+//  录屏视频导出
 
 import Foundation
 import AVFoundation
@@ -66,10 +66,53 @@ public class BFRecordExport {
     enum DispatchError: Error {
         case timeout
     }
+    
+    func getOutputFilePath() -> URL{
+        var outPutMP4Path = exportVideosDirectory
+        if !directoryIsExists(dicPath: outPutMP4Path) {
+            createDirectory(path: outPutMP4Path)
+        }
+        outPutMP4Path.append("video_\(String.qe.timestamp()).mp4")
+        return URL(fileURLWithPath: outPutMP4Path)
+        
+    }
+    
+    func exprotVideo(){
+//        //重新创建GPUImageMovie用于保存
+//           saveMovie = [[GPUImageMovie alloc] initWithURL:self.pathURL];
+        let saveFilter = GPUImageFilter()
+        let saveMovie = GPUImageMovie(url: asset?.url)
+        saveMovie?.shouldRepeat = false
+        saveMovie?.addTarget(saveFilter)
+        
+        let filePath = getOutputFilePath()
+        let savewrite = GPUImageMovieWriter(movieURL: getOutputFilePath(), size: getVideoSize())
+        savewrite?.shouldPassthroughAudio = true
+        savewrite?.encodingLiveVideo = true
+        saveFilter.addTarget(savewrite)
+        
+        saveMovie?.enableSynchronizedEncoding(using: savewrite)
+//        saveMovie?.audioEncodingTarget = savewrite
+        savewrite?.startRecording()
+        saveMovie?.startProcessing()
+        savewrite?.completionBlock = {
+            DispatchQueue.main.async { [weak self, weak savewrite] in
+                saveFilter.removeTarget(savewrite)
+                savewrite?.finishRecording()
+                saveMovie?.cancelProcessing()
+                saveMovie?.removeTarget(saveFilter)
+                cShowHUB(superView: nil, msg: "合成成功")
+                self?.exportCompletion?(nil, filePath)
+                self?.saveVideoToPhoto(url: filePath)
+            }
+        }
+    }
 
     
     func beginExport(videoStickers:[PQEditVisionTrackMaterialsModel], audioAsset: [AVURLAsset]?) {
         // 输出视频地址
+//        exprotVideo()
+//        return;
         var outPutMP4Path = exportVideosDirectory
         if !directoryIsExists(dicPath: outPutMP4Path) {
             createDirectory(path: outPutMP4Path)
@@ -92,7 +135,6 @@ public class BFRecordExport {
                         let semaphore = DispatchSemaphore(value: 0)
                         PQPlayerViewModel.mergeAudios(urls: list) { completURL in
                             audioUrl = completURL
-                            BFLog(1, message: "异步做同步")
                             semaphore.signal()
                         }
                         _ = semaphore.wait(timeout: .now() + 5)
@@ -194,7 +236,7 @@ public class BFRecordExport {
         self.asset?.tracks.forEach({ track in
             if track.mediaType == .video{
                 let realSize = __CGSizeApplyAffineTransform(track.naturalSize, track.preferredTransform)
-                size = CGSize(width: abs(realSize.width), height: abs(realSize.height))
+                size = CGSize(width: ceil(abs(realSize.width)), height: ceil(abs(realSize.height)))
             }
         })
         

+ 6 - 6
BFRecordScreenKit/Classes/BFRecordManager.swift

@@ -62,7 +62,7 @@ class BFRecordManager {
             BFLog(message: "count == \(count)")
             
         }
-
+        BFLog(1, message: "开始录制")
         audioRecorder?.startRecord()
         beginRecordTime = Date()
 
@@ -108,16 +108,16 @@ class BFRecordManager {
 
             let duration = Date().timeIntervalSince( strongSelf.beginRecordTime)
             if isSuccess && !isCancel && duration > 1 {
-                BFLog(message: "结束录音  结果:\(isSuccess) \n url is \(url)")
+                BFLog(1, message: "结束录音  结果:\(isSuccess) \n url is \(url)")
 
                 // 处理降噪
                 let noiseFilePath = url.replacingOccurrences(of: ".wav", with: "_noise_\(1)_.wav")
                 BFLog(1, message: "降噪后地址:\(noiseFilePath)")
                 NXNoiseReduction().denoise(url, outFile: noiseFilePath)
-                let model = PQVoiceModel()
-                model.wavFilePath = noiseFilePath
-                model.duration = String(format: "%f", duration)
-                self?.endRecordHandle?(true, model)
+                if let model = self?.voiceModel{
+                    model.wavFilePath = noiseFilePath
+                    self?.endRecordHandle?(true, model)
+                }
 
 //
 //                strongSelf.recorderPart.cacheRecorderFiles.append(URL(fileURLWithPath: noiseFilePath))

+ 198 - 59
BFRecordScreenKit/Classes/BFRecordScreenController.swift

@@ -12,25 +12,34 @@ import GPUImage
 import Photos
 import BFCommonKit
 import BFFramework
+import UIKit
 
 public class BFRecordScreenController: BFBaseViewController {
     
     public var nextActionHandle:(()->Void)?
     public var closeActionHandle:(()->Void)?
+    
+    // MARK: - 录制参数
     public var asset:PHAsset?
+//    var shouldPlayRecordIndex:Int = -1          // 当前应该播放的录音资源序号
+    var currentPlayRecordIndex:Int = -1         // 当前正在播放的录音资源序号
+    var isRecording = false                     // 是否正在录音
+    var isNormalPlaying = false {               // 是否正在录音
+        didSet{
+            playBtn.isSelected = isNormalPlaying
+        }
+    }
+    var currentAssetProgress : CMTime = .zero   // 当前素材播放的进度
+    // 视频素材
     public var avasset:AVURLAsset?
     public var recordList:[PQVoiceModel] = [PQVoiceModel]()
-
     var assetPlayer:AVPlayer?       // 原视频音频播放器
-    lazy var recordPlayer:AVAudioPlayer = {// 录音音频播放器
-        let player = AVAudioPlayer()
-        player.volume = 1
-        return player
-        
-    }()
+    var isCompletePlay = true
+    var hadPrepareToPlayRecord = false    // 录音播放器准备
+    var recordPlayer:AVPlayer? // 录音音频播放器
     var movie :GPUImageMovie?       // 视频预览
     var playView :GPUImageView?     // 视频展示视图
-    var isDragingProgressSlder : Bool = false
+    var isDragingProgressSlder : Bool = false // 是否在拖动进度条
     
     //定义音频的编码参数
     let recordSettings:[String : Any] = [AVSampleRateKey : 44100.0, //声音采样率
@@ -48,29 +57,44 @@ public class BFRecordScreenController: BFBaseViewController {
             
         }
         manager.endRecordHandle = {[weak self] (isTimeout, model) in
-            if FileManager.default.fileExists(atPath: model?.wavFilePath ?? ""){
+            if let model = model, FileManager.default.fileExists(atPath: model.wavFilePath ?? ""){
                 // 加入到语音数组里
+                let ass = AVURLAsset(url: URL(fileURLWithPath: model.wavFilePath))
+                
+                model.endTime = model.startTime + CMTimeGetSeconds(ass.duration)
                 while let m = self?.recordList.last{
-                    if m.startTime < model!.startTime {
+                    if model.startTime < m.startTime {
                         self?.recordList.removeLast()
-                    }else if m.endTime < model!.startTime {
-                        m.endTime = model!.startTime
+                    }else if m.endTime > model.startTime {
+                        m.endTime = model.startTime
                     }else{
                         break
                     }
                 }
-                self?.recordList.append(model!)
-                self?.drewRecordProgessLable()
+                BFLog(1, message: "添加录音文件:\(model.startTime) -- \(model.endTime)")
+                self?.recordList.append(model)
+                self?.drawOrUpdateRecordProgessLable()
             }
             
         }
         return manager
     }()
 
+    // MARK: - 视图参数
     var beginOnStartBtn:Bool = false
     var touchStart:CGPoint = CGPoint(x: 0, y: 0)
     var avplayerTimeObserver: NSKeyValueObservation?
 
+    lazy var progreddL : UILabel = {
+        let l = UILabel(frame: CGRect(x: 0, y: cDevice_iPhoneStatusBarHei, width: cScreenWidth, height: 14))
+        l.textAlignment = .center
+        l.font = UIFont.systemFont(ofSize: 10)
+        l.textColor = .white
+        l.shadowColor = .black
+        l.shadowOffset = CGSize(width: 1, height: 1)
+        return l
+    }()
+    
     lazy var playBtn:UIButton = {
         let btn = UIButton(frame: view.bounds)
         btn.addTarget(self, action: #selector(playVideo(btn:)), for: .touchUpInside)
@@ -100,6 +124,13 @@ public class BFRecordScreenController: BFBaseViewController {
         return btn
     }()
     
+    lazy var progessSildeBackV : UIView = {
+        let vv = UIView()
+        vv.backgroundColor = UIColor.hexColor(hexadecimal: "#303030")
+        
+        return vv
+    }()
+    
     lazy var progessSilde:BFPlayerSlider = {
         let sliderView = BFPlayerSlider()
         let tjbV = UIView(frame: CGRect(x: 0, y: 0, width: 4, height: 16))
@@ -109,8 +140,8 @@ public class BFRecordScreenController: BFBaseViewController {
         sliderView.setMaximumTrackImage(thbImage, for: .normal)
         sliderView.setThumbImage(thbImage, for: .highlighted)
         sliderView.setThumbImage(thbImage, for: .normal)
-        sliderView.maximumTrackTintColor = UIColor.hexColor(hexadecimal: "#303030")
-        sliderView.minimumTrackTintColor = UIColor.hexColor(hexadecimal: "#303030")
+        sliderView.maximumTrackTintColor = .clear // UIColor.hexColor(hexadecimal: "#303030")
+        sliderView.minimumTrackTintColor = .clear //UIColor.hexColor(hexadecimal: "#303030")
 //        sliderView.minimumTrackTintColor = UIColor.hexColor(hexadecimal: "#FA6400")
         sliderView.addTarget(self, action: #selector(sliderTouchBegan(sender:)), for: .touchDown)
         sliderView.addTarget(self, action: #selector(sliderTouchEnded(sender:)), for: .touchUpInside)
@@ -122,7 +153,7 @@ public class BFRecordScreenController: BFBaseViewController {
     lazy var closeBtn:UIButton = {
         let btn = UIButton(type: .custom)
         btn.setImage(imageInRecordScreenKit(by: "xx"), for: .normal)
-        btn.addTarget(self, action: #selector(close), for: .touchUpInside)
+        btn.addTarget(self, action: #selector(closePage), for: .touchUpInside)
         return btn
     }()
     
@@ -133,14 +164,29 @@ public class BFRecordScreenController: BFBaseViewController {
         return btn
     }()
     
-    //MARK: -- 生命周期
+    lazy var toolV : BFIntroduceToolView = {
+        let toolV = BFIntroduceToolView()
+        toolV.centerY = view.centerY
+        
+        toolV.choosedToolHandle = {[weak self] tool in
+            guard let sself = self else {
+                return
+            }
+            tool.center = sself.view.center
+            sself.view.addSubview(tool)
+        }
+        
+        return toolV
+        
+    }()
+    //MARK: ------------------ 生命周期
     deinit {
         cleanMovieTarget()
         NotificationCenter.default.removeObserver(self)
         avplayerTimeObserver?.invalidate()
         recorderManager.stopRecord(isCancel: true)
         assetPlayer?.pause()
-        recordPlayer.pause()
+        recordPlayer?.pause()
         
     }
     
@@ -160,10 +206,12 @@ public class BFRecordScreenController: BFBaseViewController {
         view.addSubview(playView!)
         fetchVideo()
         
-        
         view.addSubview(playBtn)
         view.addSubview(bottomeView)
+        view.addSubview(progreddL)
+//        view.addSubview(toolV)
         bottomeView.addSubview(recordBtn)
+        bottomeView.addSubview(progessSildeBackV)
         bottomeView.addSubview(progessSilde)
         bottomeView.addSubview(closeBtn)
         bottomeView.addSubview(nextBtn)
@@ -197,10 +245,15 @@ public class BFRecordScreenController: BFBaseViewController {
             make.top.width.height.equalTo(closeBtn)
         }
         
-        progessSilde.snp.makeConstraints { make in
+        progessSildeBackV.snp.makeConstraints { make in
             make.left.equalTo(closeBtn.snp.right).offset(16)
             make.right.equalTo(nextBtn.snp.left).offset(-16)
             make.centerY.equalTo(closeBtn)
+            make.height.equalTo(8)
+        }
+        
+        progessSilde.snp.makeConstraints { make in
+            make.left.right.centerY.equalTo(progessSildeBackV)
             make.height.equalTo(20)
         }
         
@@ -208,9 +261,9 @@ public class BFRecordScreenController: BFBaseViewController {
     
     // MARK: - 按钮事件响应
     
-    // 觸發拖曳手勢後 執行的動
+    // 触发拖曳手势后,执行的动
     @objc func pan(recognizer: UIPanGestureRecognizer) {
-        // 置 UIView 新的位置
+        // 置 UIView 新的位置
         if !checkStatus(show: false) {
             return
         }
@@ -252,28 +305,35 @@ public class BFRecordScreenController: BFBaseViewController {
     @objc func startRecord(btn:UIButton){
         btn.setImage(imageInRecordScreenKit(by: "mic2"), for: .normal)
         BFLog(1, message: "start \(UIControl.Event.touchDown)")
+        pause()
+
         let model = PQVoiceModel()
-        model.startTime = CMTimeGetSeconds(assetPlayer?.currentItem?.currentTime() ?? CMTime.zero)
+        model.startTime = CMTimeGetSeconds(self.currentAssetProgress)
         recorderManager.voiceModel? = model
         recorderManager.startRecord(index: recordList.count)
         movie?.startProcessing()
         assetPlayer?.volume = 0
         assetPlayer?.play()
+        isRecording = true
     }
     
     @objc func endRecord(btn:UIButton){
         recordBtn.setImage(imageInRecordScreenKit(by: "mic1"), for: .normal)
         // 存储录音
         recorderManager.endRecord()
+        isRecording = false
+
         pause()
     }
     
     func cancleRecord(){
         recordBtn.setImage(imageInRecordScreenKit(by: "mic1"), for: .normal)
         recorderManager.cancleRecord()
+        isRecording = false
+        
         pause()
     }
-    @objc func close(){
+    @objc func closePage(){
         pause()
         closeActionHandle?()
     }
@@ -283,25 +343,19 @@ public class BFRecordScreenController: BFBaseViewController {
     }
     
     @objc func playVideo(btn:UIButton){
-        btn.isSelected = !btn.isSelected
-        BFLog(1, message: "点击")
-        if btn.isSelected{
-            play()
-
-        }else{
-            pause()
-        }
+        btn.isSelected ? pause() : play()
     }
 
     @objc public func sliderTouchBegan(sender _: UISlider) {
-//        isDragingProgressSlder = true
-//        pause()
+        isDragingProgressSlder = true
+        pause()
     }
 
     @objc public func sliderTouchEnded(sender: UISlider) {
-//        changeProgress(progress: sender.value)
-//        isDragingProgressSlder = false
-//        play()
+        changeProgress(progress: sender.value)
+        isDragingProgressSlder = false
+        currentPlayRecordIndex = -1
+
     }
     
     // MARK: - 权限申请
@@ -350,29 +404,88 @@ public class BFRecordScreenController: BFBaseViewController {
     }
     
     // MARK: - 音视频处理
-    func playRecord(at duration:CMTime){
-        if recordList.count > 0, let player = try? AVAudioPlayer(contentsOf: URL(fileURLWithPath: (recordList.first?.wavFilePath)!)) {
-            self.recordPlayer = player
-            self.recordPlayer.volume = 1
-            self.recordPlayer.play()
-        }else{
-            self.recordPlayer.pause()
+    func playRecord(at currentT:CMTime){
+        let (shouldPlayRecordIndex, recordedAudio) = recordList.enumerated().first { model in
+            model.1.endTime > CMTimeGetSeconds(currentT)
+        } ?? (-1, nil)
+        
+        guard let recordedAudio = recordedAudio else {
+            return
+        }
+        
+        BFLog(1, message: "当前时间:\(CMTimeGetSeconds(currentT)), 找到的音频:\(recordedAudio.startTime), \(recordedAudio.endTime)")
+        
+        // 创建播放器
+        if self.recordPlayer == nil || (self.recordPlayer?.currentItem?.asset as? AVURLAsset)?.url.lastPathComponent != (recordedAudio.wavFilePath as NSString).lastPathComponent {
+            self.recordPlayer?.pause()
+            self.recordPlayer = AVPlayer(url: URL(fileURLWithPath: recordedAudio.wavFilePath))
+            self.recordPlayer!.volume = 1
+            //                self.recordPlayer?.prepareToPlay()
+            currentPlayRecordIndex = -1
+            hadPrepareToPlayRecord = false
+            BFLog(1, message: "录音播放器初始化(有时候不准)")
         }
+        
+        synced(currentPlayRecordIndex) {
+            if !hadPrepareToPlayRecord
+                && CMTimeGetSeconds(currentT) >= recordedAudio.startTime
+                && CMTimeGetSeconds(currentT) <= recordedAudio.endTime - 0.2 // 这个条件是避免录音结束后有小幅度回退导致播放最新录音
+            {
+                // 应当开始播放了
+                // 两个逻辑:如果在播,则跳过;如果暂停拖动到中间,则seek
+                if currentPlayRecordIndex == -1 {
+                    let second = CMTimeGetSeconds(currentT) - recordedAudio.startTime
+                    recordPlayer?.seek(to: CMTime(value: CMTimeValue(second), timescale: 100), toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000), completionHandler: {[weak self] finished in
+                        if finished && (self?.isNormalPlaying ?? false) {
+                            DispatchQueue.main.async {[weak self] in
+                                self?.recordPlayer?.play()
+                            }
+                        }
+                    })
+                    currentPlayRecordIndex = shouldPlayRecordIndex
+                    hadPrepareToPlayRecord = true
+                    BFLog(1, message: "录音开始播放2, \(second), \(CMTimeGetSeconds(recordPlayer?.currentItem?.duration ?? .zero))")
+                }
+            }
+            
+        }
+        BFLog(1, message: "应当播放:\(shouldPlayRecordIndex), 当前播放:\(currentPlayRecordIndex)")
+//        if let recordedAudio = recordedAudio {
+//
+//
+//            if shouldPlayRecordIndex != currentPlayRecordIndex {
+//                // 设置新的播放资源
+//
+////                self.recordPlayer.delegate = self
+//                self.recordPlayer.play()
+//
+//            } else {
+//                // 更新播放进度
+//                let second = CMTimeGetSeconds(duration) - recordedAudio.startTime
+//                self.recordPlayer.seek(to: CMTime(seconds: second, preferredTimescale: 25), toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000))
+//            }
+//        }
     }
     
     func play(){
-        cShowHUB(superView: nil, msg: "开始播放")
-        assetPlayer?.volume = 0.5
+        BFLog(1, message: "开始播放")
+        assetPlayer?.volume = 0.2
         movie?.startProcessing()
-        assetPlayer?.play()
-        playRecord(at: CMTime.zero)
+        isNormalPlaying = true
+        let second = assetPlayer?.currentItem?.currentTime()
+        assetPlayer?.seek(to: second ?? CMTime.zero, toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000), completionHandler: {[weak self] finished in
+            if finished {
+                self?.assetPlayer?.play()
+            }
+        })
     }
     
     func pause(){
-        cShowHUB(superView: nil, msg: "暂停播放")
+        BFLog(1, message: "暂停播放")
         movie?.cancelProcessing()
         assetPlayer?.pause()
-        recordPlayer.pause()
+        recordPlayer?.pause()
+        isNormalPlaying = false
     }
     
     func fetchVideo(){
@@ -466,14 +579,18 @@ public class BFRecordScreenController: BFBaseViewController {
             assetPlayer?.replaceCurrentItem(with: item)
         }else {
             assetPlayer = AVPlayer(playerItem: item)
-            avplayerTimeObserver = assetPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 10), queue: DispatchQueue.global()) {[weak self] time in
+            avplayerTimeObserver = assetPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 100), queue: DispatchQueue.global()) {[weak self] time in
              //    进度监控
+                self?.currentAssetProgress = time
                 BFLog(1, message: "curr:\(CMTimeGetSeconds(time))")
                 if CMTimeGetSeconds(item.duration) > 0, !(self?.isDragingProgressSlder ?? false) {
                     DispatchQueue.main.async { [weak self] in
                         self?.progessSilde.value = Float(CMTimeGetSeconds(time) / CMTimeGetSeconds(item.duration))
+                        self?.progreddL.text = String(format: "%.2f / %.2f", CMTimeGetSeconds(time), CMTimeGetSeconds(item.duration))
                     }
                 }
+                // 播放对应的录音音频
+                self?.playRecord(at: time)
             } as? NSKeyValueObservation
         }
 
@@ -482,6 +599,7 @@ public class BFRecordScreenController: BFBaseViewController {
             BFLog(message: "AVPlayerItemDidPlayToEndTime = \(notify)")
             self?.assetPlayer?.seek(to: CMTime.zero)
             self?.playBtn.isSelected = false
+            self?.currentPlayRecordIndex = -1
         }
     }
 
@@ -499,28 +617,49 @@ public class BFRecordScreenController: BFBaseViewController {
     //MARK: - 录音对应图像绘制
     
     func changeProgress(progress:Float) {
-        if let item = assetPlayer?.currentItem {
-            let duration = CMTimeGetSeconds(item.duration)
-            item.seek(to: CMTime(value: CMTimeValue(progress * Float(duration) * 100), timescale: 100)) { finished in
+        if let duration = assetPlayer?.currentItem?.duration {
+            assetPlayer!.seek(to: CMTime(value: CMTimeValue(progress * Float(CMTimeGetSeconds(duration)) * 100), timescale: 100), toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000)) {[weak self] finished in
                 if finished{
                     BFLog(1, message: "拖动成功")
+                    self?.movie?.startProcessing()
                 }
             }
         }
     }
     
-    func drewRecordProgessLable(){
-        
+    func drawOrUpdateRecordProgessLable(){
+        progessSildeBackV.subviews.forEach { vv in
+            vv.removeFromSuperview()
+        }
+        DispatchQueue.main.async {[weak self] in
+            if let totalDur = self?.asset?.duration, totalDur > 0, let list = self?.recordList {
+                let width = self?.progessSildeBackV.width ?? 0
+                let height = self?.progessSildeBackV.height ?? 0
+                list.forEach { model in
+                    let lineV = UIView(frame: CGRect(x: model.startTime * width / totalDur , y: 0, width: (model.endTime - model.startTime) * width / totalDur, height: height))
+                    lineV.backgroundColor = UIColor.hexColor(hexadecimal: "#28BE67")
+                    self?.progessSildeBackV.addSubview(lineV)
+                }
+            }
+        }
     }
 }
 
 extension BFRecordScreenController:GPUImageMovieDelegate {
     public func didCompletePlayingMovie(){
         BFLog(1, message: "播放结束")
-        
+        currentPlayRecordIndex = -1
     }
 }
 
 extension BFRecordScreenController:AVAudioRecorderDelegate {
-    
+    public func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
+        BFLog(1, message: "录音结束")
+    }
+}
+
+extension BFRecordScreenController : AVAudioPlayerDelegate {
+    public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
+        BFLog(1, message: "录音播放结束")
+    }
 }

+ 9 - 5
Example/BFRecordScreenKit.xcodeproj/project.pbxproj

@@ -27,7 +27,7 @@
 		4A426DA6274FA4E000B3733B /* IntroduceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroduceController.swift; sourceTree = "<group>"; };
 		4A96F093274CF8DC008657DA /* PhotoVideoListController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoVideoListController.swift; sourceTree = "<group>"; };
 		5E394037E3C86B6D51A62719 /* Pods_BFRecordScreenKit_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BFRecordScreenKit_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
-		607FACD01AFB9204008FA782 /* 开讲.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "开讲.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		607FACD01AFB9204008FA782 /* Introduce.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Introduce.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
@@ -78,7 +78,7 @@
 		607FACD11AFB9204008FA782 /* Products */ = {
 			isa = PBXGroup;
 			children = (
-				607FACD01AFB9204008FA782 /* 开讲.app */,
+				607FACD01AFB9204008FA782 /* Introduce.app */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -166,7 +166,7 @@
 			);
 			name = BFRecordScreenKit_Example;
 			productName = BFRecordScreenKit;
-			productReference = 607FACD01AFB9204008FA782 /* 开讲.app */;
+			productReference = 607FACD01AFB9204008FA782 /* Introduce.app */;
 			productType = "com.apple.product-type.application";
 		};
 /* End PBXNativeTarget section */
@@ -251,6 +251,7 @@
 				"${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework",
 				"${BUILT_PRODUCTS_DIR}/AliyunOSSiOS/AliyunOSSiOS.framework",
 				"${BUILT_PRODUCTS_DIR}/BFCommonKit/BFCommonKit.framework",
+				"${BUILT_PRODUCTS_DIR}/BFLogger/BFLogger.framework",
 				"${BUILT_PRODUCTS_DIR}/BFNetRequestKit/BFNetRequestKit.framework",
 				"${BUILT_PRODUCTS_DIR}/BFUIKit/BFUIKit.framework",
 				"${BUILT_PRODUCTS_DIR}/FDFullscreenPopGesture/FDFullscreenPopGesture.framework",
@@ -274,6 +275,7 @@
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AliyunOSSiOS.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BFCommonKit.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BFLogger.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BFNetRequestKit.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BFUIKit.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FDFullscreenPopGesture.framework",
@@ -468,10 +470,11 @@
 				INFOPLIST_KEY_CFBundleDisplayName = "开讲";
 				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				MARKETING_VERSION = 1.0;
 				MODULE_NAME = ExampleApp;
 				PRODUCT_BUNDLE_IDENTIFIER = com.piaoquan.introduce;
 				PRODUCT_MODULE_NAME = "$(TARGET_NAME)";
-				PRODUCT_NAME = "开讲";
+				PRODUCT_NAME = Introduce;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};
@@ -488,10 +491,11 @@
 				INFOPLIST_KEY_CFBundleDisplayName = "开讲";
 				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				MARKETING_VERSION = 1.0;
 				MODULE_NAME = ExampleApp;
 				PRODUCT_BUNDLE_IDENTIFIER = com.piaoquan.introduce;
 				PRODUCT_MODULE_NAME = "$(TARGET_NAME)";
-				PRODUCT_NAME = "开讲";
+				PRODUCT_NAME = Introduce;
 				SWIFT_SWIFT3_OBJC_INFERENCE = Default;
 				SWIFT_VERSION = 4.0;
 			};

+ 16 - 0
Example/BFRecordScreenKit.xcodeproj/xcshareddata/xcschemes/BFRecordScreenKit-Example.xcscheme

@@ -15,7 +15,11 @@
             <BuildableReference
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "607FACCF1AFB9204008FA782"
+<<<<<<< HEAD
                BuildableName = "&#x5f00;&#x8bb2;.app"
+=======
+               BuildableName = "Introduce.app"
+>>>>>>> 2387598f1bd7d829d99e17dcf8480a17770bff02
                BlueprintName = "BFRecordScreenKit_Example"
                ReferencedContainer = "container:BFRecordScreenKit.xcodeproj">
             </BuildableReference>
@@ -45,7 +49,11 @@
          <BuildableReference
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "607FACCF1AFB9204008FA782"
+<<<<<<< HEAD
             BuildableName = "&#x5f00;&#x8bb2;.app"
+=======
+            BuildableName = "Introduce.app"
+>>>>>>> 2387598f1bd7d829d99e17dcf8480a17770bff02
             BlueprintName = "BFRecordScreenKit_Example"
             ReferencedContainer = "container:BFRecordScreenKit.xcodeproj">
          </BuildableReference>
@@ -78,7 +86,11 @@
          <BuildableReference
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "607FACCF1AFB9204008FA782"
+<<<<<<< HEAD
             BuildableName = "&#x5f00;&#x8bb2;.app"
+=======
+            BuildableName = "Introduce.app"
+>>>>>>> 2387598f1bd7d829d99e17dcf8480a17770bff02
             BlueprintName = "BFRecordScreenKit_Example"
             ReferencedContainer = "container:BFRecordScreenKit.xcodeproj">
          </BuildableReference>
@@ -95,7 +107,11 @@
          <BuildableReference
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "607FACCF1AFB9204008FA782"
+<<<<<<< HEAD
             BuildableName = "&#x5f00;&#x8bb2;.app"
+=======
+            BuildableName = "Introduce.app"
+>>>>>>> 2387598f1bd7d829d99e17dcf8480a17770bff02
             BlueprintName = "BFRecordScreenKit_Example"
             ReferencedContainer = "container:BFRecordScreenKit.xcodeproj">
          </BuildableReference>

+ 2 - 3
Example/BFRecordScreenKit/Info.plist

@@ -11,11 +11,11 @@
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<key>CFBundleName</key>
-	<string>$(PRODUCT_NAME)</string>
+	<string>开讲</string>
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>1.0</string>
+	<string>$(MARKETING_VERSION)</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
@@ -39,7 +39,6 @@
 	<key>UISupportedInterfaceOrientations</key>
 	<array>
 		<string>UIInterfaceOrientationPortrait</string>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
 	</array>
 </dict>
 </plist>

+ 45 - 1
Example/Podfile

@@ -6,6 +6,18 @@ source 'https://git.yishihui.com/iOS/BFSpecs.git'
 
 target 'BFRecordScreenKit_Example' do
   pod 'BFRecordScreenKit', :path => '../'
+
+## Pods-for-AppStore
+#  pod 'BFCommonKit',           '1.4.9'
+#  pod 'BFNetRequestKit',       '0.2.3'
+#  pod 'BFUIKit',               '0.1.1'
+#  pod 'BFMaterialKit',         '0.1.6'
+#  pod 'BFFramework',           '1.0.7'
+#  pod 'BFVideoEditKit',        '0.1.0'
+#  pod 'BFAliyunNlsSDK-Swift',  '0.1.0'
+#  pod 'BFLogger',              '0.1.0'
+
+## Pods-for-Archive(Jenkins)
   pod 'BFCommonKit',           :git => 'https://git.yishihui.com/iOS/BFCommonKit.git'
   pod 'BFNetRequestKit',       :git => 'https://git.yishihui.com/iOS/BFNetRequestKit.git'
   pod 'BFUIKit',               :git => 'https://git.yishihui.com/iOS/BFUIKit.git'
@@ -13,6 +25,38 @@ target 'BFRecordScreenKit_Example' do
   pod 'BFFramework',           :git => 'https://git.yishihui.com/iOS/BFFramework.git'
   pod 'BFVideoEditKit',        :git => 'https://git.yishihui.com/iOS/BFVideoEditKit.git'
   pod 'BFAliyunNlsSDK-Swift',  :git => 'https://git.yishihui.com/iOS/BFAliyunNlsSDK-Swift.git'
+  pod 'BFLogger',              :git => 'https://git.yishihui.com/iOS/BFLogger.git'
+
+## ak:Pods-for-testing
+#  pod 'BFCommonKit',           :path => '/Users/ak/Desktop/TZFrameworks/BFCommonKit/'
+#  pod 'BFNetRequestKit',       :path => '/Users/ak/Desktop/TZFrameworks/BFNetRequestKit/'
+#  pod 'BFUIKit',               :path => '/Users/ak/Desktop/TZFrameworks/BFUIKit/'
+#  pod 'BFMaterialKit',         :path => '/Users/ak/Desktop/TZFrameworks/BFMaterialKit/'
+#  pod 'BFFramework',           :path => '/Users/ak/Desktop/TZFrameworks/BFFramework/'
+#  pod 'BFVideoEditKit',        :path => '/Users/ak/Desktop/TZFrameworks/BFVideoEditKit/'
+#  pod 'BFAliyunNlsSDK-Swift',  :path => '/Users/ak/Desktop/TZFrameworks/BFAliyunNlsSDK-Swift/'
+#  pod 'BFLogger',              :path => '/Users/ak/Desktop/TZFrameworks/BFLogger/'
+
+## zq:Pods-for-testing
+#  pod 'BFCommonKit',           :path => '../BFCommonKit/'
+#  pod 'BFNetRequestKit',       :path => '../BFNetRequestKit/'
+#  pod 'BFUIKit',               :path => '../BFUIKit/'
+#  pod 'BFMaterialKit',         :path => '../BFMaterialKit/'
+#  pod 'BFFramework',           :path => '../BFFramework/'
+#  pod 'BFVideoEditKit',        :path => '../BFVideoEditKit/'
+#  pod 'BFAliyunNlsSDK-Swift',  :path => '../BFAliyunNlsSDK-Swift/'
+#  pod 'BFLogger',              :path => '../BFLogger/'
+
+## ww:Pods-for-testing
+#  pod 'BFCommonKit',            :path => '../../../BFCommonKit/Trunk'
+#  pod 'BFNetRequestKit',        :path => '../../../BFNetRequestKit/Trunk'
+#  pod 'BFUIKit',                :path => '../../../BFUIKit/Trunk'
+#  pod 'BFMaterialKit',          :path => '../../../BFMaterialKit/Trunk'
+#  pod 'BFFramework',            :path => '../../../BFFramework/Trunk'
+#  pod 'BFVideoEditKit',         :path => '../../../BFVideoEditKit/Trunk'
+#  pod 'BFAliyunNlsSDK-Swift',   :path => '../../../BFAliyunNlsSDK-Swift/Trunk'
+#  pod 'BFLogger',               :path => '../../../BFLogger/Trunk'
+  
   post_install do |installer|
     installer.pods_project.targets.each do |target|
       #if target.name =="App" || target.name =="App1"
@@ -23,4 +67,4 @@ target 'BFRecordScreenKit_Example' do
     end
   end
   
-end
+end

+ 22 - 38
Example/Podfile.lock

@@ -40,6 +40,9 @@ PODS:
     - ObjectMapper (= 4.2.0)
     - TXLiteAVSDK_Player (= 9.3.10765)
     - WechatOpenSDK-Swift (= 1.8.7.1)
+  - BFLogger (0.1.0):
+    - BFCommonKit
+    - BFUIKit
   - BFMaterialKit (0.1.9):
     - BFUIKit
   - BFNetRequestKit (1.0.0):
@@ -129,14 +132,15 @@ PODS:
   - WechatOpenSDK-Swift (1.8.7.1)
 
 DEPENDENCIES:
-  - BFAliyunNlsSDK-Swift (from `https://git.yishihui.com/iOS/BFAliyunNlsSDK-Swift.git`)
-  - BFCommonKit (from `https://git.yishihui.com/iOS/BFCommonKit.git`)
-  - BFFramework (from `https://git.yishihui.com/iOS/BFFramework.git`)
-  - BFMaterialKit (from `https://git.yishihui.com/iOS/BFMaterialKit.git`)
-  - BFNetRequestKit (from `https://git.yishihui.com/iOS/BFNetRequestKit.git`)
+  - BFAliyunNlsSDK-Swift (from `../../../BFAliyunNlsSDK-Swift/Trunk`)
+  - BFCommonKit (from `../../../BFCommonKit/Trunk`)
+  - BFFramework (from `../../../BFFramework/Trunk`)
+  - BFLogger (from `../../../BFLogger/Trunk`)
+  - BFMaterialKit (from `../../../BFMaterialKit/Trunk`)
+  - BFNetRequestKit (from `../../../BFNetRequestKit/Trunk`)
   - BFRecordScreenKit (from `../`)
-  - BFUIKit (from `https://git.yishihui.com/iOS/BFUIKit.git`)
-  - BFVideoEditKit (from `https://git.yishihui.com/iOS/BFVideoEditKit.git`)
+  - BFUIKit (from `../../../BFUIKit/Trunk`)
+  - BFVideoEditKit (from `../../../BFVideoEditKit/Trunk`)
 
 SPEC REPOS:
   https://github.com/CocoaPods/Specs.git:
@@ -163,44 +167,23 @@ SPEC REPOS:
 
 EXTERNAL SOURCES:
   BFAliyunNlsSDK-Swift:
-    :git: https://git.yishihui.com/iOS/BFAliyunNlsSDK-Swift.git
+    :path: "../../../BFAliyunNlsSDK-Swift/Trunk"
   BFCommonKit:
-    :git: https://git.yishihui.com/iOS/BFCommonKit.git
+    :path: "../../../BFCommonKit/Trunk"
   BFFramework:
-    :git: https://git.yishihui.com/iOS/BFFramework.git
+    :path: "../../../BFFramework/Trunk"
+  BFLogger:
+    :path: "../../../BFLogger/Trunk"
   BFMaterialKit:
-    :git: https://git.yishihui.com/iOS/BFMaterialKit.git
+    :path: "../../../BFMaterialKit/Trunk"
   BFNetRequestKit:
-    :git: https://git.yishihui.com/iOS/BFNetRequestKit.git
+    :path: "../../../BFNetRequestKit/Trunk"
   BFRecordScreenKit:
     :path: "../"
   BFUIKit:
-    :git: https://git.yishihui.com/iOS/BFUIKit.git
-  BFVideoEditKit:
-    :git: https://git.yishihui.com/iOS/BFVideoEditKit.git
-
-CHECKOUT OPTIONS:
-  BFAliyunNlsSDK-Swift:
-    :commit: 5d4b25b98f5294bc1dae7a5c75542b85cabf59de
-    :git: https://git.yishihui.com/iOS/BFAliyunNlsSDK-Swift.git
-  BFCommonKit:
-    :commit: 8d5f57b0113d48867f9d1d63aa5d9777baa841b6
-    :git: https://git.yishihui.com/iOS/BFCommonKit.git
-  BFFramework:
-    :commit: 1be8e452b2aed3df07093cc4a3949d3616ebd42d
-    :git: https://git.yishihui.com/iOS/BFFramework.git
-  BFMaterialKit:
-    :commit: 83b6088afd809c0416cc1f0bd27462a880c0e1d7
-    :git: https://git.yishihui.com/iOS/BFMaterialKit.git
-  BFNetRequestKit:
-    :commit: 5d98c4f78849413c21e8cb7117a3b4cc243b4224
-    :git: https://git.yishihui.com/iOS/BFNetRequestKit.git
-  BFUIKit:
-    :commit: 15b17c31208508931bbe46d90aeb177a907d634b
-    :git: https://git.yishihui.com/iOS/BFUIKit.git
+    :path: "../../../BFUIKit/Trunk"
   BFVideoEditKit:
-    :commit: 1e6acf7acc57fca3f73813d93b4ee767dfc5549d
-    :git: https://git.yishihui.com/iOS/BFVideoEditKit.git
+    :path: "../../../BFVideoEditKit/Trunk"
 
 SPEC CHECKSUMS:
   Alamofire: f3b09a368f1582ab751b3fff5460276e0d2cf5c9
@@ -208,6 +191,7 @@ SPEC CHECKSUMS:
   BFAliyunNlsSDK-Swift: 44049d173720cf858729d3b011c07e0c33c90fd2
   BFCommonKit: fbebd7d46eaa7adaf5311aae2230b68ab5e99788
   BFFramework: 2c44a33844e1a737c4f581b5c4949a9298867e5e
+  BFLogger: a286144e7dcdc20d3afc79deafed491aa0ac4306
   BFMaterialKit: a10f33e7748689a3eeffff3b18df9c350241ba8d
   BFNetRequestKit: 6b200205bd1a9491c04f5a3e95301d37a547f96b
   BFRecordScreenKit: ebe9e2888a1a139274c807cf28171ca8112da9a4
@@ -232,6 +216,6 @@ SPEC CHECKSUMS:
   TXLiteAVSDK_Player: 2b60edf893a8e82165a5e4b961a6cb347b10be4a
   WechatOpenSDK-Swift: 18a8f7b12e745c30acc013f72a9f8a25aad6e216
 
-PODFILE CHECKSUM: f78a6f6a0d08a98dcba06d4683e82c279e6b7031
+PODFILE CHECKSUM: 6d008d3366f807ead4b6cc60ddc20baa0eed54ac
 
 COCOAPODS: 1.11.2