|
@@ -5,16 +5,14 @@
|
|
|
// Created by 胡志强 on 2021/11/29.
|
|
|
//
|
|
|
|
|
|
-import Foundation
|
|
|
+import BFCommonKit
|
|
|
+import BFRecordScreenKit
|
|
|
import BFUIKit
|
|
|
+import Foundation
|
|
|
import Photos
|
|
|
-import BFRecordScreenKit
|
|
|
import UIKit
|
|
|
-import BFCommonKit
|
|
|
-
|
|
|
|
|
|
class INVideoExportController: BFBaseViewController {
|
|
|
-
|
|
|
var avplayerTimeObserver: NSKeyValueObservation?
|
|
|
let backV = UIView()
|
|
|
var hasExportAll = false
|
|
@@ -24,9 +22,9 @@ class INVideoExportController: BFBaseViewController {
|
|
|
var saveAllUlr = URL(fileURLWithPath: "aaa")
|
|
|
var saveOnlyUlr = URL(fileURLWithPath: "aaa")
|
|
|
var isExporting = false
|
|
|
-
|
|
|
+
|
|
|
// 播放进度
|
|
|
- lazy var progreddL : UILabel = {
|
|
|
+ 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)
|
|
@@ -35,16 +33,16 @@ class INVideoExportController: BFBaseViewController {
|
|
|
l.shadowOffset = CGSize(width: 1, height: 1)
|
|
|
return l
|
|
|
}()
|
|
|
-
|
|
|
+
|
|
|
// 合成进度指示条
|
|
|
- lazy var progressView : UIView = {
|
|
|
+ lazy var progressView: UIView = {
|
|
|
let v = UIView()
|
|
|
v.backgroundColor = ThemeStyleColor
|
|
|
return v
|
|
|
}()
|
|
|
-
|
|
|
+
|
|
|
// 合成进度百分比lable
|
|
|
- lazy var progressL : UILabel = {
|
|
|
+ lazy var progressL: UILabel = {
|
|
|
let la = UILabel()
|
|
|
la.textColor = .white
|
|
|
la.textAlignment = .center
|
|
@@ -54,16 +52,16 @@ class INVideoExportController: BFBaseViewController {
|
|
|
la.shadowOffset = CGSize(width: 1, height: 1)
|
|
|
return la
|
|
|
}()
|
|
|
-
|
|
|
- lazy var saveAllBtn:UIButton = {
|
|
|
+
|
|
|
+ lazy var saveAllBtn: UIButton = {
|
|
|
let btn = UIButton()
|
|
|
btn.setImage(UIImage(named: "export_saveall_n"), for: .normal)
|
|
|
btn.setImage(UIImage(named: "export_saveall_h"), for: .selected)
|
|
|
btn.addTarget(self, action: #selector(saveAllAction(btn:)), for: .touchUpInside)
|
|
|
return btn
|
|
|
}()
|
|
|
-
|
|
|
- lazy var saveOnlyBtn:UIButton = {
|
|
|
+
|
|
|
+ lazy var saveOnlyBtn: UIButton = {
|
|
|
let btn = UIButton()
|
|
|
btn.setImage(UIImage(named: "export_saveonly_n"), for: .normal)
|
|
|
btn.setImage(UIImage(named: "export_saveonly_h"), for: .selected)
|
|
@@ -71,16 +69,16 @@ class INVideoExportController: BFBaseViewController {
|
|
|
btn.isSelected = true
|
|
|
return btn
|
|
|
}()
|
|
|
-
|
|
|
- lazy var completeBtn : UIButton = {
|
|
|
+
|
|
|
+ lazy var completeBtn: UIButton = {
|
|
|
let btn = UIButton()
|
|
|
btn.setTitle("完成", for: .normal)
|
|
|
btn.setTitleColor(UIColor.hexColor(hexadecimal: "#B1B1B1"), for: .normal)
|
|
|
btn.addTarget(self, action: #selector(completeAction), for: .touchUpInside)
|
|
|
return btn
|
|
|
}()
|
|
|
-
|
|
|
- lazy var exportBtn : UIButton = {
|
|
|
+
|
|
|
+ lazy var exportBtn: UIButton = {
|
|
|
let btn = UIButton()
|
|
|
btn.setTitle(" 保存到相册", for: .normal)
|
|
|
btn.setTitleColor(.white, for: .normal)
|
|
@@ -90,49 +88,48 @@ class INVideoExportController: BFBaseViewController {
|
|
|
btn.addTarget(self, action: #selector(saveToPhotoNow), for: .touchUpInside)
|
|
|
return btn
|
|
|
}()
|
|
|
-
|
|
|
- lazy var bottomView:UIView = {
|
|
|
+
|
|
|
+ lazy var bottomView: UIView = {
|
|
|
let vv = UIView()
|
|
|
vv.backgroundColor = .black
|
|
|
vv.isHidden = true
|
|
|
return vv
|
|
|
}()
|
|
|
-
|
|
|
- lazy var avplayer : AVPlayer = {
|
|
|
+
|
|
|
+ lazy var avplayer: AVPlayer = {
|
|
|
let avplayer = AVPlayer()
|
|
|
- avplayerTimeObserver = avplayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 100), queue: DispatchQueue.global()) {[weak self, weak avplayer] time in
|
|
|
- // 进度监控
|
|
|
+ avplayerTimeObserver = avplayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 100), queue: DispatchQueue.global()) { [weak self, weak avplayer] time in
|
|
|
+ // 进度监控
|
|
|
if let item = avplayer?.currentItem {
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
|
self?.progreddL.text = String(format: "%@ / %@", CMTimeGetSeconds(time).formatDurationToHMS(), CMTimeGetSeconds(item.duration).formatDurationToHMS())
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
} as? NSKeyValueObservation
|
|
|
-
|
|
|
- NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: avplayer.currentItem, queue: .main) { [weak avplayer] notify in
|
|
|
+
|
|
|
+ NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: avplayer.currentItem, queue: .main) { [weak avplayer] _ in
|
|
|
avplayer?.seek(to: CMTime.zero)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return avplayer
|
|
|
}()
|
|
|
-
|
|
|
- lazy var export : BFRecordExport = {
|
|
|
+
|
|
|
+ lazy var export: BFRecordExport = {
|
|
|
let export = BFRecordExport()
|
|
|
-
|
|
|
- export.progress = {[weak self] progress in
|
|
|
+
|
|
|
+ export.progress = { [weak self] progress in
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
|
if let sself = self {
|
|
|
// let width = export.data?.first?.width ?? 0
|
|
|
- sself.progressL.text = String(format: "%d%%", Int(progress*100))
|
|
|
+ sself.progressL.text = String(format: "%d%%", Int(progress * 100))
|
|
|
sself.progressView.snp.updateConstraints { make in
|
|
|
make.width.equalTo(cScreenWidth * CGFloat(progress))
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- export.exportCompletion = {[weak self] (error, url) in
|
|
|
+
|
|
|
+ export.exportCompletion = { [weak self] _, url in
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
|
guard let sself = self else {
|
|
|
return
|
|
@@ -144,17 +141,17 @@ class INVideoExportController: BFBaseViewController {
|
|
|
sself.progreddL.isHidden = false
|
|
|
sself.progressView.isHidden = true
|
|
|
sself.progressL.isHidden = true
|
|
|
-
|
|
|
+
|
|
|
if let fileUrl = url {
|
|
|
let item = AVPlayerItem(url: fileUrl)
|
|
|
sself.avplayer.replaceCurrentItem(with: item)
|
|
|
sself.avplayer.play()
|
|
|
-
|
|
|
+
|
|
|
if sself.saveAllBtn.isSelected {
|
|
|
sself.saveAllUlr = fileUrl
|
|
|
sself.hasExportAll = true
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if sself.saveOnlyBtn.isSelected {
|
|
|
sself.saveOnlyUlr = fileUrl
|
|
|
sself.hasExportOnly = true
|
|
@@ -164,27 +161,24 @@ class INVideoExportController: BFBaseViewController {
|
|
|
}
|
|
|
return export
|
|
|
}()
|
|
|
-
|
|
|
+
|
|
|
deinit {
|
|
|
avplayerTimeObserver?.invalidate()
|
|
|
NotificationCenter.default.removeObserver(self)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
override func viewWillAppear(_ animated: Bool) {
|
|
|
super.viewWillAppear(animated)
|
|
|
showNavigation()
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
override func viewWillDisappear(_ animated: Bool) {
|
|
|
super.viewWillDisappear(animated)
|
|
|
UIApplication.shared.isIdleTimerDisabled = false
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
override func backBtnClick() {
|
|
|
- if !(hasExportAll || hasExportOnly) {
|
|
|
-
|
|
|
- }
|
|
|
+ if !(hasExportAll || hasExportOnly) {}
|
|
|
export.cancelExport()
|
|
|
super.backBtnClick()
|
|
|
}
|
|
@@ -194,62 +188,59 @@ class INVideoExportController: BFBaseViewController {
|
|
|
view.backgroundColor = .black
|
|
|
navHeadImageView?.backgroundColor = .black
|
|
|
leftButton(image: nil, imageName: nil, tintColor: UIColor.white)
|
|
|
-
|
|
|
+
|
|
|
// backV.frame = CGRect(x: 0, y: navHeadImageView?.bottomY ?? 0, width: cScreenWidth, height: cScreenWidth)
|
|
|
backV.backgroundColor = .clear
|
|
|
backV.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(play)))
|
|
|
|
|
|
-
|
|
|
addSubviews()
|
|
|
-
|
|
|
+
|
|
|
// export.startExprot()
|
|
|
|
|
|
- DispatchQueue.main.asyncAfter(deadline: .now()+0.2) {[weak self] in
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
|
|
|
self?.exportNow()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- func addSubviews(){
|
|
|
-
|
|
|
+
|
|
|
+ func addSubviews() {
|
|
|
view.addSubview(backV)
|
|
|
view.addSubview(bottomView)
|
|
|
-
|
|
|
+
|
|
|
let playerLayer = AVPlayerLayer(player: avplayer)
|
|
|
backV.layer.addSublayer(playerLayer)
|
|
|
-
|
|
|
+
|
|
|
backV.addSubview(progressView)
|
|
|
backV.addSubview(progressL)
|
|
|
backV.addSubview(progreddL)
|
|
|
-
|
|
|
+
|
|
|
bottomView.addSubview(saveAllBtn)
|
|
|
bottomView.addSubview(saveOnlyBtn)
|
|
|
bottomView.addSubview(exportBtn)
|
|
|
bottomView.addSubview(completeBtn)
|
|
|
-
|
|
|
+
|
|
|
backV.snp.makeConstraints { make in
|
|
|
make.left.right.equalToSuperview()
|
|
|
make.top.equalTo(navHeadImageView!.snp.bottom)
|
|
|
make.bottom.equalTo(bottomView.snp.top)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
progressView.snp.makeConstraints { make in
|
|
|
make.left.top.height.equalToSuperview()
|
|
|
make.width.equalTo(0)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
progressL.snp.makeConstraints { make in
|
|
|
make.center.width.equalToSuperview()
|
|
|
make.height.equalTo(20)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
progreddL.snp.makeConstraints { make in
|
|
|
make.bottom.equalToSuperview().offset(-10)
|
|
|
make.centerX.equalTo(backV)
|
|
|
make.width.equalTo(100)
|
|
|
make.height.equalTo(20)
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
bottomView.snp.makeConstraints { make in
|
|
|
make.left.right.equalToSuperview()
|
|
|
if #available(iOS 11.0, *) {
|
|
@@ -258,61 +249,60 @@ class INVideoExportController: BFBaseViewController {
|
|
|
make.bottom.equalToSuperview()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
completeBtn.snp.makeConstraints { make in
|
|
|
make.left.right.equalTo(exportBtn)
|
|
|
make.bottom.equalTo(-1 * cSafeAreaHeight - 3)
|
|
|
make.height.equalTo(20)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
exportBtn.snp.makeConstraints { make in
|
|
|
make.left.equalTo(saveAllBtn)
|
|
|
make.right.equalTo(saveOnlyBtn)
|
|
|
make.height.equalTo(50)
|
|
|
make.bottom.equalTo(completeBtn.snp.top).offset(-10)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
saveAllBtn.snp.makeConstraints { make in
|
|
|
make.left.equalTo(16)
|
|
|
make.bottom.equalTo(exportBtn.snp.top).offset(-21)
|
|
|
make.height.equalTo(70)
|
|
|
make.top.equalTo(28)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
saveOnlyBtn.snp.makeConstraints { make in
|
|
|
make.left.equalTo(saveAllBtn.snp.right).offset(16)
|
|
|
make.top.height.width.equalTo(saveAllBtn)
|
|
|
make.right.equalTo(-16)
|
|
|
}
|
|
|
-
|
|
|
- DispatchQueue.main.asyncAfter(deadline: .now()+0) {[weak self] in
|
|
|
+
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0) { [weak self] in
|
|
|
playerLayer.frame = self!.backV.bounds
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
- //MARK: - 按钮事件
|
|
|
-
|
|
|
- func exportNow(){
|
|
|
- if isExporting {
|
|
|
- cShowHUB(superView: nil, msg: "正在合成中。。。")
|
|
|
- return
|
|
|
- }
|
|
|
- bottomView.isHidden = true
|
|
|
- progressView.isHidden = false
|
|
|
- progressL.isHidden = false
|
|
|
- progreddL.isHidden = true
|
|
|
- export.startExprot(synthesisAll:saveAllBtn.isSelected)
|
|
|
- isExporting = true
|
|
|
- UIApplication.shared.isIdleTimerDisabled = true
|
|
|
+
|
|
|
+ // MARK: - 按钮事件
|
|
|
+
|
|
|
+ func exportNow() {
|
|
|
+ if isExporting {
|
|
|
+ cShowHUB(superView: nil, msg: "正在合成中。。。")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ bottomView.isHidden = true
|
|
|
+ progressView.isHidden = false
|
|
|
+ progressL.isHidden = false
|
|
|
+ progreddL.isHidden = true
|
|
|
+ export.startExprot(synthesisAll: saveAllBtn.isSelected)
|
|
|
+ isExporting = true
|
|
|
+ UIApplication.shared.isIdleTimerDisabled = true
|
|
|
}
|
|
|
-
|
|
|
- @objc func saveToPhotoNow(){
|
|
|
- if (self.saveAllBtn.isSelected && self.hasSaveAll) || self.saveOnlyBtn.isSelected && self.hasSaveOnly {
|
|
|
+
|
|
|
+ @objc func saveToPhotoNow() {
|
|
|
+ if (saveAllBtn.isSelected && hasSaveAll) || saveOnlyBtn.isSelected && hasSaveOnly {
|
|
|
cShowHUB(superView: nil, msg: "已保存过了")
|
|
|
return
|
|
|
}
|
|
|
- if let url = (avplayer.currentItem?.asset as? AVURLAsset)?.url{
|
|
|
+ if let url = (avplayer.currentItem?.asset as? AVURLAsset)?.url {
|
|
|
PHPhotoLibrary.shared().performChanges {
|
|
|
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url)
|
|
|
} completionHandler: { isFinished, _ in
|
|
@@ -322,31 +312,31 @@ class INVideoExportController: BFBaseViewController {
|
|
|
}
|
|
|
if self.saveAllBtn.isSelected {
|
|
|
self.hasSaveAll = true
|
|
|
- }else if self.saveOnlyBtn.isSelected {
|
|
|
+ } else if self.saveOnlyBtn.isSelected {
|
|
|
self.hasSaveOnly = true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- @objc func saveAllAction(btn:UIButton){
|
|
|
+
|
|
|
+ @objc func saveAllAction(btn: UIButton) {
|
|
|
if btn.isSelected {
|
|
|
return
|
|
|
}
|
|
|
btn.isSelected = true
|
|
|
saveOnlyBtn.isSelected = false
|
|
|
avplayer.pause()
|
|
|
- if !hasExportAll{
|
|
|
+ if !hasExportAll {
|
|
|
exportNow()
|
|
|
- }else{
|
|
|
+ } else {
|
|
|
let item = AVPlayerItem(url: saveAllUlr)
|
|
|
avplayer.replaceCurrentItem(with: item)
|
|
|
avplayer.play()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- @objc func saveOnlyAction(btn:UIButton){
|
|
|
+
|
|
|
+ @objc func saveOnlyAction(btn: UIButton) {
|
|
|
if btn.isSelected {
|
|
|
return
|
|
|
}
|
|
@@ -355,31 +345,32 @@ class INVideoExportController: BFBaseViewController {
|
|
|
avplayer.pause()
|
|
|
if !hasExportOnly {
|
|
|
exportNow()
|
|
|
- }else{
|
|
|
+ } else {
|
|
|
let item = AVPlayerItem(url: saveOnlyUlr)
|
|
|
avplayer.replaceCurrentItem(with: item)
|
|
|
avplayer.play()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- @objc func completeAction(){
|
|
|
+
|
|
|
+ @objc func completeAction() {
|
|
|
// MARK: 删除所有录制资源. 现在放在了选择相册展示时清理cache
|
|
|
+
|
|
|
// export.clearFileCache()
|
|
|
// try? FileManager.default.removeItem(at: self.saveAllUlr)
|
|
|
// try? FileManager.default.removeItem(at: self.saveOnlyUlr)
|
|
|
- self.navigationController?.popToRootViewController(animated: true)
|
|
|
+ navigationController?.popToRootViewController(animated: true)
|
|
|
}
|
|
|
-
|
|
|
- @objc func play(){
|
|
|
+
|
|
|
+ @objc func play() {
|
|
|
if isExporting {
|
|
|
- self.avplayer.pause()
|
|
|
+ avplayer.pause()
|
|
|
return
|
|
|
}
|
|
|
- if self.avplayer.currentItem != nil {
|
|
|
- if self.avplayer.timeControlStatus == .playing {
|
|
|
- self.avplayer.pause()
|
|
|
- }else if self.avplayer.timeControlStatus == .paused{
|
|
|
- self.avplayer.play()
|
|
|
+ if avplayer.currentItem != nil {
|
|
|
+ if avplayer.timeControlStatus == .playing {
|
|
|
+ avplayer.pause()
|
|
|
+ } else if avplayer.timeControlStatus == .paused {
|
|
|
+ avplayer.play()
|
|
|
}
|
|
|
}
|
|
|
}
|