|
@@ -17,7 +17,10 @@ import Foundation
|
|
|
import GPUImage
|
|
|
import Photos
|
|
|
import UIKit
|
|
|
-
|
|
|
+import BFUploadKit
|
|
|
+import Kingfisher
|
|
|
+import BFAnalyzeKit
|
|
|
+import BFCommonKit
|
|
|
struct WithDrawModel {
|
|
|
var type: Int // 0:拖动; 1:预览播放暂停 2: 录音结束 3: 删除录音
|
|
|
var timestamp: CMTime
|
|
@@ -48,6 +51,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
public var nextActionHandle: (() -> Void)?
|
|
|
public var closeActionHandle: (() -> Void)?
|
|
|
public var changeItemHandle: ((_ index: Int) -> Void)?
|
|
|
+ public var cleanScreen: ((Bool) -> Void)?
|
|
|
// 当前录制结束的上报
|
|
|
public var recordEndHandle: ((_ currentRecord: PQVoiceModel?) -> Void)?
|
|
|
// 字幕按钮点击上报
|
|
@@ -55,6 +59,8 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
// public var currentRecordId: String? // 当前录制Id
|
|
|
//选了发音人点了确定
|
|
|
public var voiceBtnClickHandle: ((_ voice: PQVoiceModel?) -> Void)?
|
|
|
+ //选择的背景音乐信息
|
|
|
+ public var bgmModel:PQVoiceModel?
|
|
|
// MARK: - 素材参数
|
|
|
lazy var rsvmanager : BFRecordScreenVideoManager = {
|
|
|
let m = BFRecordScreenVideoManager()
|
|
@@ -73,6 +79,9 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
lazy var rscmanager : BFRecordScreenCameraManager = {
|
|
|
let m = BFRecordScreenCameraManager()
|
|
|
+ m.assetPlayer = assetPlayer
|
|
|
+
|
|
|
+
|
|
|
m.recordProgressCallBack = {[weak self] progress in
|
|
|
guard let wself = self else { return }
|
|
|
wself.rscurrentManager.currentAssetProgress = progress
|
|
@@ -126,6 +135,11 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
let itemModel = itemModels[currItemModelIndex]
|
|
|
currMediaType = itemModel.mediaType ?? .Video
|
|
|
isEndPlay = false
|
|
|
+
|
|
|
+ assetPlayer.pause()
|
|
|
+ assetPlayer.replaceCurrentItem(with: nil)
|
|
|
+ recordPlayer.pause()
|
|
|
+ recordPlayer.replaceCurrentItem(with: nil)
|
|
|
|
|
|
switch itemModel.mediaType {
|
|
|
case .Image:
|
|
@@ -213,6 +227,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
voiceSettingBtn.isHidden = isRecording
|
|
|
subtitleBtn.isHidden = isRecording
|
|
|
soundSettingBtn.isHidden = isRecording
|
|
|
+ addMusicBtn.isHidden = isRecording
|
|
|
recordBtn.setTitle(isRecording ? "record_pause".BFLocale : (currMediaType == .Camera ? "record_lz".BFLocale : "record_ly".BFLocale), for: .normal)
|
|
|
recordBtn.backgroundColor = UIColor.hexColor(hexadecimal: "#389AFF", alpha: isRecording ? 0.6 : 1)
|
|
|
cameraFlipBtn.isHidden = !(!isRecording && (currMediaType == .Camera))
|
|
@@ -243,6 +258,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
soundSettingBtn.isHidden = isNormalPlaying
|
|
|
voiceSettingBtn.isHidden = isNormalPlaying
|
|
|
withDrawBtn.isHidden = isNormalPlaying
|
|
|
+ addMusicBtn.isHidden = isNormalPlaying
|
|
|
updateRecordBtnStatus(needHidden: isNormalPlaying)
|
|
|
cameraFlipBtn.isHidden = !(!isNormalPlaying && (currMediaType == .Camera) && !isDragingProgressSlder)
|
|
|
}
|
|
@@ -260,8 +276,9 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
var currenStartPlayTime: CMTime = .zero
|
|
|
var pauseTime: Double = 0 // 停止无操作的时间点
|
|
|
|
|
|
- var assetPlayer: AVPlayer = AVPlayer(playerItem: nil) // 原视频音频播放器
|
|
|
- var recordPlayer: AVPlayer = AVPlayer(playerItem: nil) // 录音音频播放器
|
|
|
+ var assetPlayer : AVPlayer = AVPlayer(playerItem: nil) // 原视频音频播放器
|
|
|
+ var recordPlayer : AVPlayer = AVPlayer(playerItem: nil) // 录音音频播放器
|
|
|
+ var bgmPlayer = BFMusicManager() // 背景音乐音频播放器
|
|
|
|
|
|
var hadPrepareToPlayRecord = false // 录音播放器准备
|
|
|
var playView: GPUImageView? // 视频展示视图
|
|
@@ -297,8 +314,8 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
AVEncoderBitDepthHintKey: 16, // 位深
|
|
|
AVEncoderAudioQualityKey: AVAudioQuality.medium.rawValue] // 音频质量
|
|
|
|
|
|
- public var haveSpeakVolume: Float = 0.15
|
|
|
- public var noSpeakVolume: Float = 0.30
|
|
|
+ //原素材音量
|
|
|
+ public var originalVolume: Float = 0.2
|
|
|
|
|
|
// 录音管理器
|
|
|
var recorderManager: BFVoiceRecordManager?
|
|
@@ -393,7 +410,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
btn.isEnabled = false
|
|
|
btn.titleLabel?.font = UIFont.systemFont(ofSize: 12)
|
|
|
btn.contentVerticalAlignment = UIControl.ContentVerticalAlignment.center
|
|
|
- btn.addTarget(self, action: #selector(withdrawAction), for: .touchUpInside)
|
|
|
+ btn.addTarget(self, action: #selector(withdrawAction), for: .touchDown)
|
|
|
return btn
|
|
|
}()
|
|
|
|
|
@@ -412,6 +429,28 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
return toolV
|
|
|
|
|
|
}()
|
|
|
+
|
|
|
+ lazy var musicCutView: BFMusicCutView = {
|
|
|
+ let musicCutView = BFMusicCutView(frame: CGRect(x: 0, y: 0, width: cScreenWidth, height: cScreenHeigth))
|
|
|
+ musicCutView.isHidden = true
|
|
|
+ musicCutView.cutTimeHandle = {[weak self] iscancel, endTime, musicInfo in
|
|
|
+ guard let wself = self else { return }
|
|
|
+
|
|
|
+ if(!iscancel){
|
|
|
+ wself.hadChoosed(music:musicInfo)
|
|
|
+ }else{
|
|
|
+ musicInfo?.isSelected = false
|
|
|
+ let btn = UIButton()
|
|
|
+ btn.tag = 1001
|
|
|
+ wself.choseMusicPanel.btnAction(btn: btn)
|
|
|
+ }
|
|
|
+
|
|
|
+ //add by ak
|
|
|
+ wself.showOptBtn(isShow: true)
|
|
|
+ }
|
|
|
+ return musicCutView
|
|
|
+ }()
|
|
|
+
|
|
|
|
|
|
// 头像 add by ak
|
|
|
lazy var avatarView: BFRecordAvatarView = {
|
|
@@ -493,36 +532,96 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
let btn = UIButton(type: .custom)
|
|
|
btn.setImage(imageInRecordScreenKit(by: "flip"), for: .normal)
|
|
|
btn.titleLabel?.font = UIFont.systemFont(ofSize: 10)
|
|
|
- btn.addTarget(self, action: #selector(cameraFlipAction), for: .touchUpInside)
|
|
|
+ btn.addTarget(self, action: #selector(cameraFlipAction), for: .touchDown)
|
|
|
return btn
|
|
|
}()
|
|
|
|
|
|
// 添加音乐设置
|
|
|
- lazy var addMusicBtn: UIButton = {
|
|
|
- let btn = UIButton(type: .custom)
|
|
|
- btn.backgroundColor = UIColor.black
|
|
|
+ lazy var addMusicBtn: BFCustomMusicBtn = {
|
|
|
+// let btn = UIButton(type: .custom)
|
|
|
+// btn.setImage(imageInRecordScreenKit(by: "addmusic"), for: .normal)
|
|
|
+// btn.setTitle("选择音乐", for: .normal)
|
|
|
+// btn.titleLabel?.font = UIFont.systemFont(ofSize: 13)
|
|
|
+// btn.addTarget(self, action: #selector(addMusicAction), for: .touchDown)
|
|
|
+
|
|
|
+ let btn = BFCustomMusicBtn(frame: CGRect.zero)
|
|
|
+ btn.backgroundColor = UIColor.init(white: 0, alpha: 0.6)
|
|
|
btn.layer.cornerRadius = 16
|
|
|
- btn.setImage(imageInRecordScreenKit(by: "addmusic"), for: .normal)
|
|
|
- btn.setTitle("选择音乐", for: .normal)
|
|
|
- btn.titleLabel?.font = UIFont.systemFont(ofSize: 13)
|
|
|
- btn.addTarget(self, action: #selector(addMusicAction), for: .touchUpInside)
|
|
|
+ btn.clickAction = {[weak self] in
|
|
|
+ guard let wself = self else { return }
|
|
|
+
|
|
|
+ wself.addMusicAction()
|
|
|
+ }
|
|
|
return btn
|
|
|
}()
|
|
|
|
|
|
lazy var choseMusicPanel: BFChooseMusicView = {
|
|
|
- let vv = BFChooseMusicView(frame: CGRect(x: 0, y: cScreenHeigth, width: cScreenWidth, height: cScreenHeigth - 200))
|
|
|
- vv.clickBtnAction = { [weak self] type in
|
|
|
+ let vv = BFChooseMusicView(frame: CGRect(x: 0, y: cScreenHeigth, width: cScreenWidth, height: cScreenHeigth))
|
|
|
+ vv.clickBtnAction = { [weak self, weak vv] type in
|
|
|
guard let wself = self else { return }
|
|
|
|
|
|
+ var nextAction : ((Bool) -> Void)?
|
|
|
if type == BFChooseMusicViewClickType.sure {
|
|
|
+ wself.hadChoosed(music: vv?.chosedMusic)
|
|
|
+ wself.audioSettingView.musicSlider.value = Float(vv?.musicVolume ?? 0)
|
|
|
+
|
|
|
+ BFLog(1, message: "volume1 sure: \(wself.choseMusicPanel.musicVolume)")
|
|
|
+ }else if type == .cancle{
|
|
|
+ wself.choseMusicPanel.musicVolume = Int(wself.audioSettingView.musicSlider.value)
|
|
|
+ BFLog(1, message: "volume1 cancel: \(wself.choseMusicPanel.musicVolume)")
|
|
|
+ }else if type == .search{
|
|
|
+ nextAction = {[weak self] isFinished in
|
|
|
+ guard let wself = self else { return }
|
|
|
+ BFLog(1, message: "volume1 search: \(wself.choseMusicPanel.musicVolume)")
|
|
|
+
|
|
|
+ if isFinished {
|
|
|
+ let vc = BFMusicSearchController()
|
|
|
+ vc.modalPresentationStyle = .fullScreen
|
|
|
+ vc.musicVolume = wself.choseMusicPanel.musicVolume
|
|
|
+ vc.choseAction = {[weak self] voiceModel in
|
|
|
+ guard let wself = self else { return }
|
|
|
+ wself.hadChoosed(music: voiceModel)
|
|
|
+ wself.choseMusicPanel.searchModel = voiceModel
|
|
|
+ }
|
|
|
+
|
|
|
+ vc.cutActionCallback = {[weak self] voiceModel in
|
|
|
+ guard let wself = self else { return }
|
|
|
+ wself.showOptBtn(isShow: false)
|
|
|
+ wself.showCutView(voiceModel)
|
|
|
+ }
|
|
|
+ wself.present(vc, animated: true, completion: nil)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let hiddAnimation = {[weak self] in
|
|
|
+ guard let wself = self else { return }
|
|
|
|
|
|
- }else {
|
|
|
+ wself.choseMusicPanel.frame = CGRect(x: 0, y: cScreenHeigth, width: cScreenWidth, height: cScreenHeigth)
|
|
|
|
|
|
+ if(type != .search){
|
|
|
+ wself.showOptBtn(isShow: true)
|
|
|
+ }
|
|
|
+ wself.cleanScreen?(false)
|
|
|
}
|
|
|
- UIView.animate(withDuration: 0.25) {
|
|
|
- wself.choseMusicPanel.frame = CGRect(x: 0, y: cScreenHeigth, width: cScreenWidth, height: cScreenHeigth - 200)
|
|
|
+
|
|
|
+ UIView.animate(withDuration: 0.25, animations: hiddAnimation, completion: nextAction)
|
|
|
+ }
|
|
|
+
|
|
|
+ vv.cutActionCallback = {[weak self] voiceModel in
|
|
|
+
|
|
|
+ UIView.animate(withDuration: 0.25) {[weak self] in
|
|
|
+ guard let wself = self else { return }
|
|
|
+
|
|
|
+ wself.choseMusicPanel.frame = CGRect(x: 0, y: cScreenHeigth, width: cScreenWidth, height: cScreenHeigth)
|
|
|
+
|
|
|
+ } completion: {[weak self] _ in
|
|
|
+ guard let wself = self else { return }
|
|
|
+ wself.showCutView(voiceModel)
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
return vv
|
|
|
}()
|
|
|
|
|
@@ -574,24 +673,22 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
// 音量设置
|
|
|
lazy var audioSettingView: BFAudioSettingView = {
|
|
|
let audioSettingView = BFAudioSettingView(frame: CGRect(x: 0, y: 0, width: cScreenWidth, height: cScreenHeigth))
|
|
|
+ audioSettingView.originalMSlider.value = 20
|
|
|
+ audioSettingView.musicSlider.value = 20
|
|
|
audioSettingView.isHidden = true
|
|
|
- audioSettingView.haveSpeakSlider.valueIsInt = true
|
|
|
- audioSettingView.noSpeakSlider.valueIsInt = true
|
|
|
- audioSettingView.callBack = { [weak self] haveSpeak, noHaveSpeak in
|
|
|
+ audioSettingView.musicSlider.valueIsInt = true
|
|
|
+ audioSettingView.originalMSlider.valueIsInt = true
|
|
|
+ audioSettingView.callBack = { [weak self] originalVolume, musicVolume in
|
|
|
// BFLog(1, message: "haveSpeak is:\(haveSpeak),noHaveSpeak is:\(noHaveSpeak)")
|
|
|
guard let wself = self else { return }
|
|
|
-
|
|
|
- wself.haveSpeakVolume = haveSpeak / 100.0
|
|
|
- wself.noSpeakVolume = noHaveSpeak / 100.0
|
|
|
- if !wself.isNormalPlaying, !wself.isRecording {
|
|
|
- if wself.deleteRecordBtn.isHidden {
|
|
|
-// wself.recordPlayer.volume = 0
|
|
|
- wself.assetPlayer.volume = wself.noSpeakVolume
|
|
|
- } else {
|
|
|
-// wself.recordPlayer.volume = 1.0
|
|
|
- wself.assetPlayer.volume = wself.haveSpeakVolume
|
|
|
- }
|
|
|
- }
|
|
|
+ wself.showOptBtn(isShow: true)
|
|
|
+ wself.bgmModel?.volume = Int(musicVolume)
|
|
|
+ wself.originalVolume = originalVolume / 100.0
|
|
|
+ wself.choseMusicPanel.musicVolume = Int(musicVolume)
|
|
|
+ wself.assetPlayer.volume = wself.originalVolume
|
|
|
+// if !wself.isNormalPlaying, !wself.isRecording {
|
|
|
+//
|
|
|
+// }
|
|
|
}
|
|
|
|
|
|
return audioSettingView
|
|
@@ -679,12 +776,24 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
assetPlayer.pause()
|
|
|
recordPlayer.pause()
|
|
|
}
|
|
|
+
|
|
|
+ /// 显示或隐藏功能 btn
|
|
|
+ /// - Parameter isShow: <#isShow description#>
|
|
|
+ func showOptBtn(isShow:Bool){
|
|
|
+
|
|
|
+ soundSettingBtn.isHidden = !isShow
|
|
|
+ cameraFlipBtn.isHidden = !isShow
|
|
|
+ voiceSettingBtn.isHidden = !isShow
|
|
|
+ subtitleBtn.isHidden = !isShow
|
|
|
+ addMusicBtn.isHidden = !isShow
|
|
|
+
|
|
|
+ cleanScreen?(!isShow)
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
@objc func didBecomeActive() {
|
|
|
BFLog(message: "进入活跃状态")
|
|
|
-
|
|
|
- loadingView.startGIF()
|
|
|
-
|
|
|
}
|
|
|
|
|
|
@objc func willResignActive() {
|
|
@@ -733,11 +842,6 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
override public func viewDidLoad() {
|
|
|
super.viewDidLoad()
|
|
|
_ = disablePopGesture()
|
|
|
-
|
|
|
- let doubleTapGes = UITapGestureRecognizer(target: self, action: #selector(doubleTapAction(tap:)))
|
|
|
- doubleTapGes.numberOfTapsRequired = 2
|
|
|
- doubleTapGes.numberOfTouchesRequired = 1
|
|
|
- view.addGestureRecognizer(doubleTapGes)
|
|
|
|
|
|
// 进入活跃状态
|
|
|
PQNotification.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
|
|
@@ -772,10 +876,10 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
view.addSubview(bottomeView)
|
|
|
// view.addSubview(subtitleLabel)
|
|
|
-// view.addSubview(addMusicBtn)
|
|
|
- view.addSubview(choseMusicPanel)
|
|
|
-
|
|
|
view.addSubview(playBtn)
|
|
|
+
|
|
|
+ view.addSubview(choseMusicPanel)
|
|
|
+ view.addSubview(addMusicBtn)
|
|
|
// view.addSubview(avatarView)
|
|
|
// view.addSubview(openCameraBtn)
|
|
|
// view.addSubview(drawPinBtn)
|
|
@@ -785,10 +889,9 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
view.addSubview(voiceSettingBtn)
|
|
|
voiceSettingBtn.addSubview(voiceIconView)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
view.addSubview(cameraFlipBtn)
|
|
|
|
|
|
-
|
|
|
view.addSubview(subtitleSettingView)
|
|
|
view.addSubview(audioSettingView)
|
|
|
//??? add key windows?
|
|
@@ -810,22 +913,25 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
// 字幕设置回调
|
|
|
subtitleSettingView.subtitleSettingCallBack = { [weak self] subtitileModel in
|
|
|
-
|
|
|
+
|
|
|
if let wself = self{
|
|
|
|
|
|
- //1,设置字幕样式
|
|
|
- wself.setSubtitleStyle(settingModel: subtitileModel.setting)
|
|
|
-
|
|
|
- //2,显示设置文字,不显示设置为空
|
|
|
- if(subtitileModel.setting.subtitleIsShow){
|
|
|
- wself.updateSubtitle(time: wself.currentAssetProgress)
|
|
|
- }else{
|
|
|
- wself.subtitleLabel.text = ""
|
|
|
- }
|
|
|
-
|
|
|
- // mdf by ak 这里是设置字幕开关回调
|
|
|
- if wself.subTitleBtnClickHandle != nil {
|
|
|
- wself.subTitleBtnClickHandle!(subtitileModel.setting.subtitleIsShow)
|
|
|
+ wself.showOptBtn(isShow: true)
|
|
|
+ if(subtitileModel != nil){
|
|
|
+ //1,设置字幕样式
|
|
|
+ wself.setSubtitleStyle(settingModel: subtitileModel!.setting)
|
|
|
+
|
|
|
+ //2,显示设置文字,不显示设置为空
|
|
|
+ if(subtitileModel!.setting.subtitleIsShow){
|
|
|
+ wself.updateSubtitle(time: wself.currentAssetProgress)
|
|
|
+ }else{
|
|
|
+ wself.subtitleLabel.text = ""
|
|
|
+ }
|
|
|
+
|
|
|
+ // mdf by ak 这里是设置字幕开关回调
|
|
|
+ if wself.subTitleBtnClickHandle != nil {
|
|
|
+ wself.subTitleBtnClickHandle!(subtitileModel!.setting.subtitleIsShow)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -902,7 +1008,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
}
|
|
|
voiceSettingView.voiceSettingCallBack = {[weak self] actionType ,selectVoice ,isSame in
|
|
|
guard let wself = self else { return }
|
|
|
-
|
|
|
+ wself.showOptBtn(isShow: true)
|
|
|
if actionType == .VoiceSettingActionConfirm{//要生成真实音频文件
|
|
|
BFLog(2, message: "确认选择发音人操作")
|
|
|
if(wself.voiceBtnClickHandle != nil && selectVoice != nil){
|
|
@@ -928,7 +1034,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
//显示 UI
|
|
|
wself.voiceIconView.setNetImage(url: "\(wself.mSelectVoiced?.avatarUrl ?? "")")
|
|
|
if(!wself.voiceChangeStickerFinish(itemIndex: wself.currItemModelIndex)){
|
|
|
-
|
|
|
+ wself.loadingView.isDownloadMusic = false
|
|
|
wself.loadingView.loadShow()
|
|
|
}
|
|
|
//静默转换语音
|
|
@@ -970,6 +1076,8 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
}
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+ view.addSubview(musicCutView);
|
|
|
|
|
|
UIApplication.shared.keyWindow?.addSubview(loadingView)
|
|
|
}
|
|
@@ -980,12 +1088,11 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
make.height.equalTo(adapterWidth(width: 180))
|
|
|
}
|
|
|
|
|
|
-// addMusicBtn.snp.makeConstraints { make in
|
|
|
-// make.centerX.equalToSuperview()
|
|
|
-// make.top.equalTo(soundSettingBtn).offset(-8)
|
|
|
-// make.width.equalTo(100)
|
|
|
-// make.height.equalTo(32)
|
|
|
-// }
|
|
|
+ addMusicBtn.snp.makeConstraints { make in
|
|
|
+ make.centerX.equalToSuperview()
|
|
|
+ make.top.equalTo(soundSettingBtn).offset(-12)
|
|
|
+ make.height.equalTo(32)
|
|
|
+ }
|
|
|
|
|
|
progreddL.snp.makeConstraints { make in
|
|
|
make.width.equalTo(100)
|
|
@@ -1385,6 +1492,23 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
// }
|
|
|
|
|
|
// MARK: - 按钮事件响应
|
|
|
+
|
|
|
+ func showCutView(_ model:PQVoiceModel) {
|
|
|
+
|
|
|
+ DispatchQueue.main.async { [weak self] in
|
|
|
+ guard let wself = self else { return }
|
|
|
+ wself.musicCutView.bgmData = model
|
|
|
+ wself.musicCutView.currentProgressLab.text = model.startCMTime.seconds.formatDurationToHMS()
|
|
|
+ wself.musicCutView.resetWave()
|
|
|
+ wself.musicCutView.show()
|
|
|
+
|
|
|
+ wself.musicCutView.frame = CGRect(x: 0, y: cScreenHeigth + 220, width: cScreenWidth, height: cScreenHeigth)
|
|
|
+ UIView.animate(withDuration: 0.1) {
|
|
|
+ // 显示裁剪视图
|
|
|
+ wself.musicCutView.frame = CGRect(x: 0, y:0, width: cScreenWidth, height: cScreenHeigth)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
override public func backBtnClick() {
|
|
|
//add by ak 删除变音文件
|
|
@@ -1444,20 +1568,21 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
@objc func subTitleClick() {
|
|
|
BFLog(message: "subTitle Click ")
|
|
|
subtitleSettingView.isHidden = !subtitleSettingView.isHidden
|
|
|
-
|
|
|
+ showOptBtn(isShow: false)
|
|
|
updateSubtitle(time: currentAssetProgress)
|
|
|
}
|
|
|
|
|
|
// 声音设置
|
|
|
@objc func soundSetting() {
|
|
|
BFLog(message: "设置声音")
|
|
|
-
|
|
|
+ showOptBtn(isShow: false)
|
|
|
audioSettingView.isHidden = !audioSettingView.isHidden
|
|
|
}
|
|
|
|
|
|
//变声设置
|
|
|
@objc func voiceSetting() {
|
|
|
BFLog(message: "设置变音")
|
|
|
+ showOptBtn(isShow: false)
|
|
|
if(mSelectVoiced != nil){
|
|
|
voiceSettingView.selectVoice = mSelectVoiced
|
|
|
voiceSettingView.flushSelectVoiceStatus(voiceStatue: .isSelected)
|
|
@@ -1468,17 +1593,6 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
}
|
|
|
|
|
|
- @objc func doubleTapAction(tap:UITapGestureRecognizer) {
|
|
|
- if !(bottomeView.bounds.contains(tap.location(in: bottomeView))
|
|
|
- || navHeadImageView!.bounds.contains(tap.location(in: navHeadImageView!))
|
|
|
- || !voiceSettingView.isHidden
|
|
|
- || !subtitleSettingView.isHidden
|
|
|
- || !audioSettingView.isHidden
|
|
|
- || recordBtn.isHidden){
|
|
|
- cameraFlipAction()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
@objc func cameraFlipAction() {
|
|
|
if currMediaType == .Camera && !recordBtn.isHidden {
|
|
|
rscmanager.cameraFlip()
|
|
@@ -1486,24 +1600,20 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
}
|
|
|
|
|
|
@objc func addMusicAction() {
|
|
|
- cShowHUB(superView: nil, msg: "选择音乐")
|
|
|
|
|
|
soundSettingBtn.isHidden = true
|
|
|
cameraFlipBtn.isHidden = true
|
|
|
voiceSettingBtn.isHidden = true
|
|
|
subtitleBtn.isHidden = true
|
|
|
addMusicBtn.isHidden = true
|
|
|
-
|
|
|
+ cleanScreen?(true)
|
|
|
UIView.animate(withDuration: 0.25) {[weak self] in
|
|
|
guard let wself = self else { return }
|
|
|
- wself.soundSettingBtn.isHidden = false
|
|
|
- wself.cameraFlipBtn.isHidden = false
|
|
|
- wself.voiceSettingBtn.isHidden = false
|
|
|
- wself.subtitleBtn.isHidden = false
|
|
|
- wself.addMusicBtn.isHidden = false
|
|
|
|
|
|
- wself.choseMusicPanel.frame = CGRect(x: 0, y: 210, width: cScreenWidth, height: cScreenHeigth - 200)
|
|
|
+ wself.choseMusicPanel.frame = CGRect(x: 0, y: 0, width: cScreenWidth, height: cScreenHeigth)
|
|
|
}
|
|
|
+ choseMusicPanel.refreshCurrSelectModel(mod: bgmModel)
|
|
|
+ choseMusicPanel.musicVolume = Int(audioSettingView.musicSlider.value)
|
|
|
}
|
|
|
|
|
|
/// 删除指定段落的所有字幕 数据
|
|
@@ -1647,6 +1757,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
@objc func endRecord() {
|
|
|
// 存储录音
|
|
|
+
|
|
|
if !isRecording {
|
|
|
return
|
|
|
}
|
|
@@ -1928,7 +2039,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
recordBtn.isHidden = isEndPlay ? false : su
|
|
|
}
|
|
|
|
|
|
- deleteRecordBtn.isHidden = isEndPlay ? true : !(recordBtn.isHidden)
|
|
|
+ deleteRecordBtn.isHidden = isEndPlay ? true : ((isRecording || isNormalPlaying) ? true : !(recordBtn.isHidden))
|
|
|
}
|
|
|
|
|
|
func recordFinished(_ isFinished:Bool) {
|
|
@@ -2053,33 +2164,26 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
}
|
|
|
|
|
|
// MARK: - 音视频处理
|
|
|
-
|
|
|
+
|
|
|
+ /// 查找录音播放
|
|
|
+ /// - Parameters:
|
|
|
+ /// - currentT: 当前播放进度时刻
|
|
|
+ /// - periodicTimeObserver: 每次刷新要执行的block
|
|
|
+ /// - didPlayToEndTime: 录音播放结束后的block
|
|
|
+ /// - _: 播放失败的block
|
|
|
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
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
+
|
|
|
//add by ak 使用的音频数据
|
|
|
let useVoiceStickers = itemModels[currItemModelIndex].getUsedVoices()
|
|
|
|
|
|
//音量设置判断使用原录音数据
|
|
|
- if itemModels[currItemModelIndex].voiceStickers.first(where: { m in
|
|
|
- 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 itemModels[currItemModelIndex].voiceStickers.first(where: { m in
|
|
|
+// CMTimeCompare(m.startCMTime, currentT) <= 0 && CMTimeCompare(currentT, m.endCMTime) <= 0
|
|
|
+// }) != nil {
|
|
|
+// if assetPlayer.volume != originalVolume {
|
|
|
+// assetPlayer.volume = originalVolume
|
|
|
+// }
|
|
|
+// }
|
|
|
// BFLog(1, message: "volume:\(assetPlayer.volume ?? -1)")
|
|
|
|
|
|
if currentPlayRecordIndex == -3 { // 刚录音完,不需要播放
|
|
@@ -2100,7 +2204,6 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
return
|
|
|
}
|
|
|
BFLog(1, message: "当前时间:\(CMTimeGetSeconds(currentT)), 找到的音频:\(recordedAudio.startCMTime.seconds) ~ \(recordedAudio.endCMTime.seconds), \(recordedAudio.wavFilePath ?? "")")
|
|
|
-
|
|
|
// 创建播放器
|
|
|
if (recordPlayer.currentItem?.asset as? AVURLAsset)?.url.lastPathComponent != (recordedAudio.wavFilePath as NSString?)?.lastPathComponent {
|
|
|
let newItem = AVPlayerItem(url: URL(fileURLWithPath: recordedAudio.wavFilePath))
|
|
@@ -2126,20 +2229,20 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
}
|
|
|
wself.hadPrepareToPlayRecord = false
|
|
|
wself.currentPlayRecordIndex = -1
|
|
|
-// wself.recordPlayer.volume = 0
|
|
|
-// wself.assetPlayer.volume = wself.noSpeakVolume
|
|
|
+
|
|
|
+ wself.assetPlayer.volume = wself.originalVolume
|
|
|
+
|
|
|
BFLog(3, message: "播放结束")
|
|
|
didPlayToEndTime((shouldPlayRecordIndex, recordedAudio), newItem)
|
|
|
}
|
|
|
// recordPlayer.removeTimeObserver(recordPlayerTimeObserver as Any)
|
|
|
// recordPlayerTimeObserver?.invalidate()
|
|
|
//MARK: 声音播放器播放进度回调
|
|
|
- recordPlayerTimeObserver = recordPlayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 1000), queue: DispatchQueue.global()) { [weak self, weak recordPlayer] time in
|
|
|
- guard let wself = self, let rPlay = recordPlayer else {
|
|
|
- BFLog(3, message: "wself为空")
|
|
|
- return
|
|
|
+ recordPlayerTimeObserver = recordPlayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 1000), queue: DispatchQueue.global()) { [weak self] time in
|
|
|
+ guard let wself = self else { return }
|
|
|
+ if time.seconds > 0 {
|
|
|
+ wself.assetPlayer.volume = wself.originalVolume * 0.6
|
|
|
}
|
|
|
-// BFLog(1, message: "当前播放--- \(time.seconds), \(rPlay.currentItem?.duration.seconds ?? 0)")
|
|
|
if CMTimeGetSeconds(wself.currenStartPlayTime) <= 0 {
|
|
|
BFLog(message: "重新更新开始播放进度\(#function)-\(wself.currenStartPlayTime.seconds)")
|
|
|
wself.currenStartPlayTime = time
|
|
@@ -2147,14 +2250,11 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
let progressTime = CMTime(seconds: CMTimeGetSeconds(time) - CMTimeGetSeconds(wself.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 {
|
|
|
-// didPlayToEndTime((shouldPlayRecordIndex, recordedAudio), newItem)
|
|
|
-// }
|
|
|
} as? NSKeyValueObservation
|
|
|
}
|
|
|
if currMediaType == .Video {
|
|
|
videoMaterialRecordPlay(at: currentT, shouldPlayRecordIndex: shouldPlayRecordIndex, recordedAudio: recordedAudio)
|
|
|
- } else {
|
|
|
+ } else if currMediaType == .Image {
|
|
|
imageMaterialRecordPlay(at: currentT, shouldPlayRecordIndex: shouldPlayRecordIndex, recordedAudio: recordedAudio)
|
|
|
}
|
|
|
BFLog(1, message: "应当播放:\(shouldPlayRecordIndex), 当前播放:\(currentPlayRecordIndex)")
|
|
@@ -2198,8 +2298,6 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
if finished, wself.isNormalPlaying {
|
|
|
wself.recordPlayer.play()
|
|
|
-// wself.recordPlayer.volume = 1
|
|
|
-// wself.assetPlayer.volume = wself.haveSpeakVolume ?? 0
|
|
|
BFLog(1, message: "录音开始播放 playing, \(second), \(CMTimeGetSeconds(wself.recordPlayer.currentItem?.duration ?? .zero)), \(wself.recordPlayer.currentItem?.currentTime().seconds ?? 0)")
|
|
|
}
|
|
|
})
|
|
@@ -2253,7 +2351,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
BFLog(1, message: "开始播放 \(currentAssetProgress.seconds)")
|
|
|
recorderManager?.voiceModel = nil
|
|
|
events.append(WithDrawModel(type: 1, timestamp: currentAssetProgress, recordItem: rscurrentManager.recordItem!))
|
|
|
-
|
|
|
+
|
|
|
itemModels[currItemModelIndex].titleStickers.sort { m1, m2 in
|
|
|
CMTimeCompare(m1.timelineIn, m2.timelineIn) < 0
|
|
|
}
|
|
@@ -2280,16 +2378,21 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
rscurrentManager.currentAssetProgress = .zero
|
|
|
}
|
|
|
+
|
|
|
+ bgmPlayer.player.currentItem?.reversePlaybackEndTime = CMTime(seconds: bgmModel?.currentTime ?? 0.0, preferredTimescale: 1000)
|
|
|
+ bgmPlayer.player.volume = Float(choseMusicPanel.musicVolume) / 100.0
|
|
|
+ assetPlayer.volume = originalVolume
|
|
|
|
|
|
- rscurrentManager.play()
|
|
|
|
|
|
- subtitleBtn.isHidden = true
|
|
|
- voiceSettingBtn.isHidden = true
|
|
|
- soundSettingBtn.isHidden = true
|
|
|
- withDrawBtn.isHidden = true
|
|
|
- recordBtn.isHidden = true
|
|
|
- deleteRecordBtn.isHidden = true
|
|
|
+ if currItemModelIndex == 0 && currentAssetProgress == .zero{
|
|
|
+ bgmPlayer.player.seek(to: bgmPlayer.player.currentItem?.reversePlaybackEndTime ?? .zero ) {[weak self] _ in
|
|
|
+ self?.bgmPlayer.play()
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ bgmPlayer.play()
|
|
|
+ }
|
|
|
|
|
|
+ rscurrentManager.play()
|
|
|
}
|
|
|
|
|
|
public func pause() {
|
|
@@ -2298,6 +2401,9 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
assetPlayer.pause()
|
|
|
recordPlayer.pause()
|
|
|
+ bgmPlayer.pause()
|
|
|
+ rscurrentManager.pause()
|
|
|
+
|
|
|
recordStartPlayTime = CMTime.zero
|
|
|
pauseTime = currentAssetProgress.seconds
|
|
|
currentPlayRecordIndex = -1
|
|
@@ -2305,7 +2411,9 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
|
|
|
// 暂停状态
|
|
|
updatePlayBtnStatus()
|
|
|
- rscurrentManager.pause()
|
|
|
+ updateRecordBtnStatus()
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
public func fetchMaterial(_ phAsset:[PHAsset]) {
|
|
@@ -2425,10 +2533,10 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
if !wself.isRecording, wself.currItemModelIndex < (wself.itemModels.count - 1) {
|
|
|
} else {} //
|
|
|
|
|
|
- wself.isNormalPlaying = false
|
|
|
wself.isEndPlay = true
|
|
|
- wself.updatePlayBtnStatus()
|
|
|
-
|
|
|
+ wself.pause()
|
|
|
+
|
|
|
+ //add by ak 导入视频素材播放结束后主动调用一次基类的pause 停止背景音乐
|
|
|
|
|
|
if wself.isRecording {
|
|
|
wself.endRecord()
|
|
@@ -2452,7 +2560,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
|
guard let wself = self else { return }
|
|
|
|
|
|
- BFLog(message: "更新录音进度\(#function)-\(wself.currentAssetProgress.seconds )")
|
|
|
+ BFLog(message: "更新录音进度\(#function) - \(wself.currentAssetProgress.seconds )")
|
|
|
wself.progreddL.text = String(format: "%@", CMTimeGetSeconds(time).formatDurationToHMS())
|
|
|
let su = !wself.isDragingProgressSlder || wself.isRecording || wself.isNormalPlaying
|
|
|
if su { // 不拖动,正常播放和录音时更新进度条
|
|
@@ -2528,7 +2636,7 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
|
guard let wself = self else { return }
|
|
|
|
|
|
- BFLog(message: "更新录音进度\(#function)- \(wself.currentAssetProgress.seconds)")
|
|
|
+ BFLog(message: "更新录音进度\(#function) - \(wself.currentAssetProgress.seconds)")
|
|
|
wself.progreddL.text = String(format: "%@", CMTimeGetSeconds(wself.currentAssetProgress).formatDurationToHMS())
|
|
|
}
|
|
|
assetPlayer.seek(to: currentAssetProgress, toleranceBefore: CMTime(value: 1, timescale: 1_000_000), toleranceAfter: CMTime(value: 1, timescale: 1_000_000)) { _ in
|
|
@@ -2591,6 +2699,52 @@ public class BFRecordScreenController: BFBaseViewController {
|
|
|
imageRecordProgress(isRecord: true, progress: progress)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ func hadChoosed(music:PQVoiceModel?) {
|
|
|
+ bgmModel = music
|
|
|
+ bgmPlayer.replaceCurrentItem(musicPath: bgmModel?.musicPath)
|
|
|
+
|
|
|
+ if let model = music {
|
|
|
+
|
|
|
+ BFEventTrackAdaptor.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_musicChangerButton, pageSource: .sp_speekPage,extParams: ["musicID":bgmModel?.musicId ?? ""],commonParams: commonParams())
|
|
|
+
|
|
|
+ if let title = model.musicName {
|
|
|
+// addMusicBtn.setTitle(title, for: .normal)
|
|
|
+// addMusicBtn.kf.setImage(with: URL(string: model.avatarUrl), for: .normal)
|
|
|
+
|
|
|
+ addMusicBtn.config(title: title, imgUrl: URL(string: model.avatarUrl))
|
|
|
+ }else{
|
|
|
+// addMusicBtn.setTitle("选择音乐", for: .normal)
|
|
|
+// addMusicBtn.setImage(imageInRecordScreenKit(by: "addmusic"), for: .normal)
|
|
|
+ addMusicBtn.config()
|
|
|
+ }
|
|
|
+ // 设置music为背景音乐
|
|
|
+ hadDowonloadMusic(model: model)
|
|
|
+ }else {
|
|
|
+ addMusicBtn.config()
|
|
|
+ BFLog(1, message: "无效音乐")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func hadDowonloadMusic(model: PQVoiceModel) {
|
|
|
+ loadingView.isDownloadMusic = true
|
|
|
+ loadingView.loadShow()
|
|
|
+ if let path = model.musicPath {
|
|
|
+ PQDownloadManager.downLoadFile(url: path) { [weak self ]musicUrl, err in
|
|
|
+ guard let wself = self else { return }
|
|
|
+
|
|
|
+ if err == nil, musicUrl != nil {
|
|
|
+ model.wavFilePath = musicUrl
|
|
|
+ wself.loadingView.removeLoading()
|
|
|
+ }else{
|
|
|
+ cShowHUB(superView: wself.view, msg: "音乐下载失败,请重新尝试")
|
|
|
+ wself.bgmModel = nil
|
|
|
+// wself.addMusicBtn.setTitle("选择音乐", for: .normal)
|
|
|
+ wself.addMusicBtn.config()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
extension BFRecordScreenController: GPUImageMovieDelegate {
|
|
@@ -2632,6 +2786,11 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
|
|
|
cell = BFVideoCoverViewCell.gpuVideoViewCell(collectionView: collectionView, indexPath: indexPath)
|
|
|
case .Camera:
|
|
|
cell = BFCameraCoverViewCell.gpuCamraViewCell(collectionView: collectionView, indexPath: indexPath)
|
|
|
+ (cell as? BFCameraCoverViewCell)?.cameraFlip = {[weak self] in
|
|
|
+ guard let wself = self else { return }
|
|
|
+
|
|
|
+ wself.cameraFlipAction()
|
|
|
+ }
|
|
|
default:
|
|
|
break
|
|
|
}
|
|
@@ -2727,10 +2886,11 @@ extension BFRecordScreenController: UICollectionViewDelegate, UICollectionViewDa
|
|
|
|
|
|
func endScrollItem(page: Int) {
|
|
|
BFLog(1, message: "endScrollItem")
|
|
|
+ rscurrentManager.playBGMPlayer.pause()
|
|
|
// 切换素材时先把录制状态切为不可用,延迟可点,避免在缩略图未加载出来时即刻录制
|
|
|
+ pause()
|
|
|
currItemModelIndex = page
|
|
|
// 暂停
|
|
|
- pause()
|
|
|
//add by ak BFRecordScreenCameraManager 中的播放器也要暂停那里的进度回调也会刷新 UI 导致出现闪烁 BUG
|
|
|
rscmanager.pause()
|
|
|
|
|
@@ -3074,6 +3234,7 @@ extension BFRecordScreenController: BFTTSManagerDelegte{
|
|
|
|
|
|
if(isShowLoadView && !isFinish){
|
|
|
loadingView.loadShow()
|
|
|
+ loadingView.isDownloadMusic = false
|
|
|
}
|
|
|
|
|
|
return isFinish
|