123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- //
- // INVideoExportController.swift
- // Introduce
- //
- // Created by 胡志强 on 2021/11/29.
- //
- import Foundation
- import BFUIKit
- import Photos
- import BFRecordScreenKit
- import UIKit
- import BFCommonKit
- class INVideoExportController: BFBaseViewController {
-
- var videoAsset : AVURLAsset?
- var avplayerTimeObserver: NSKeyValueObservation?
- let backV = UIView()
- var hasExportAll = false
- var hasExportOnly = false
- var hasSaveAll = false
- var hasSaveOnly = false
- var saveAllUlr = URL(fileURLWithPath: "aaa")
- var saveOnlyUlr = URL(fileURLWithPath: "aaa")
- var isExporting = false
-
- // 播放进度
- 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 progressView : UIView = {
- let v = UIView()
- v.backgroundColor = ThemeStyleColor
- return v
- }()
-
- // 合成进度百分比lable
- lazy var progressL : UILabel = {
- let la = UILabel()
- la.textColor = .white
- la.textAlignment = .center
- la.text = "0%"
- la.font = UIFont.systemFont(ofSize: 28)
- la.shadowColor = .black
- la.shadowOffset = CGSize(width: 1, height: 1)
- return la
- }()
-
- 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 = {
- let btn = UIButton()
- btn.setImage(UIImage(named: "export_saveonly_n"), for: .normal)
- btn.setImage(UIImage(named: "export_saveonly_h"), for: .selected)
- btn.addTarget(self, action: #selector(saveOnlyAction(btn:)), for: .touchUpInside)
- btn.isSelected = true
- return btn
- }()
-
- lazy var exportBtn : UIButton = {
- let btn = UIButton()
- btn.setTitle(" 保存到相册", for: .normal)
- btn.setTitleColor(.white, for: .normal)
- btn.setImage(UIImage(named: "export_btn"), for: .normal)
- btn.backgroundColor = ThemeStyleColor
- btn.addCorner(roundingCorners: .allCorners, corner: 8)
- btn.addTarget(self, action: #selector(saveToPhotoNow), for: .touchUpInside)
- return btn
- }()
-
- lazy var bottomView:UIView = {
- let vv = UIView()
- vv.backgroundColor = .black
-
- return vv
- }()
-
- 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
- // 进度监控
- 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
- avplayer?.seek(to: CMTime.zero)
- }
-
- return avplayer
- }()
-
- lazy var export : BFRecordExport = {
- let export = BFRecordExport()
-
- 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.progressView.snp.updateConstraints { make in
- make.width.equalTo(cScreenWidth * CGFloat(progress))
- }
- }
- }
- }
-
- export.exportCompletion = {[weak self] (error, url) in
- DispatchQueue.main.async { [weak self] in
- guard let sself = self else {
- return
- }
- self?.isExporting = false
- sself.bottomView.isHidden = false
- 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
- }
- }
- }
- }
- return export
- }()
-
- deinit {
- avplayerTimeObserver?.invalidate()
- NotificationCenter.default.removeObserver(self)
- }
-
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
- showNavigation()
- }
-
- override func backBtnClick() {
- if !(hasExportAll || hasExportOnly) {
-
- }
- export.cancelExport()
- super.backBtnClick()
- }
- override func viewDidLoad() {
- super.viewDidLoad()
- 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
- self?.exportNow()
- }
- }
-
- 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)
-
- 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, *) {
- make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)
- } else {
- make.bottom.equalToSuperview()
- }
- }
-
- exportBtn.snp.makeConstraints { make in
- make.left.equalTo(saveAllBtn)
- make.right.equalTo(saveOnlyBtn)
- make.height.equalTo(50)
- make.bottom.equalTo(-40)
- }
-
- 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
- playerLayer.frame = self!.backV.bounds
- }
- }
-
- //MARK: - 按钮事件
-
- func exportNow(){
- if bottomView.isHidden {
- cShowHUB(superView: nil, msg: "正在合成中。。。")
- return
- }
- bottomView.isHidden = true
- progressView.isHidden = false
- progressL.isHidden = false
- progreddL.isHidden = true
- export.startExprot(synthesisAll:saveAllBtn.isSelected)
-
- }
-
- @objc func saveToPhotoNow(){
- if (self.saveAllBtn.isSelected && self.hasSaveAll) || self.saveOnlyBtn.isSelected && self.hasSaveOnly {
- cShowHUB(superView: nil, msg: "已保存过了")
- return
- }
- if let url = (avplayer.currentItem?.asset as? AVURLAsset)?.url{
- PHPhotoLibrary.shared().performChanges {
- PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url)
- } completionHandler: { isFinished, _ in
- if isFinished {
- DispatchQueue.main.async {
- cShowHUB(superView: nil, msg: "保存成功")
- }
- if self.saveAllBtn.isSelected {
- self.hasSaveAll = true
- }else if self.saveOnlyBtn.isSelected {
- self.hasSaveOnly = true
- }
- }
- }
- }
- }
-
- @objc func saveAllAction(btn:UIButton){
- if btn.isSelected {
- return
- }
- btn.isSelected = true
- saveOnlyBtn.isSelected = false
- avplayer.pause()
- if !hasExportAll{
- exportNow()
- }else{
- let item = AVPlayerItem(url: saveAllUlr)
- avplayer.replaceCurrentItem(with: item)
- avplayer.play()
- }
- }
-
- @objc func saveOnlyAction(btn:UIButton){
- if btn.isSelected {
- return
- }
- btn.isSelected = true
- saveAllBtn.isSelected = false
- avplayer.pause()
- if !hasExportOnly {
- exportNow()
- }else{
- let item = AVPlayerItem(url: saveOnlyUlr)
- avplayer.replaceCurrentItem(with: item)
- avplayer.play()
- }
- }
-
- @objc func play(){
- if isExporting {
- self.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()
- }
- }
- }
- }
|