Browse Source

1,使用 avplayer 播放进度方式查找可播放音频

jsonwang 3 years ago
parent
commit
bd8c95079b

+ 38 - 69
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenCameraManager.swift

@@ -32,9 +32,6 @@ class BFRecordScreenCameraManager: BFRecordScreenBaseManager {
     var rendView = GPUImageView()
     var cameraProgressV: BFCameraProgressView?
 
-    var dispatchQueue: DispatchQueue?
-    var dispatchWorkItem: DispatchWorkItem?
-
     override var recordItem: BFRecordItemModel? {
         didSet {
             cameraProgressV?.recordItem = recordItem
@@ -95,6 +92,8 @@ class BFRecordScreenCameraManager: BFRecordScreenBaseManager {
                 wself.currentAssetProgress = CMTime(seconds: (currTime + wself.currPlayTime).seconds, preferredTimescale: 1000)
                 
                 BFLog(message: "当前播放器状态: \(wself.avplayer.timeControlStatus.rawValue) \( wself.currentAssetProgress.seconds)")
+                
+                wself.playRecordVoice()
             }
 //            BFLog(1, message: "拖动 currTime: \(currTime.seconds)")
             DispatchQueue.main.async { [weak self] in
@@ -456,7 +455,16 @@ class BFRecordScreenCameraManager: BFRecordScreenBaseManager {
     }
 
     func playRecordVoice(needPlay: Bool = true) {
-        BFLog(message: "开始查找!!!!currentAssetProgress:\(currentAssetProgress)")
+        //三种状态值
+//        case paused = 0
+//        case waitingToPlayAtSpecifiedRate = 1
+//        case playing = 2
+        if recordPlayer?.timeControlStatus == .playing || recordPlayer?.timeControlStatus == .waitingToPlayAtSpecifiedRate {
+            BFLog( 2,message:"recordPlayer is playering 本次查找无效,有播放任务")
+            return
+        }
+        BFLog(message: "开始查找!!!!当前进度:\(currentAssetProgress.seconds) \(recordPlayer?.timeControlStatus.rawValue ?? -1)")
+ 
         // 播放音频
         var useVoiceStickers = [PQVoiceModel]()
         if (recordItem?.voiceChangeStickers.count ?? 0) > 0 {
@@ -465,16 +473,19 @@ class BFRecordScreenCameraManager: BFRecordScreenBaseManager {
             useVoiceStickers = recordItem?.voiceStickers ?? [PQVoiceModel]()
         }
 
-    
-        BFLog(message: "时间范围: currentAssetProgress\(currentAssetProgress.seconds)")
         let spitTime = (recordItem?.voiceChangeStickers.count ?? 0) > 0 ? 0.0 : 0.333
 
         if let mod = useVoiceStickers.first(where: { m in
             CMTimeCompare(m.startCMTime, currentAssetProgress + CMTime(seconds: spitTime, preferredTimescale: 1000)) <= 0 && CMTimeCompare(m.endCMTime, (currentAssetProgress + CMTime(seconds: spitTime, preferredTimescale: 1000))) > 0
         }) {
         
-            for model in useVoiceStickers {
-                BFLog(message: "时间范围:\(model.startCMTime.seconds) 到 \(model.endCMTime.seconds) \(currentAssetProgress.seconds)")
+            BFLog(message: "找到音频开始时间:\(mod.startCMTime.seconds)结束 \(mod.endCMTime.seconds) currentAssetProgress is \(currentAssetProgress.seconds)")
+ 
+            //当前播放的文件
+            let cureentPalyURlString = (recordPlayer?.currentItem?.asset as? AVURLAsset)?.url.absoluteString ?? ""
+            if(cureentPalyURlString.replacingOccurrences(of: "file://", with: "") == mod.wavFilePath &&  recordPlayer?.timeControlStatus != .playing){
+                BFLog( 2,message:"命中的和播放的文件路径一样? wavFilePath:\(mod.wavFilePath ?? "") recordPlayer Status \(recordPlayer?.timeControlStatus.rawValue ?? -1)")
+                return
             }
             recordPlayer?.replaceCurrentItem(with: AVPlayerItem(url: URL(fileURLWithPath: mod.wavFilePath)))
             let tt = currentAssetProgress - mod.startCMTime
@@ -491,6 +502,21 @@ class BFRecordScreenCameraManager: BFRecordScreenBaseManager {
                 }
                 BFLog(message: "finishedre \(finishedre) 当前时间\(self.currentAssetProgress.seconds)")
             }
+       
+            NotificationCenter.default.addObserver(forName: .AVPlayerItemNewErrorLogEntry, object: recordPlayer?.currentItem, queue: .main) { notify in
+                BFLog(message: "AVPlayerItemNewErrorLogEntry = \(notify)")
+            }
+            NotificationCenter.default.addObserver(forName: .AVPlayerItemFailedToPlayToEndTime, object: recordPlayer?.currentItem, queue: .main) { notify in
+                BFLog(message: "AVPlayerItemFailedToPlayToEndTime = \(notify)")
+            }
+            NotificationCenter.default.addObserver(forName: .AVPlayerItemPlaybackStalled, object: recordPlayer?.currentItem, queue: .main) { notify in
+                BFLog(message: "AVPlayerItemPlaybackStalled = \(notify)")
+            }
+            recordPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: CMTimeScale(playerTimescale)), queue: .main) { [weak self] cmTime in
+                let delta = CMTimeGetSeconds(cmTime)
+      
+                BFLog(message: "progress = \(delta)")
+            }
 
             NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: recordPlayer?.currentItem, queue: .main) { [weak self] _ in
                 guard let wself = self else {
@@ -499,69 +525,15 @@ class BFRecordScreenCameraManager: BFRecordScreenBaseManager {
                  
                 //录制的视频如果不是播放过程当中 就不进行录音的播放了。
                 let palyEndURlString = (wself.recordPlayer?.currentItem?.asset as? AVURLAsset)?.url.absoluteString ?? ""
-                BFLog(message: "recordPlayer 播放完了:\(palyEndURlString) wself.avplayer.timeControlStatus \(wself.avplayer.timeControlStatus.rawValue)")
-//                if let mod = wself.recordItem?.getUsedVoices().first(where: { m in
-//                    palyEndURlString == m.wavFilePath
-//                }) {
-//                    mod.
-//                }
-                if wself.avplayer.timeControlStatus == .playing {
-                    wself.playRecordVoice()
-                }
+                BFLog(message: "recordPlayer 播放完了:\(palyEndURlString) wself.avplayer.timeControlStatus \(wself.avplayer.timeControlStatus.rawValue) currentAssetProgress: \(wself.currentAssetProgress.seconds)")
+ 
             }
         } else {
             BFLog(message: "没有找到即将播放的录制音频文件?\(currentAssetProgress.seconds)")
-            findAvailableChangeVoice()
-        }
-    }
 
-    // add by ak 正常播放未命中可使用录音时查找最近一个可用的音频, 并在 S 秒后会自动播放。
-    /// <#Description#>
-    func findAvailableChangeVoice() {
-        var playCMTime = CMTime.zero
-
-        if let mod = recordItem?.getUsedVoices().first(where: { m in
-            CMTimeCompare(m.startCMTime, currentAssetProgress) >= 0
-        }){
-            BFLog(message: "当前时间\(currentAssetProgress.seconds),命中的开始时间:\(mod.startCMTime.seconds) 结束时间\(mod.endCMTime.seconds)")
-            playCMTime = CMTimeSubtract(mod.startCMTime, currentAssetProgress)
-            
-            dispatchQueue = DispatchQueue.global(qos: .background) // create queue
-            dispatchWorkItem = DispatchWorkItem { [weak self] in
-                guard let wself = self else {
-                    return
-                }
-                if !wself.dispatchWorkItemIsCancel {
-                    wself.playRecordVoice(needPlay: true)
-                } else {
-                    BFLog(message: "dispatchWorkItem  Is Cancel")
-                }
-            }
-
-            if dispatchWorkItem != nil {
-                BFLog(message: "\(playCMTime.seconds) s 后自动播放变音音频\(mod.wavFilePath ?? "") 当前时间:\(currentAssetProgress.seconds)")
-                dispatchQueue?.asyncAfter(
-                    deadline: .now() + playCMTime.seconds,
-                    execute: dispatchWorkItem!
-                )
-            }
-        }else{
-            BFLog(message: "没有找到可播放的录制音频文件?\(currentAssetProgress.seconds)")
         }
-
-       
     }
-
-    // add by ak取消自动播放任务,1,暂停时 2,录制的视频播放结束时 调用
-    func cancelDispatchWorkItem() {
-        BFLog(message: "取消录制音频的查找下一个播放任务")
-        // 取消变声音音频任务
-        if let dispatchWorkItem = self.dispatchWorkItem {
-            dispatchWorkItem.cancel()
-            dispatchWorkItemIsCancel = true
-        }
-    }
-
+ 
     func findNextModel() {
         if let mod = recordItem?.videoStickers.sorted(by: { m1, m2 in
             m1.timelineCMIn.seconds < m2.timelineCMIn.seconds
@@ -635,12 +607,9 @@ class BFRecordScreenCameraManager: BFRecordScreenBaseManager {
 
             BFLog(1, message: "endPlay:\(wself.currentAssetProgress.seconds), 总时长:\(wself.recordItem!.materialDuraion.seconds), currplayer:\(wself.avplayer.currentItem?.currentTime().seconds ?? 0)")
 
-            // 判断录音是否还在播放
+            // 判断录音是否还在播放,如果在播放停止
             if wself.recordPlayer?.timeControlStatus == .playing {
                 wself.recordPlayer?.pause()
-                wself.cancelDispatchWorkItem()
-                wself.dispatchWorkItem = DispatchWorkItem { // create work item
-                }
             }
             // 如果离结束大于0.7s,代表还有下一段视频
             if ((wself.recordItem?.materialDuraion ?? .zero) - wself.currentAssetProgress).seconds > 0.7 {