PublishNewVideoPhotoView.swift 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. //
  2. // PublishNewVideoPhotoView.swift
  3. // RainbowPlanet
  4. //
  5. // Created by 南鑫林 on 2019/9/3.
  6. // Copyright © 2019 RainbowPlanet. All rights reserved.
  7. //
  8. import UIKit
  9. // MARK: - 初始化/action
  10. class PublishNewVideoPhotoView: BaseView {
  11. /// 销毁View
  12. deinit {
  13. NXLLog("deinit")
  14. if observe != nil {
  15. NotificationCenter.default.removeObserver(observe!)
  16. }
  17. }
  18. weak var observe : NSObjectProtocol?
  19. /// 录制的时长
  20. var recorderDuration: CGFloat = 0.0
  21. /// 录制最大时长
  22. let maxDuration : CGFloat = 60.0
  23. /// 录制最小时长
  24. let minDuration : CGFloat = 3.0
  25. /// 滤镜选中的selected
  26. var selectedIndex : Int = 0
  27. /// 是否完成录制
  28. var isFinishRecorder : Bool = false
  29. /// 添加View
  30. override func setupViews() {
  31. backgroundColor = UIColor.black
  32. addSubview(recorderPreview)
  33. addSubview(publishNewVideoPhotoSetView)
  34. addSubview(effectFilterBeautyView)
  35. addSubview(musicView)
  36. }
  37. /// 布局
  38. override func setupLayouts() {
  39. publishNewVideoPhotoSetView.snp.makeConstraints { (make) in
  40. make.edges.equalToSuperview()
  41. }
  42. }
  43. /// 设置数据
  44. override func setupData() {
  45. // 返回
  46. publishNewVideoPhotoSetView.closeButton.rx.tap.subscribe(onNext: { [weak self] (data) in
  47. self?.recorder?.stopPreview()
  48. let vc = UIViewController.topMost
  49. vc?.navigationController?.dismiss(animated: true, completion: nil)
  50. }).disposed(by: disposeBag)
  51. // 翻转
  52. publishNewVideoPhotoSetView.cameraFlipButton.rx.tap.subscribe(onNext: {[weak self] (data) in
  53. self?.setCameraFlip()
  54. }).disposed(by: disposeBag)
  55. // 滤镜
  56. publishNewVideoPhotoSetView.filterButton.rx.tap.subscribe(onNext: {[weak self] (data) in
  57. self?.effectFilterBeautyView.filterBeautyType = .filter
  58. self?.effectFilterBeautyViewisHidden(isHidden: false)
  59. }).disposed(by: disposeBag)
  60. // 美颜
  61. publishNewVideoPhotoSetView.beautyButton.rx.tap.subscribe(onNext: {[weak self] (data) in
  62. self?.effectFilterBeautyView.filterBeautyType = .beauty
  63. self?.effectFilterBeautyViewisHidden(isHidden: false)
  64. }).disposed(by: disposeBag)
  65. // 音乐
  66. publishNewVideoPhotoSetView.musicButton.rx.tap.subscribe(onNext: {[weak self] (data) in
  67. self?.musicViewisHidden(isHidden: false)
  68. }).disposed(by: disposeBag)
  69. // 闪光灯
  70. publishNewVideoPhotoSetView.flashButton.rx.tap.subscribe(onNext: {[weak self] (data) in
  71. if self?.recorder?.torchMode == .auto {
  72. self?.recorder?.switchTorch(with: AliyunIRecorderTorchMode.on)
  73. self?.publishNewVideoPhotoSetView.flashButton.setImage(kImage(name: "video_ico_flashlight"), for: UIControl.State.normal)
  74. } else if self?.recorder?.torchMode == .on {
  75. self?.recorder?.switchTorch(with: AliyunIRecorderTorchMode.off)
  76. self?.publishNewVideoPhotoSetView.flashButton.setImage(kImage(name: "video_ico_flashlight_close"), for: UIControl.State.normal)
  77. } else if self?.recorder?.torchMode == .off {
  78. self?.recorder?.switchTorch(with: AliyunIRecorderTorchMode.auto)
  79. self?.publishNewVideoPhotoSetView.flashButton.setImage(kImage(name: "video_ico_flashlight_auto"), for: UIControl.State.normal)
  80. }
  81. }).disposed(by: disposeBag)
  82. //录制/拍摄
  83. publishNewVideoPhotoSetView.recordButton.rx.tap.subscribe(onNext: { [weak self] (data) in
  84. // 开始录制/暂停录制
  85. if PublishNewViewModel.shared.publishNewRecorderType == .video {
  86. if (self?.publishNewVideoPhotoSetView.recordButton.isSelected)! { //暂停拍摄
  87. self?.stopTakeVideo()
  88. }else { //开始拍摄
  89. self?.startTakeVideo()
  90. }
  91. }
  92. // 拍照
  93. if PublishNewViewModel.shared.publishNewRecorderType == .photo {
  94. // 拍照
  95. self?.takePhoto()
  96. //切换按钮状态
  97. self?.publishNewVideoPhotoSetView.recordButton.isSelected = false
  98. }
  99. }).disposed(by: disposeBag)
  100. // 回删视频
  101. publishNewVideoPhotoSetView.deleteButton.rx.tap.subscribe(onNext: { [weak self] (data) in
  102. /// 回删视频
  103. self?.deleteVideo()
  104. }).disposed(by: disposeBag)
  105. // 完成录制
  106. publishNewVideoPhotoSetView.finishButton.rx.tap.subscribe(onNext: { [weak self] (data) in
  107. //完成录制的view
  108. self?.finishRecorderView()
  109. if self?.recorder?.isRecording ?? true {
  110. // 完成录制需要先掉用停止录制在走delegate
  111. self?.stopTakeVideo()
  112. }else {
  113. self?.finishTakeVideo()
  114. }
  115. }).disposed(by: disposeBag)
  116. // 左滑 滤镜 加 1
  117. publishNewVideoPhotoSetView.leftSwipeClosure = {
  118. [weak self] in
  119. self?.filterPlus()
  120. }
  121. // 右滑 滤镜 减 1
  122. publishNewVideoPhotoSetView.rightSwipeClosure = {
  123. [weak self] in
  124. self?.filterLess()
  125. }
  126. // 美颜等级设置
  127. effectFilterBeautyView.effectBeautyView.didSelectCloSure = {
  128. [weak self] beautifyValue in
  129. self?.recorder?.beautifyValue = beautifyValue
  130. }
  131. // 美颜滤镜设置
  132. effectFilterBeautyView.effectFilterView.didSelectCloSure = {
  133. [weak self] (index, aliyunEffectFilter) in
  134. self?.selectedIndex = index
  135. if index == 0 {
  136. self?.recorder?.deleteFilter()
  137. }else {
  138. self?.recorder?.apply(aliyunEffectFilter)
  139. }
  140. self?.showFilterNameLabel(aliyunEffectFilter: aliyunEffectFilter)
  141. }
  142. // 关闭音乐按钮
  143. musicView.closeButton.rx.tap.subscribe(onNext: { [weak self] (data) in
  144. PublishNewMusicView.publishNewMusicSelectedIndexPath = nil
  145. self?.musicViewisHidden(isHidden: true)
  146. }).disposed(by: disposeBag)
  147. // 不使用音乐按钮
  148. musicView.noUseMusicButton.rx.tap.subscribe(onNext: { [weak self] (data) in
  149. PublishNewMusicView.publishNewMusicSelectedIndexPath = nil
  150. PublishNewMusicView.publishNewMusicUseIndexPath = nil
  151. let effectMusic : AliyunEffectMusic? = nil
  152. self?.recorder?.apply(effectMusic)
  153. self?.musicViewisHidden(isHidden: true)
  154. }).disposed(by: disposeBag)
  155. // 使用音乐
  156. musicView.userMusicClosure = {
  157. [weak self] in
  158. if PublishNewMusicView.publishNewMusicUseURL?.path == nil {
  159. PublishNewMusicView.publishNewMusicUseIndexPath = nil
  160. self?.musicViewisHidden(isHidden: true)
  161. SwiftProgressHUD.shared().showText("使用音乐错误,请您重新选择!!!")
  162. }else {
  163. PublishNewMusicView.publishNewMusicSelectedIndexPath = nil
  164. self?.recorder?.apply(AliyunEffectMusic(file: PublishNewMusicView.publishNewMusicUseURL?.path))
  165. self?.musicViewisHidden(isHidden: true)
  166. }
  167. }
  168. // 左滑 滤镜 加 1
  169. recorderPreview.leftSwipeClosure = {
  170. [weak self] in
  171. self?.filterPlus()
  172. }
  173. // 右滑 滤镜 减 1
  174. recorderPreview.rightSwipeClosure = {
  175. [weak self] in
  176. self?.filterLess()
  177. }
  178. // 点击手势
  179. recorderPreview.tapClosure = {
  180. [weak self] in
  181. if self?.effectFilterBeautyView.alpha == 1 {
  182. // 隐藏滤镜
  183. self?.effectFilterBeautyViewisHidden(isHidden: true)
  184. }
  185. if self?.musicView.alpha == 1 {
  186. // 隐藏音乐
  187. self?.musicViewisHidden(isHidden: true)
  188. }
  189. }
  190. // 对于锁屏,来电,退后台等事件,需要进行特殊处理。
  191. //当进入Inactive状态前需要调
  192. observe = NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: OperationQueue.main) {[weak self] (_) in
  193. if self?.recorder?.isRecording ?? true {
  194. self?.stopTakeVideo()
  195. }
  196. self?.recorder?.stopPreview()
  197. }
  198. // 当进入Active状态
  199. observe = NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: OperationQueue.main) {[weak self] (_) in
  200. self?.recorder?.stopPreview()
  201. }
  202. }
  203. /// SDK录制类
  204. lazy var recorder: AliyunIRecorder? = {
  205. let recorder = AliyunIRecorder.init(delegate: self, videoSize: CGSize(width: 720, height: 1280))
  206. // 预览View
  207. recorder?.preview = recorderPreview
  208. //创建文件夹路径
  209. let taskPathUrl =
  210. PathURLManager.projectDateFormatPath(dateFormat: "yyyyMM", parentURL:
  211. PathURLManager.projectVideosPath(parentURL:
  212. PathURLManager.projectResourcesPath(parentURL:
  213. PathURLManager.projectRecordssPath(parentURL:
  214. PathURLManager.projectDocumentPath()))))!
  215. //清除录制路径
  216. PathURLManager.clearPath(pathURL: taskPathUrl)
  217. // 设置文件夹路径
  218. recorder?.taskPath = taskPathUrl.path
  219. // 设置录制视频输出路径
  220. let outputPathUrl =
  221. PathURLManager.projectPathExtensionMp4(parentURL:
  222. PathURLManager.projectFilePath(fileName:
  223. PathURLManager.randomString(), parentURL:
  224. PathURLManager.projectDateFormatPath(dateFormat: "yyyyMM", parentURL:
  225. PathURLManager.projectVideosPath(parentURL:
  226. PathURLManager.projectResourcesPath(parentURL:
  227. PathURLManager.projectRecordssPath(parentURL:
  228. PathURLManager.projectDocumentPath()))))))!
  229. // 设置录制视频输出路径
  230. recorder?.outputPath = outputPathUrl.path
  231. //循环切换手电筒模式手电筒模式有三种,分别是off,on和auto。切换顺序:off —-> on —-> auto。默认值:off。
  232. recorder?.switchTorch(with: AliyunIRecorderTorchMode.off)
  233. // 美颜状态
  234. recorder?.beautifyStatus = true;
  235. // 设置美颜度 [0,100]
  236. recorder?.beautifyValue = 50
  237. // 前置摄像头采集分辨率 默认:AVCaptureSessionPreset1280x720
  238. recorder?.frontCaptureSessionPreset = AVCaptureSession.Preset.hd1280x720.rawValue
  239. // 后置摄像头采集分辨率 默认:AVCaptureSessionPreset1280x720
  240. recorder?.backCaptureSessionPreset = AVCaptureSession.Preset.hd1280x720.rawValue
  241. // 设置摄像头角度
  242. recorder?.cameraRotate = 0
  243. // 设置编码方式 0软编 1硬编
  244. recorder?.encodeMode = 0
  245. // 设置关键帧间隔
  246. recorder?.gop = 5
  247. // 设置关键帧间隔
  248. recorder?.recordFps = 25
  249. // 设置是否静音
  250. recorder?.mute = false
  251. // 设置视频质量 如果设置了bitrate参数,那么当前设置无效。
  252. recorder?.videoQuality = .hight
  253. // 设置输出视频码率(bps)
  254. recorder?.bitrate = 2000000
  255. // 设置采集视频格式
  256. recorder?.outputType = .type420f
  257. // 设置视频最大时长 默认8
  258. recorder?.clipManager.maxDuration = maxDuration
  259. // 设置视频最小时长 默认8
  260. recorder?.clipManager.minDuration = minDuration
  261. return recorder!
  262. }()
  263. /// 摄像头
  264. lazy var recorderPreview : PublishNewRecorderPreview = {
  265. let recorderPreview = PublishNewRecorderPreview(frame: kScreenBounds)
  266. return recorderPreview
  267. }()
  268. /// 所有按钮View
  269. lazy var publishNewVideoPhotoSetView: PublishNewVideoPhotoSetView = {
  270. let publishNewVideoPhotoSetView = PublishNewVideoPhotoSetView()
  271. return publishNewVideoPhotoSetView
  272. }()
  273. /// 滤镜跟美颜
  274. lazy var effectFilterBeautyView: PublishNewEffectFilterBeautyView = {
  275. let effectFilterBeautyView = PublishNewEffectFilterBeautyView(frame: CGRect(x: 0, y: kScreenHeight, width: kScreenWidth, height: 48 + 125 + kSafeTabBarHeight))
  276. return effectFilterBeautyView
  277. }()
  278. /// 音乐
  279. lazy var musicView : PublishNewMusicView = {
  280. let musicView = PublishNewMusicView(frame: CGRect(x: 0, y: kScreenHeight, width: kScreenWidth, height: kScreenHeight - kSafeStatusBarHeight))
  281. return musicView
  282. }()
  283. }
  284. // MARK: - 方法
  285. extension PublishNewVideoPhotoView {
  286. /// 开始拍视频
  287. func startTakeVideo() {
  288. self.recorder?.startRecording()
  289. DispatchQueue.main.async {
  290. [weak self] in
  291. // 回删按钮隐藏
  292. self?.deleteAlpha(alpha: 0)
  293. // 分段view隐藏
  294. self?.segmentedViewAlpha(alpha: 0)
  295. // 开始录制隐藏View
  296. self?.startTakeVideoHiddenView()
  297. }
  298. }
  299. /// 暂停拍视频
  300. func stopTakeVideo() {
  301. self.recorder?.stopRecording()
  302. }
  303. /// 开始录制隐藏View
  304. func startTakeVideoHiddenView() {
  305. publishNewVideoPhotoSetView.progressView.videoCount += 1
  306. publishNewVideoPhotoSetView.closeButton.isHidden = true
  307. publishNewVideoPhotoSetView.cameraFlipButton.isHidden = true
  308. publishNewVideoPhotoSetView.filterButton.isHidden = true
  309. publishNewVideoPhotoSetView.beautyButton.isHidden = true
  310. publishNewVideoPhotoSetView.musicButton.isHidden = true
  311. //切换按钮状态
  312. publishNewVideoPhotoSetView.recordButton.isSelected = !publishNewVideoPhotoSetView.recordButton.isSelected
  313. }
  314. /// 停止录制显示View
  315. func stopTakeVideoVideoHiddenView() {
  316. publishNewVideoPhotoSetView.closeButton.isHidden = false
  317. publishNewVideoPhotoSetView.cameraFlipButton.isHidden = false
  318. publishNewVideoPhotoSetView.filterButton.isHidden = false
  319. publishNewVideoPhotoSetView.beautyButton.isHidden = false
  320. publishNewVideoPhotoSetView.musicButton.isHidden = false
  321. //切换按钮状态
  322. publishNewVideoPhotoSetView.recordButton.isSelected = !publishNewVideoPhotoSetView.recordButton.isSelected
  323. }
  324. /// 完成拍视频
  325. func finishTakeVideo() {
  326. self.recorder?.finishRecording()
  327. }
  328. /// 拍照
  329. func takePhoto() {
  330. recorder?.takePhoto({(image, rawImage) in
  331. DispatchQueue.main.async {
  332. // 跳转到使用照片页面
  333. let publishConfirmPhotoNewVC = PublishConfirmPhotoNewViewController()
  334. publishConfirmPhotoNewVC.photoImg = image
  335. UIViewController.topMost?.navigationController?.pushViewController(publishConfirmPhotoNewVC, animated: true)
  336. }
  337. })
  338. }
  339. /// 回删视频
  340. func deleteVideo() {
  341. DispatchQueue.main.async {
  342. [weak self] in
  343. if self?.recorder?.clipManager?.partCount ?? 0 > 0 {
  344. AlertSheetView.alert(title: "是否删除上一片段?") { [weak self] (popupView, index, title) in
  345. let partCount = self?.recorder?.clipManager?.partCount
  346. // 删除最后一个视频片段
  347. self?.recorder?.clipManager?.deletePart()
  348. // 视频时长
  349. self?.recorderDuration = (self?.recorder?.clipManager?.duration)!
  350. // 完成按钮是否显示
  351. self?.finishAlpha()
  352. // 时间按钮是否显示
  353. self?.durationTimeAlpha()
  354. // 设置回删的进度View
  355. self?.publishNewVideoPhotoSetView.progressView.videoCount -= 1
  356. // 设置回删的进度View
  357. self?.setProgress()
  358. // 剩下最后一个片段视频
  359. if partCount == 1 {
  360. // 回删按钮是否隐藏
  361. self?.deleteAlpha(alpha: 0)
  362. // 分段view隐藏
  363. self?.segmentedViewAlpha(alpha: 1)
  364. }
  365. }
  366. }
  367. }
  368. }
  369. /// 回删按钮显示跟隐藏
  370. /// - Parameter alpha: 回删按钮显示跟隐藏
  371. func deleteAlpha(alpha:CGFloat) {
  372. DispatchQueue.main.async {
  373. [weak self] in
  374. self?.publishNewVideoPhotoSetView.deleteButton.alpha = alpha
  375. }
  376. }
  377. /// 完成按钮显示跟隐藏
  378. /// - Parameter alpha: 完成按钮显示跟隐藏
  379. func finishAlpha() {
  380. DispatchQueue.main.async {
  381. [weak self] in
  382. if (self?.recorderDuration)! >= 3.0 {
  383. if (self?.publishNewVideoPhotoSetView.finishButton.isHidden)! {
  384. self?.publishNewVideoPhotoSetView.finishButton.isHidden = false
  385. }
  386. }else {
  387. if !(self?.publishNewVideoPhotoSetView.finishButton.isHidden)! {
  388. self?.publishNewVideoPhotoSetView.finishButton.isHidden = true
  389. }
  390. }
  391. }
  392. }
  393. /// 时间label显示跟隐藏
  394. /// - Parameter alpha: 时间label显示跟隐藏
  395. func durationTimeAlpha() {
  396. DispatchQueue.main.async {
  397. [weak self] in
  398. if (self?.recorderDuration)! > 0.0 {
  399. if (self?.publishNewVideoPhotoSetView.durationTimeLabel.isHidden)! {
  400. self?.publishNewVideoPhotoSetView.durationTimeLabel.isHidden = false
  401. self?.publishNewVideoPhotoSetView.durationTimeDotLabel.isHidden = false
  402. }
  403. let d : Int = Int(self?.recorderDuration ?? 0)
  404. let m : Int = Int(d / 60)
  405. let s : Int = Int(d % 60)
  406. self?.publishNewVideoPhotoSetView.durationTimeLabel.text = String(format: "%02d:%02d", m,s)
  407. }else {
  408. if !(self?.publishNewVideoPhotoSetView.durationTimeLabel.isHidden)! {
  409. self?.publishNewVideoPhotoSetView.durationTimeLabel.isHidden = true
  410. self?.publishNewVideoPhotoSetView.durationTimeDotLabel.isHidden = true
  411. }
  412. }
  413. }
  414. }
  415. /// 设置时间进度
  416. func setProgress() {
  417. DispatchQueue.main.async {
  418. [weak self] in
  419. self?.publishNewVideoPhotoSetView.progressView.progress = self?.recorderDuration ?? 0
  420. }
  421. }
  422. /// 设置进度条是否显示
  423. ///
  424. /// - Parameter alpha: 透明度
  425. func setProgressViewAlpha(alpha:CGFloat,duration:TimeInterval) {
  426. UIView.animate(withDuration: duration) {
  427. [weak self] in
  428. self?.publishNewVideoPhotoSetView.progressView.alpha = alpha
  429. }
  430. // 更新关闭/闪光灯/音乐按钮的位置
  431. closeMakeConstraints(duration: duration)
  432. }
  433. /// 更新关闭/闪光灯/音乐按钮的位置
  434. ///
  435. /// - Parameter duration: 0.5s
  436. func closeMakeConstraints(duration:TimeInterval) {
  437. if PublishNewViewModel.shared.publishNewRecorderType == .video {
  438. publishNewVideoPhotoSetView.closeVideoUpMakeConstraints(duration: duration)
  439. // 设置闪光灯icon
  440. recorder?.switchTorch(with: AliyunIRecorderTorchMode.off)
  441. publishNewVideoPhotoSetView.flashButton.setImage(kImage(name: "video_ico_flashlight_close"), for: UIControl.State.normal)
  442. }else if PublishNewViewModel.shared.publishNewRecorderType == .photo {
  443. publishNewVideoPhotoSetView.closePhotoUpMakeConstraints(duration: duration)
  444. // 设置闪光灯icon
  445. recorder?.switchTorch(with: AliyunIRecorderTorchMode.auto)
  446. publishNewVideoPhotoSetView.flashButton.setImage(kImage(name: "video_ico_flashlight_auto"), for: UIControl.State.normal)
  447. }
  448. }
  449. /// 设置相机翻转
  450. func setCameraFlip() {
  451. let cameraPosition = recorder?.cameraPosition
  452. if cameraPosition == .front {
  453. UIView.transition(with: recorderPreview, duration: 0.5, options: UIView.AnimationOptions.transitionFlipFromLeft, animations: {
  454. [weak self] in
  455. self?.recorder?.switchCameraPosition()
  456. }, completion: { _ in})
  457. }else {
  458. UIView.transition(with: recorderPreview, duration: 0.5, options: UIView.AnimationOptions.transitionFlipFromRight, animations: {
  459. [weak self] in
  460. self?.recorder?.switchCameraPosition()
  461. }, completion: { _ in})
  462. }
  463. }
  464. /// 分段view显示
  465. /// - Parameter alpha: 透明度
  466. func segmentedViewAlpha(alpha:CGFloat) {
  467. UIView.animate(withDuration: 0.5) {
  468. PublishNewViewModel.shared.segmentedView?.alpha = alpha
  469. }
  470. }
  471. /// 滤镜美颜是否显示
  472. ///
  473. /// - Parameter isHidden: 是否隐藏
  474. func effectFilterBeautyViewisHidden(isHidden:Bool) {
  475. var offsetY : CGFloat = kScreenHeight
  476. if isHidden {
  477. offsetY = kScreenHeight
  478. if recorderDuration == 0 {
  479. segmentedViewAlpha(alpha:1)
  480. }else {
  481. segmentedViewAlpha(alpha:0)
  482. }
  483. // 移除点击手势
  484. recorderPreview.removetap()
  485. }else {
  486. offsetY = kScreenHeight-(48 + 125 + kSafeTabBarHeight)
  487. segmentedViewAlpha(alpha:0)
  488. // 添加点击手势
  489. recorderPreview.addTap()
  490. }
  491. UIView.animate(withDuration: 0.5) {
  492. [weak self] in
  493. self?.effectFilterBeautyView.frame = CGRect(x: 0, y: offsetY, width: kScreenWidth, height: 48 + 125 +
  494. kSafeTabBarHeight)
  495. if isHidden {
  496. self?.effectFilterBeautyView.alpha = 0
  497. self?.publishNewVideoPhotoSetView.alpha = 1
  498. }else {
  499. self?.effectFilterBeautyView.alpha = 1
  500. self?.publishNewVideoPhotoSetView.alpha = 0
  501. }
  502. }
  503. }
  504. //滤镜 减 1
  505. func filterLess() {
  506. if selectedIndex > 0 {
  507. selectedIndex = selectedIndex - 1
  508. }else {
  509. selectedIndex = (aliyunFiltersModel?.filters?.count ?? 1) - 1
  510. }
  511. //选中滤镜
  512. didSelectFilter()
  513. }
  514. //滤镜 加 1
  515. func filterPlus() {
  516. if selectedIndex < ((aliyunFiltersModel?.filters?.count ?? 0) - 1) {
  517. selectedIndex = selectedIndex + 1
  518. }else {
  519. selectedIndex = 0
  520. }
  521. //选中滤镜
  522. didSelectFilter()
  523. }
  524. /// 选中滤镜
  525. func didSelectFilter() {
  526. let indexPath = IndexPath(row: self.selectedIndex , section: 0)
  527. effectFilterBeautyView.effectFilterView.collectionView(effectFilterBeautyView.effectFilterView.collectionView, didSelectItemAt: indexPath)
  528. effectFilterBeautyView.effectFilterView.collectionView.selectItem(at: indexPath, animated: true, scrollPosition: UICollectionView.ScrollPosition.centeredHorizontally)
  529. }
  530. /// 滤镜名字显示
  531. ///
  532. /// - Parameter aliyunEffectFilter: 滤镜模型
  533. func showFilterNameLabel(aliyunEffectFilter:AliyunEffectFilter) {
  534. recorderPreview.filterNameLabel.alpha = 1
  535. recorderPreview.filterNameLabel.text = aliyunEffectFilter.name
  536. UIView.animate(withDuration: 2, animations: {
  537. [weak self] in
  538. self?.recorderPreview.filterNameLabel.alpha = 1
  539. }, completion: {
  540. [weak self] (finished) in
  541. UIView.animate(withDuration: 2, animations: {
  542. [weak self] in
  543. self?.recorderPreview.filterNameLabel.alpha = 0
  544. })
  545. })
  546. }
  547. /// 音乐是否显示
  548. ///
  549. /// - Parameter isHidden: 是否隐藏
  550. func musicViewisHidden(isHidden:Bool) {
  551. AliPlayerManager.shared.audioPlayer.stop()
  552. recorder?.startPreview()
  553. var offsetY : CGFloat = kScreenHeight
  554. if isHidden {
  555. offsetY = kScreenHeight
  556. if recorderDuration == 0 {
  557. segmentedViewAlpha(alpha:1)
  558. }else {
  559. segmentedViewAlpha(alpha:0)
  560. }
  561. // 移除点击手势
  562. recorderPreview.removetap()
  563. musicView.listContainerView.reloadData()
  564. }else {
  565. offsetY = kSafeStatusBarHeight
  566. segmentedViewAlpha(alpha:0)
  567. // 添加点击手势
  568. recorderPreview.addTap()
  569. }
  570. UIView.animate(withDuration: 0.5, animations: {
  571. [weak self] in
  572. self?.musicView.frame = CGRect(x: 0, y: offsetY, width: kScreenWidth, height: kScreenHeight -
  573. kSafeStatusBarHeight)
  574. if isHidden {
  575. self?.musicView.alpha = 0
  576. self?.publishNewVideoPhotoSetView.alpha = 1
  577. }else {
  578. self?.musicView.alpha = 1
  579. self?.publishNewVideoPhotoSetView.alpha = 0
  580. }
  581. })
  582. }
  583. /// 结束录制回调/停止录制回调
  584. func stopRecorderShowHidden() {
  585. // 回删按钮透明度
  586. deleteAlpha(alpha:1)
  587. // 停止录制显示View
  588. DispatchQueue.main.async {
  589. [weak self] in
  590. self?.stopTakeVideoVideoHiddenView()
  591. }
  592. }
  593. /// 完成录制的View
  594. func finishRecorderView() {
  595. SwiftProgressHUD.shared().showWait("视频正在合成中...")
  596. isFinishRecorder = true
  597. }
  598. }
  599. // MARK: - 代理
  600. extension PublishNewVideoPhotoView : AliyunIRecorderDelegate {
  601. /// 授权代理
  602. /// - Parameter status: 收取状态
  603. func recorderDeviceAuthorization(_ status: AliyunIRecorderDeviceAuthor) {
  604. switch status {
  605. // 授权同意
  606. case .enabled:
  607. break
  608. // 音频授权被拒绝
  609. case .audioDenied:
  610. break
  611. // 视频授权被拒绝
  612. case .videoDenied:
  613. break
  614. default:
  615. break
  616. }
  617. }
  618. /**
  619. 摄像头返回的原始视频数据
  620. 开放出来的目的是用于做人脸识别
  621. @param sampleBuffer 视频数据
  622. */
  623. // func recorderOutputVideoRawSampleBuffer(_ sampleBuffer: CMSampleBuffer!)
  624. /**
  625. 返回原始的音频数据
  626. 用来做语音识别一类的业务
  627. @param sampleBuffer 音频数据
  628. */
  629. // func recorderOutputAudioRawSampleBuffer(_ sampleBuffer: CMSampleBuffer!)
  630. /**
  631. 用户自定义渲染
  632. @param sampleBuffer 原始视频数据
  633. @return 用户自渲染后的PixelBuffer
  634. */
  635. // optional func customRenderedPixelBuffer(withRawSampleBuffer sampleBuffer: CMSampleBuffer!) -> Unmanaged<CVPixelBuffer>!
  636. /**
  637. 用户自定义渲染
  638. 开放pixelBuffer和纹理id给用户自渲染 (仅支持BGRA格式)
  639. @param pixelBuffer 摄像头数据
  640. @param textureName 摄像头数据纹理
  641. @return 自定义渲染后的纹理id
  642. */
  643. // optional func recorderOutputVideoPixelBuffer(_ pixelBuffer: CVPixelBuffer!, textureName: Int) -> Int
  644. /**
  645. 用户自定义渲染接口
  646. @param srcTexture 原始视频帧纹理id
  647. @param size 原始视频帧纹理size
  648. @return 返回纹理id
  649. */
  650. // optional func customRender(_ srcTexture: Int32, size: CGSize) -> Int32
  651. /**
  652. 录制实时时长
  653. @param duration 录制时长
  654. */
  655. func recorderVideoDuration(_ duration: CGFloat) {
  656. // 录制时长
  657. recorderDuration = duration
  658. // 完成按钮是否显示
  659. finishAlpha()
  660. // 时间按钮是否显示
  661. durationTimeAlpha()
  662. // 时间进度
  663. setProgress()
  664. }
  665. /**
  666. 摄像头返回的原始视频纹理
  667. 摄像头数据格式为BGRA、YUV时都需实现
  668. @param textureName 原始纹理ID
  669. @return 处理后的纹理ID
  670. */
  671. // optional func recorderOutputVideoTextureName(_ textureName: Int, textureSize textureSie: CGSize) -> Int
  672. /**
  673. 摄像头返回的原始视频纹理
  674. 摄像头数据格式仅为YUV时须实现,反之不实现
  675. @param textureName 原始UV分量的纹理ID
  676. @return 处理后的纹理ID
  677. */
  678. // optional func recorderOutputVideoUVTextureName(_ textureName: Int) -> Int
  679. /**
  680. 开始预览回调
  681. */
  682. func recorderDidStartPreview() {
  683. }
  684. /**
  685. 停止录制回调
  686. */
  687. func recorderDidStopRecording() {
  688. //是否完成录制
  689. if isFinishRecorder { //完成 显示view也要完成视频合成
  690. finishTakeVideo()
  691. }else{ //没有完成只改变view显示
  692. stopRecorderShowHidden()
  693. }
  694. }
  695. /**
  696. 当录至最大时长时回调
  697. */
  698. func recorderDidStopWithMaxDuration() {
  699. finishRecorderView()
  700. finishTakeVideo()
  701. }
  702. /**
  703. 结束录制回调
  704. */
  705. func recorderDidFinishRecording() {
  706. SwiftProgressHUD.shared().hide()
  707. if isFinishRecorder { //完成 显示view也要完成视频合成
  708. stopRecorderShowHidden()
  709. }
  710. isFinishRecorder = false
  711. DispatchQueue.main.async {
  712. [weak self] in
  713. self?.publishNewVideoPhotoSetView.recordButton.isSelected = false
  714. let vc = PublishEditNewViewController()
  715. vc.taskPath = self?.recorder?.taskPath
  716. vc.popClosure = {
  717. [weak self] in
  718. self?.recorder?.startPreview()
  719. }
  720. UIViewController.topMost?.navigationController?.pushViewController(vc, animated: true)
  721. }
  722. }
  723. /**
  724. 录制异常
  725. @param error 异常
  726. */
  727. func recoderError(_ error: Error!) {
  728. NXLLog(error)
  729. SwiftProgressHUD.shared().showText("录制异常")
  730. }
  731. }