|
@@ -65,7 +65,11 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- var currentAssetProgress: CMTime = .zero // 当前素材播放的进度
|
|
|
+ var currentAssetProgress: CMTime = .zero {
|
|
|
+ didSet {
|
|
|
+ BFLog(3,message: "currentAssetProgress=\(currentAssetProgress.seconds)")
|
|
|
+ }
|
|
|
+ } // 当前素材播放的进度
|
|
|
// 播放器开始播放时间
|
|
|
var recordStartPlayTime: CMTime = .zero
|
|
|
// 某个录音开始播放时间
|
|
@@ -121,6 +125,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
var beginOnStartBtn: Bool = false
|
|
|
var touchStart: CGPoint = CGPoint(x: 0, y: 0)
|
|
|
var avplayerTimeObserver: NSKeyValueObservation?
|
|
|
+ var recordPlayerTimeObserver: NSKeyValueObservation?
|
|
|
|
|
|
var indirectionView: BFIndirectionProgressView?
|
|
|
|
|
@@ -131,6 +136,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
l.textColor = .white
|
|
|
l.shadowColor = .black
|
|
|
l.shadowOffset = CGSize(width: 0, height: 1)
|
|
|
+ l.layer.opacity = 0.4
|
|
|
l.text = "00:00"
|
|
|
return l
|
|
|
}()
|
|
@@ -307,10 +313,10 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
self?.noSpeakVolume = noHaveSpeak / 100.0
|
|
|
if !(self?.isNormalPlaying ?? false), !(self?.isRecording ?? false) {
|
|
|
if self?.deleteRecordBtn.isHidden ?? false {
|
|
|
- self?.recordPlayer?.volume = 0
|
|
|
+// self?.recordPlayer?.volume = 0
|
|
|
self?.assetPlayer?.volume = self?.noSpeakVolume ?? 1.0
|
|
|
} else {
|
|
|
- self?.recordPlayer?.volume = 1.0
|
|
|
+// self?.recordPlayer?.volume = 1.0
|
|
|
self?.assetPlayer?.volume = self?.haveSpeakVolume ?? 0.0
|
|
|
}
|
|
|
}
|
|
@@ -400,6 +406,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
cleanMovieTarget()
|
|
|
NotificationCenter.default.removeObserver(self)
|
|
|
avplayerTimeObserver?.invalidate()
|
|
|
+ recordPlayerTimeObserver?.invalidate()
|
|
|
if isRecording {
|
|
|
recorderManager?.stopRecord(isCancel: true)
|
|
|
}
|
|
@@ -501,6 +508,9 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
BFLog(1, message: "卡在录音尾巴上了1")
|
|
|
newSubtitle.timelineIn = newSubtitle.timelineIn - CMTime(seconds: 0.1, preferredTimescale: 1000)
|
|
|
}
|
|
|
+ }else {
|
|
|
+ BFLog(1, message: "没有对应音频播放记录,出现错误!!!!!!")
|
|
|
+ return
|
|
|
}
|
|
|
}
|
|
|
var showText = ((payload?["result"]) as? String) ?? ""
|
|
@@ -716,7 +726,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
}
|
|
|
var findShowSubtitle: PQEditSubTitleModel?
|
|
|
for (index, subtitle) in itemModels[currItemModelIndex].titleStickers.enumerated() {
|
|
|
- if CMTimeCompare(subtitle.timelineIn, time) <= 0, CMTimeCompare(subtitle.timelineOut, time) >= 0 {
|
|
|
+ if CMTimeCompare(subtitle.timelineIn, time) <= 0, CMTimeCompare(subtitle.timelineOut, time) > 0, subtitle.audioFilePath.count > 0 { // audioFilePath.count 这个条件是确保这个字幕有对应录音
|
|
|
findShowSubtitle = subtitle
|
|
|
BFLog(1, message: "找到要显示的字幕 in \((findShowSubtitle?.timelineIn ?? .zero).seconds) out \((findShowSubtitle?.timelineOut ?? .zero).seconds) text:\(findShowSubtitle?.text ?? "") currTime is \(CMTimeGetSeconds(time))")
|
|
|
showSubtitleIndex = index
|
|
@@ -1002,8 +1012,10 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
let model = PQVoiceModel()
|
|
|
model.startCMTime = currentAssetProgress
|
|
|
+ model.currIndex = currItemModelIndex
|
|
|
model.volume = 100
|
|
|
recorderManager?.voiceModel = model
|
|
|
+ BFLog(3,message: "开始录制-开始:currentAssetProgress=\(currentAssetProgress.seconds),cuInde=\(currItemModelIndex),\(model)")
|
|
|
recorderManager?.startRecord()
|
|
|
recorderManager?.audioRecorder?.startNeoNui(NeoNuiToken ?? "", appid: NeoNuiAPPID ?? "")
|
|
|
isRecording = true
|
|
@@ -1036,6 +1048,11 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
}
|
|
|
beginOnStartBtn = false
|
|
|
|
|
|
+ recordBtn.isEnabled = false
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {[weak self] in
|
|
|
+ self?.recordBtn.isEnabled = true
|
|
|
+ }
|
|
|
+
|
|
|
isRecording = false
|
|
|
// progressThumV.progressView.isUserInteractionEnabled = true
|
|
|
// collectionView.isScrollEnabled = true
|
|
@@ -1061,6 +1078,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
if !avatarView.isHidden {
|
|
|
avatarView.endRecord()
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
@objc func cancleRecord() {
|
|
@@ -1075,6 +1093,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
/// 不足一秒,主动取消录制
|
|
|
/// - Parameter voiceModel: <#voiceModel description#>
|
|
|
@objc func recordManagerCancelRecord(voiceModel: PQVoiceModel?) {
|
|
|
+ BFLog(3,message: "开始录制-取消:currentAssetProgress=\(currentAssetProgress.seconds),cuInde=\(currItemModelIndex),currIndex=\(voiceModel?.currIndex ?? 0),\(String(describing: voiceModel)),\(String(describing:recorderManager?.voiceModel))")
|
|
|
if voiceModel != nil, currentAssetProgress.seconds - (recorderManager?.voiceModel?.startCMTime.seconds ?? 0) < 1.0 {
|
|
|
cShowHUB(superView: nil, msg: "最短录制1秒")
|
|
|
}
|
|
@@ -1094,12 +1113,14 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
subtitleCount = itemModels[currItemModelIndex].titleStickers.count
|
|
|
BFLog(2, message: "删除\(voiceModel?.wavFilePath ?? "")对应的字幕 后 count\(subtitleCount)")
|
|
|
/// 重置进度
|
|
|
- if itemModels[currItemModelIndex].mediaType == .IMAGE {
|
|
|
- currentAssetProgress = CMTime(seconds: recorderManager?.voiceModel?.startCMTime.seconds ?? 0, preferredTimescale: 1000)
|
|
|
- resetCurrentProgress()
|
|
|
+ if voiceModel?.currIndex == currItemModelIndex {
|
|
|
+ if itemModels[currItemModelIndex].mediaType == .IMAGE {
|
|
|
+ currentAssetProgress = CMTime(seconds: recorderManager?.voiceModel?.startCMTime.seconds ?? 0, preferredTimescale: 1000)
|
|
|
+ resetCurrentProgress()
|
|
|
+ }
|
|
|
+ // 移除
|
|
|
+ resetAllIndirectionView()
|
|
|
}
|
|
|
- // 移除
|
|
|
- resetAllIndirectionView()
|
|
|
recorderManager?.voiceModel = nil
|
|
|
}
|
|
|
|
|
@@ -1379,21 +1400,48 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
// MARK: - 音视频处理
|
|
|
|
|
|
func playRecord(at currentT: CMTime, periodicTimeObserver: @escaping (_ time: CMTime, _ currentItem: AVPlayerItem) -> Void, didPlayToEndTime: @escaping (_ recordedInfo: (Int, PQVoiceModel)?, _ currentItem: AVPlayerItem?) -> Void, playFailed _: @escaping (_ recordedInfo: (Int, PQVoiceModel)?, _ currentItem: AVPlayerItem?) -> Void) {
|
|
|
+
|
|
|
+// if currentPlayRecordIndex >= 0 {
|
|
|
+// if assetPlayer?.volume != haveSpeakVolume{
|
|
|
+// assetPlayer?.volume = haveSpeakVolume
|
|
|
+// }
|
|
|
+// }else{
|
|
|
+// if assetPlayer?.volume != noSpeakVolume {
|
|
|
+// assetPlayer?.volume = noSpeakVolume
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+ if itemModels[currItemModelIndex].voiceStickers.first(where: { m in
|
|
|
+ return CMTimeCompare(m.startCMTime, currentT) <= 0 && CMTimeCompare(currentT, m.endCMTime) <= 0
|
|
|
+ }) != nil{
|
|
|
+ if assetPlayer?.volume != haveSpeakVolume{
|
|
|
+ assetPlayer?.volume = haveSpeakVolume
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if assetPlayer?.volume != noSpeakVolume {
|
|
|
+ assetPlayer?.volume = noSpeakVolume
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if currentPlayRecordIndex == -3 { // 刚录音完,不需要播放
|
|
|
return
|
|
|
}
|
|
|
+
|
|
|
+ // 先排序,再查找下一个需要播放的录音
|
|
|
let list = itemModels[currItemModelIndex].voiceStickers.sorted { m1, m2 in
|
|
|
m1.startCMTime.seconds < m2.startCMTime.seconds
|
|
|
}
|
|
|
let (shouldPlayRecordIndex, recordedAudio) = list.enumerated().first { model in
|
|
|
model.1.endCMTime.seconds > CMTimeGetSeconds(currentT)
|
|
|
} ?? (-1, nil)
|
|
|
-
|
|
|
+
|
|
|
+ // 没找到,代表后边没有录音需求了
|
|
|
guard let recordedAudio = recordedAudio, recordedAudio.wavFilePath.count > 0 else {
|
|
|
BFLog(3, message: "未找到可播放录音")
|
|
|
return
|
|
|
}
|
|
|
BFLog(1, message: "当前时间:\(CMTimeGetSeconds(currentT)), 找到的音频:\(recordedAudio.startCMTime.seconds) ~ \(recordedAudio.endCMTime.seconds), \(recordedAudio.wavFilePath ?? "")")
|
|
|
+
|
|
|
// 创建播放器
|
|
|
if recordPlayer == nil || (recordPlayer?.currentItem?.asset as? AVURLAsset)?.url.lastPathComponent != (recordedAudio.wavFilePath as NSString?)?.lastPathComponent {
|
|
|
let newItem = AVPlayerItem(url: URL(fileURLWithPath: recordedAudio.wavFilePath))
|
|
@@ -1408,23 +1456,27 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
} else {
|
|
|
recordPlayer = AVPlayer(playerItem: newItem)
|
|
|
}
|
|
|
+ recordPlayer?.volume = 1
|
|
|
currentPlayRecordIndex = -1
|
|
|
hadPrepareToPlayRecord = false
|
|
|
BFLog(1, message: "录音播放器初始化(有时候不准)")
|
|
|
BFLog(3, message: "重置播放index-\(#function) = \(currentPlayRecordIndex)")
|
|
|
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: newItem, queue: .main) { [weak self] _ in
|
|
|
guard let sself = self else {
|
|
|
+ BFLog(3, message: "sself为空AVPlayerItemDidPlayToEndTime")
|
|
|
return
|
|
|
}
|
|
|
sself.hadPrepareToPlayRecord = false
|
|
|
sself.currentPlayRecordIndex = -1
|
|
|
- sself.recordPlayer?.volume = 0
|
|
|
- sself.assetPlayer?.volume = sself.noSpeakVolume
|
|
|
+// sself.recordPlayer?.volume = 0
|
|
|
+// sself.assetPlayer?.volume = sself.noSpeakVolume
|
|
|
+ BFLog(3, message: "播放结束")
|
|
|
didPlayToEndTime((shouldPlayRecordIndex, recordedAudio), newItem)
|
|
|
}
|
|
|
- avplayerTimeObserver?.invalidate()
|
|
|
- avplayerTimeObserver = recordPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 1000), queue: DispatchQueue.global()) { [weak self, weak recordPlayer,weak assetPlayer] time in
|
|
|
- guard let sself = self,let rPlay = recordPlayer,let aPlay = assetPlayer else {
|
|
|
+ recordPlayerTimeObserver?.invalidate()
|
|
|
+ recordPlayerTimeObserver = recordPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 1000), queue: DispatchQueue.global()) { [weak self, weak recordPlayer] time in
|
|
|
+ guard let sself = self,let rPlay = recordPlayer else {
|
|
|
+ BFLog(3, message: "sself为空")
|
|
|
return
|
|
|
}
|
|
|
BFLog(3, message: "当前播放---\(time),\(time.seconds),\(rPlay.currentItem?.currentTime().seconds ?? 0),\(rPlay.currentItem?.duration.seconds ?? 0)")
|
|
@@ -1435,11 +1487,9 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
let progressTime = CMTime(seconds: CMTimeGetSeconds(time) - CMTimeGetSeconds(sself.currenStartPlayTime), preferredTimescale: 1000)
|
|
|
BFLog(message: "progressTime进度\(#function)-\(progressTime.seconds)")
|
|
|
periodicTimeObserver(progressTime, newItem)
|
|
|
- if (rPlay.currentItem?.currentTime().seconds ?? 0) > (rPlay.currentItem?.duration.seconds ?? 0) - 0.1 {
|
|
|
- rPlay.volume = 0
|
|
|
- aPlay.volume = sself.noSpeakVolume
|
|
|
- didPlayToEndTime((shouldPlayRecordIndex, recordedAudio), newItem)
|
|
|
- }
|
|
|
+// if (rPlay.currentItem?.currentTime().seconds ?? 0) > (rPlay.currentItem?.duration.seconds ?? 0) - 0.1 {
|
|
|
+// didPlayToEndTime((shouldPlayRecordIndex, recordedAudio), newItem)
|
|
|
+// }
|
|
|
} as? NSKeyValueObservation
|
|
|
}
|
|
|
if itemModels[currItemModelIndex].mediaType == .VIDEO {
|
|
@@ -1482,8 +1532,8 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
self?.recordPlayer?.seek(to: CMTime(value: CMTimeValue(second * 1_000_000), timescale: 1_000_000), toleranceBefore: CMTime(value: 1, timescale: 1_000_000), toleranceAfter: CMTime(value: 1, timescale: 1_000_000), completionHandler: { [weak self] finished in
|
|
|
if finished, self?.isNormalPlaying ?? false {
|
|
|
self?.recordPlayer?.play()
|
|
|
- self?.recordPlayer?.volume = 1
|
|
|
- self?.assetPlayer?.volume = self?.haveSpeakVolume ?? 0
|
|
|
+// self?.recordPlayer?.volume = 1
|
|
|
+// self?.assetPlayer?.volume = self?.haveSpeakVolume ?? 0
|
|
|
BFLog(1, message: "录音开始播放 playing, \(second), \(CMTimeGetSeconds(self?.recordPlayer?.currentItem?.duration ?? .zero)), \(self?.recordPlayer?.currentItem?.currentTime().seconds ?? 0)")
|
|
|
}
|
|
|
})
|
|
@@ -1529,8 +1579,8 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
sself.recordPlayer?.seek(to: CMTime(value: CMTimeValue(second * 1_000_000), timescale: 1_000_000))
|
|
|
if sself.isNormalPlaying {
|
|
|
sself.recordPlayer?.play()
|
|
|
- sself.recordPlayer?.volume = 1
|
|
|
- sself.assetPlayer?.volume = sself.haveSpeakVolume
|
|
|
+// sself.recordPlayer?.volume = 1
|
|
|
+// sself.assetPlayer?.volume = sself.haveSpeakVolume
|
|
|
BFLog(1, message: "录音开始播放 playing, \(second), \(CMTimeGetSeconds(sself.recordPlayer?.currentItem?.duration ?? .zero)), \(sself.recordPlayer?.currentItem?.currentTime().seconds ?? 0)")
|
|
|
}
|
|
|
BFLog(3, message: "重置播放index-\(#function) = \(currentPlayRecordIndex)")
|
|
@@ -1580,12 +1630,17 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
func pause() {
|
|
|
BFLog(1, message: "暂停播放")
|
|
|
isNormalPlaying = false
|
|
|
+
|
|
|
+ // ---- 修复暂停播放回退问题
|
|
|
avplayerTimeObserver?.invalidate()
|
|
|
avplayerTimeObserver = nil
|
|
|
+ recordPlayerTimeObserver?.invalidate()
|
|
|
+ recordPlayerTimeObserver = nil
|
|
|
+ // ----
|
|
|
+
|
|
|
subtitleBtn.isHidden = false
|
|
|
soundSettingBtn.isHidden = false
|
|
|
withDrawBtn.isHidden = false
|
|
|
-// recordBtn.isHidden = isRecording ? false : isEndPlay
|
|
|
recordBtn.isHidden = (itemModels[currItemModelIndex].mediaType == .IMAGE && isEndPlay) ? false : isEndPlay
|
|
|
|
|
|
assetPlayer?.pause()
|
|
@@ -1594,6 +1649,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
pauseTime = currentAssetProgress.seconds
|
|
|
currentPlayRecordIndex = -1
|
|
|
hadPrepareToPlayRecord = false
|
|
|
+
|
|
|
// 暂停状态
|
|
|
playBtn.isSelected = (itemModels[currItemModelIndex].mediaType == .IMAGE && itemModels[currItemModelIndex].voiceStickers.count <= 0)
|
|
|
}
|
|
@@ -1670,7 +1726,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
} else {
|
|
|
assetPlayer = AVPlayer(playerItem: item)
|
|
|
BFLog(message: "设置播放器item-替换:\(String(describing: item))")
|
|
|
- assetPlayer?.volume = noSpeakVolume
|
|
|
+// assetPlayer?.volume = noSpeakVolume
|
|
|
avplayerTimeObserver?.invalidate()
|
|
|
avplayerTimeObserver = assetPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 1000), queue: DispatchQueue.global()) { [weak self] time in
|
|
|
// 进度监控
|
|
@@ -1924,6 +1980,10 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
|
|
|
|
|
|
public func collectionView(_: UICollectionView, didSelectItemAt _: IndexPath) {}
|
|
|
|
|
|
+ public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
|
|
+ BFLog(1, message: "开始滚动")
|
|
|
+ recordBtn.isEnabled = false
|
|
|
+ }
|
|
|
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
|
|
|
endScrollItem(scrollView)
|
|
|
}
|
|
@@ -1937,6 +1997,7 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
|
|
|
func endScrollItem(_ scrollView: UIScrollView) {
|
|
|
// public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
|
|
BFLog(1, message: "滚动结束")
|
|
|
+
|
|
|
let page = Int((scrollView.contentOffset.x + scrollView.frame.width / 2) / scrollView.frame.width)
|
|
|
if page != currItemModelIndex {
|
|
|
// 切换素材时先把录制状态切为不可用,延迟可点,避免在缩略图未加载出来时即可录制
|
|
@@ -1977,6 +2038,12 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
|
|
|
// 重置播放器
|
|
|
assetPlayer?.seek(to: CMTime.zero)
|
|
|
recordPlayer?.seek(to: CMTime.zero)
|
|
|
+
|
|
|
+ if let voice = itemModels[page].voiceStickers.enumerated().first(where: { m in
|
|
|
+ m.1.startTime == 0
|
|
|
+ }){
|
|
|
+ currentPlayRecordIndex = voice.0
|
|
|
+ }
|
|
|
|
|
|
searchStopAtRecordRange()
|
|
|
changeWithDrawBtnLayout(0)
|
|
@@ -1995,6 +2062,7 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
|
|
|
cell?.contentView.addSubview(subtitleLabel)
|
|
|
updateSubtitle(time: currentAssetProgress)
|
|
|
}
|
|
|
+ recordBtn.isEnabled = true
|
|
|
}
|
|
|
|
|
|
public func updateContentOffset(index: Int) {
|
|
@@ -2024,7 +2092,7 @@ public extension BFRecordScreenController {
|
|
|
currenStartPlayTime = CMTime.zero
|
|
|
}
|
|
|
playRecord(at: time, periodicTimeObserver: { [weak self] currentT, currentItem in
|
|
|
- BFLog(1, message: "播放录音进度:\(currentT.seconds),\(currentItem)")
|
|
|
+// BFLog(1, message: "播放录音进度:\(currentT.seconds),\(currentItem)")
|
|
|
if self?.itemModels[self?.currItemModelIndex ?? 0].mediaType == .IMAGE, self?.isNormalPlaying ?? false {
|
|
|
self?.imageRecordProgress(progress: CMTimeGetSeconds(currentT))
|
|
|
}
|
|
@@ -2039,6 +2107,7 @@ public extension BFRecordScreenController {
|
|
|
self?.resetCurrentProgress()
|
|
|
// 录制播放结束后显示录制按钮
|
|
|
self?.recordBtn.isHidden = false
|
|
|
+ self?.recordBtn.alpha = 1
|
|
|
} else {
|
|
|
// 注:矫正进度--一段录音播放结束后当前指针应该到当前录音结束点
|
|
|
self?.currentAssetProgress = CMTime(seconds: self?.itemModels[self?.currItemModelIndex ?? 0].voiceStickers[(recordInfo?.0 ?? 0) + 1].startCMTime.seconds ?? 0, preferredTimescale: 1000)
|