瀏覽代碼

声音分段播放

harry 3 年之前
父節點
當前提交
96d00e68e3

+ 45 - 2
BFRecordScreenKit/Classes/BFRecordExport.swift.swift

@@ -3,7 +3,7 @@
 //  BFRecordScreenKit
 //  BFRecordScreenKit
 //
 //
 //  Created by 胡志强 on 2021/11/25.
 //  Created by 胡志强 on 2021/11/25.
-//
+//  录屏视频导出
 
 
 import Foundation
 import Foundation
 import AVFoundation
 import AVFoundation
@@ -66,10 +66,53 @@ public class BFRecordExport {
     enum DispatchError: Error {
     enum DispatchError: Error {
         case timeout
         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]?) {
     func beginExport(videoStickers:[PQEditVisionTrackMaterialsModel], audioAsset: [AVURLAsset]?) {
         // 输出视频地址
         // 输出视频地址
+//        exprotVideo()
+//        return;
         var outPutMP4Path = exportVideosDirectory
         var outPutMP4Path = exportVideosDirectory
         if !directoryIsExists(dicPath: outPutMP4Path) {
         if !directoryIsExists(dicPath: outPutMP4Path) {
             createDirectory(path: outPutMP4Path)
             createDirectory(path: outPutMP4Path)
@@ -194,7 +237,7 @@ public class BFRecordExport {
         self.asset?.tracks.forEach({ track in
         self.asset?.tracks.forEach({ track in
             if track.mediaType == .video{
             if track.mediaType == .video{
                 let realSize = __CGSizeApplyAffineTransform(track.naturalSize, track.preferredTransform)
                 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(message: "count == \(count)")
             
             
         }
         }
-
+        BFLog(1, message: "开始录制")
         audioRecorder?.startRecord()
         audioRecorder?.startRecord()
         beginRecordTime = Date()
         beginRecordTime = Date()
 
 
@@ -108,16 +108,16 @@ class BFRecordManager {
 
 
             let duration = Date().timeIntervalSince( strongSelf.beginRecordTime)
             let duration = Date().timeIntervalSince( strongSelf.beginRecordTime)
             if isSuccess && !isCancel && duration > 1 {
             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")
                 let noiseFilePath = url.replacingOccurrences(of: ".wav", with: "_noise_\(1)_.wav")
                 BFLog(1, message: "降噪后地址:\(noiseFilePath)")
                 BFLog(1, message: "降噪后地址:\(noiseFilePath)")
                 NXNoiseReduction().denoise(url, outFile: 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))
 //                strongSelf.recorderPart.cacheRecorderFiles.append(URL(fileURLWithPath: noiseFilePath))

+ 126 - 48
BFRecordScreenKit/Classes/BFRecordScreenController.swift

@@ -20,17 +20,21 @@ public class BFRecordScreenController: BFBaseViewController {
     
     
     // MARK: - 录制参数
     // MARK: - 录制参数
     public var asset:PHAsset?
     public var asset:PHAsset?
-    
+//    var shouldPlayRecordIndex:Int = -1          // 当前应该播放的录音资源序号
+    var currentPlayRecordIndex:Int = -1         // 当前正在播放的录音资源序号
+    var isRecording = false                     // 是否正在录音
+    var isNormalPlaying = false {               // 是否正在录音
+        didSet{
+            playBtn.isSelected = isNormalPlaying
+        }
+    }
     // 视频素材
     // 视频素材
     public var avasset:AVURLAsset?
     public var avasset:AVURLAsset?
     public var recordList:[PQVoiceModel] = [PQVoiceModel]()
     public var recordList:[PQVoiceModel] = [PQVoiceModel]()
     var assetPlayer:AVPlayer?       // 原视频音频播放器
     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 movie :GPUImageMovie?       // 视频预览
     var playView :GPUImageView?     // 视频展示视图
     var playView :GPUImageView?     // 视频展示视图
     var isDragingProgressSlder : Bool = false // 是否在拖动进度条
     var isDragingProgressSlder : Bool = false // 是否在拖动进度条
@@ -53,15 +57,17 @@ public class BFRecordScreenController: BFBaseViewController {
         manager.endRecordHandle = {[weak self] (isTimeout, model) in
         manager.endRecordHandle = {[weak self] (isTimeout, model) in
             if FileManager.default.fileExists(atPath: model?.wavFilePath ?? ""){
             if FileManager.default.fileExists(atPath: model?.wavFilePath ?? ""){
                 // 加入到语音数组里
                 // 加入到语音数组里
+                model?.endTime = CMTimeGetSeconds(self?.assetPlayer?.currentItem?.currentTime() ?? CMTime.zero)
                 while let m = self?.recordList.last{
                 while let m = self?.recordList.last{
-                    if m.startTime < model!.startTime {
+                    if model!.startTime < m.startTime {
                         self?.recordList.removeLast()
                         self?.recordList.removeLast()
-                    }else if m.endTime < model!.startTime {
+                    }else if m.endTime > model!.startTime {
                         m.endTime = model!.startTime
                         m.endTime = model!.startTime
                     }else{
                     }else{
                         break
                         break
                     }
                     }
                 }
                 }
+                BFLog(1, message: "添加录音文件:\(model?.startTime) -- \(model?.endTime)")
                 self?.recordList.append(model!)
                 self?.recordList.append(model!)
                 self?.drewRecordProgessLable()
                 self?.drewRecordProgessLable()
             }
             }
@@ -75,6 +81,16 @@ public class BFRecordScreenController: BFBaseViewController {
     var touchStart:CGPoint = CGPoint(x: 0, y: 0)
     var touchStart:CGPoint = CGPoint(x: 0, y: 0)
     var avplayerTimeObserver: NSKeyValueObservation?
     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 = {
     lazy var playBtn:UIButton = {
         let btn = UIButton(frame: view.bounds)
         let btn = UIButton(frame: view.bounds)
         btn.addTarget(self, action: #selector(playVideo(btn:)), for: .touchUpInside)
         btn.addTarget(self, action: #selector(playVideo(btn:)), for: .touchUpInside)
@@ -126,7 +142,7 @@ public class BFRecordScreenController: BFBaseViewController {
     lazy var closeBtn:UIButton = {
     lazy var closeBtn:UIButton = {
         let btn = UIButton(type: .custom)
         let btn = UIButton(type: .custom)
         btn.setImage(imageInRecordScreenKit(by: "xx"), for: .normal)
         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
         return btn
     }()
     }()
     
     
@@ -159,7 +175,7 @@ public class BFRecordScreenController: BFBaseViewController {
         avplayerTimeObserver?.invalidate()
         avplayerTimeObserver?.invalidate()
         recorderManager.stopRecord(isCancel: true)
         recorderManager.stopRecord(isCancel: true)
         assetPlayer?.pause()
         assetPlayer?.pause()
-        recordPlayer.pause()
+        recordPlayer?.pause()
         
         
     }
     }
     
     
@@ -181,7 +197,8 @@ public class BFRecordScreenController: BFBaseViewController {
         
         
         view.addSubview(playBtn)
         view.addSubview(playBtn)
         view.addSubview(bottomeView)
         view.addSubview(bottomeView)
-        view.addSubview(toolV)
+        view.addSubview(progreddL)
+//        view.addSubview(toolV)
         bottomeView.addSubview(recordBtn)
         bottomeView.addSubview(recordBtn)
         bottomeView.addSubview(progessSilde)
         bottomeView.addSubview(progessSilde)
         bottomeView.addSubview(closeBtn)
         bottomeView.addSubview(closeBtn)
@@ -227,9 +244,9 @@ public class BFRecordScreenController: BFBaseViewController {
     
     
     // MARK: - 按钮事件响应
     // MARK: - 按钮事件响应
     
     
-    // 觸發拖曳手勢後 執行的動
+    // 触发拖曳手势后,执行的动
     @objc func pan(recognizer: UIPanGestureRecognizer) {
     @objc func pan(recognizer: UIPanGestureRecognizer) {
-        // 置 UIView 新的位置
+        // 置 UIView 新的位置
         if !checkStatus(show: false) {
         if !checkStatus(show: false) {
             return
             return
         }
         }
@@ -271,6 +288,8 @@ public class BFRecordScreenController: BFBaseViewController {
     @objc func startRecord(btn:UIButton){
     @objc func startRecord(btn:UIButton){
         btn.setImage(imageInRecordScreenKit(by: "mic2"), for: .normal)
         btn.setImage(imageInRecordScreenKit(by: "mic2"), for: .normal)
         BFLog(1, message: "start \(UIControl.Event.touchDown)")
         BFLog(1, message: "start \(UIControl.Event.touchDown)")
+        pause()
+
         let model = PQVoiceModel()
         let model = PQVoiceModel()
         model.startTime = CMTimeGetSeconds(assetPlayer?.currentItem?.currentTime() ?? CMTime.zero)
         model.startTime = CMTimeGetSeconds(assetPlayer?.currentItem?.currentTime() ?? CMTime.zero)
         recorderManager.voiceModel? = model
         recorderManager.voiceModel? = model
@@ -278,21 +297,26 @@ public class BFRecordScreenController: BFBaseViewController {
         movie?.startProcessing()
         movie?.startProcessing()
         assetPlayer?.volume = 0
         assetPlayer?.volume = 0
         assetPlayer?.play()
         assetPlayer?.play()
+        isRecording = true
     }
     }
     
     
     @objc func endRecord(btn:UIButton){
     @objc func endRecord(btn:UIButton){
         recordBtn.setImage(imageInRecordScreenKit(by: "mic1"), for: .normal)
         recordBtn.setImage(imageInRecordScreenKit(by: "mic1"), for: .normal)
         // 存储录音
         // 存储录音
         recorderManager.endRecord()
         recorderManager.endRecord()
+        isRecording = false
+
         pause()
         pause()
     }
     }
     
     
     func cancleRecord(){
     func cancleRecord(){
         recordBtn.setImage(imageInRecordScreenKit(by: "mic1"), for: .normal)
         recordBtn.setImage(imageInRecordScreenKit(by: "mic1"), for: .normal)
         recorderManager.cancleRecord()
         recorderManager.cancleRecord()
+        isRecording = false
+        
         pause()
         pause()
     }
     }
-    @objc func close(){
+    @objc func closePage(){
         pause()
         pause()
         closeActionHandle?()
         closeActionHandle?()
     }
     }
@@ -302,25 +326,19 @@ public class BFRecordScreenController: BFBaseViewController {
     }
     }
     
     
     @objc func playVideo(btn:UIButton){
     @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) {
     @objc public func sliderTouchBegan(sender _: UISlider) {
-//        isDragingProgressSlder = true
-//        pause()
+        isDragingProgressSlder = true
+        pause()
     }
     }
 
 
     @objc public func sliderTouchEnded(sender: UISlider) {
     @objc public func sliderTouchEnded(sender: UISlider) {
-//        changeProgress(progress: sender.value)
-//        isDragingProgressSlder = false
-//        play()
+        changeProgress(progress: sender.value)
+        isDragingProgressSlder = false
+        currentPlayRecordIndex = -1
+
     }
     }
     
     
     // MARK: - 权限申请
     // MARK: - 权限申请
@@ -369,35 +387,83 @@ public class BFRecordScreenController: BFBaseViewController {
     }
     }
     
     
     // MARK: - 音视频处理
     // 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 CMTimeGetSeconds(currentT) >= recordedAudio.startTime && !hadPrepareToPlayRecord{
+                // 应当开始播放了
+                // 两个逻辑:如果在播,则跳过;如果暂停拖动到中间,则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 recordPlayer] finished in
+                        if finished {
+                            recordPlayer?.play()
+                        }
+                    })
+                    currentPlayRecordIndex = shouldPlayRecordIndex
+                    hadPrepareToPlayRecord = true
+                    BFLog(1, message: "录音开始播放2 \(second), \(recordPlayer?.currentItem?.duration)")
+                }
+            }
+            
+        }
+        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(){
     func play(){
-        cShowHUB(superView: nil, msg: "开始播放")
-        assetPlayer?.volume = 0.5
+        BFLog(1, message: "开始播放")
+        assetPlayer?.volume = 0.02
         movie?.startProcessing()
         movie?.startProcessing()
-        
+        isNormalPlaying = true
         let second = assetPlayer?.currentItem?.currentTime()
         let second = assetPlayer?.currentItem?.currentTime()
-        assetPlayer?.seek(to: second ?? CMTime.zero, toleranceBefore: .zero, toleranceAfter: .zero, completionHandler: {[weak self] finished in
+        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 {
             if finished {
                 self?.assetPlayer?.play()
                 self?.assetPlayer?.play()
             }
             }
         })
         })
-        playRecord(at: CMTime.zero)
     }
     }
     
     
     func pause(){
     func pause(){
-        cShowHUB(superView: nil, msg: "暂停播放")
+        BFLog(1, message: "暂停播放")
         movie?.cancelProcessing()
         movie?.cancelProcessing()
         assetPlayer?.pause()
         assetPlayer?.pause()
-        recordPlayer.pause()
+        recordPlayer?.pause()
+        isNormalPlaying = false
     }
     }
     
     
     func fetchVideo(){
     func fetchVideo(){
@@ -491,14 +557,17 @@ public class BFRecordScreenController: BFBaseViewController {
             assetPlayer?.replaceCurrentItem(with: item)
             assetPlayer?.replaceCurrentItem(with: item)
         }else {
         }else {
             assetPlayer = AVPlayer(playerItem: item)
             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
              //    进度监控
              //    进度监控
                 BFLog(1, message: "curr:\(CMTimeGetSeconds(time))")
                 BFLog(1, message: "curr:\(CMTimeGetSeconds(time))")
                 if CMTimeGetSeconds(item.duration) > 0, !(self?.isDragingProgressSlder ?? false) {
                 if CMTimeGetSeconds(item.duration) > 0, !(self?.isDragingProgressSlder ?? false) {
                     DispatchQueue.main.async { [weak self] in
                     DispatchQueue.main.async { [weak self] in
                         self?.progessSilde.value = Float(CMTimeGetSeconds(time) / CMTimeGetSeconds(item.duration))
                         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
             } as? NSKeyValueObservation
         }
         }
 
 
@@ -507,6 +576,7 @@ public class BFRecordScreenController: BFBaseViewController {
             BFLog(message: "AVPlayerItemDidPlayToEndTime = \(notify)")
             BFLog(message: "AVPlayerItemDidPlayToEndTime = \(notify)")
             self?.assetPlayer?.seek(to: CMTime.zero)
             self?.assetPlayer?.seek(to: CMTime.zero)
             self?.playBtn.isSelected = false
             self?.playBtn.isSelected = false
+            self?.currentPlayRecordIndex = -1
         }
         }
     }
     }
 
 
@@ -524,11 +594,11 @@ public class BFRecordScreenController: BFBaseViewController {
     //MARK: - 录音对应图像绘制
     //MARK: - 录音对应图像绘制
     
     
     func changeProgress(progress:Float) {
     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{
                 if finished{
                     BFLog(1, message: "拖动成功")
                     BFLog(1, message: "拖动成功")
+                    self?.movie?.startProcessing()
                 }
                 }
             }
             }
         }
         }
@@ -542,10 +612,18 @@ public class BFRecordScreenController: BFBaseViewController {
 extension BFRecordScreenController:GPUImageMovieDelegate {
 extension BFRecordScreenController:GPUImageMovieDelegate {
     public func didCompletePlayingMovie(){
     public func didCompletePlayingMovie(){
         BFLog(1, message: "播放结束")
         BFLog(1, message: "播放结束")
-        
+        currentPlayRecordIndex = -1
     }
     }
 }
 }
 
 
 extension BFRecordScreenController:AVAudioRecorderDelegate {
 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: "录音播放结束")
+    }
 }
 }