123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697 |
- //
- // BFRecordScreenController.swift
- // BFRecordScreenKit_Example
- //
- // Created by 胡志强 on 2021/11/23.
- // Copyright © 2021 CocoaPods. All rights reserved.
- //
- import Foundation
- import BFUIKit
- import GPUImage
- import Photos
- import BFCommonKit
- import BFFramework
- import UIKit
- public class BFRecordScreenController: BFBaseViewController {
-
- public var nextActionHandle:(()->Void)?
- public var closeActionHandle:(()->Void)?
-
- // MARK: - 录制参数
- public var asset:PHAsset?
- // var shouldPlayRecordIndex:Int = -1 // 当前应该播放的录音资源序号
- var currentPlayRecordIndex:Int = -1 // >= 0 :当前正在播放的录音资源序号; -3: 刚录音完,不需要播放录音; -1:初始化阶段
- var isRecording = false // 是否正在录音
- var isNormalPlaying = false { // 是否正在播放
- didSet{
- playBtn.isSelected = isNormalPlaying
- }
- }
- var currentAssetProgress : CMTime = .zero // 当前素材播放的进度
- // 视频素材
- public var avasset:AVURLAsset?
- public var recordList:[PQVoiceModel] = [PQVoiceModel]()
- var assetPlayer:AVPlayer? // 原视频音频播放器
- var isCompletePlay = true
- var hadPrepareToPlayRecord = false // 录音播放器准备
- var recordPlayer:AVPlayer? // 录音音频播放器
- var movie :GPUImageMovie? // 视频预览
- var playView :GPUImageView? // 视频展示视图
- var isDragingProgressSlder : Bool = false // 是否在拖动进度条
-
- //定义音频的编码参数
- let recordSettings:[String : Any] = [AVSampleRateKey : 44100.0, //声音采样率
- AVFormatIDKey : kAudioFormatLinearPCM, //编码格式
- AVNumberOfChannelsKey : 1, //采集音轨
- AVEncoderBitDepthHintKey: 16, // 位深
- AVEncoderAudioQualityKey : AVAudioQuality.medium.rawValue] //音频质量
-
- // 录音相关
- lazy var recorderManager : BFVoiceRecordManager = {
-
- let manager = BFVoiceRecordManager()
- manager.cancelRecordHandle = { error in
-
- }
- manager.endRecordHandle = {[weak self] (isTimeout, model) in
- if let model = model, FileManager.default.fileExists(atPath: model.wavFilePath ?? ""){
- // 加入到语音数组里
- let ass = AVURLAsset(url: URL(fileURLWithPath: model.wavFilePath))
-
- model.endTime = model.startTime + CMTimeGetSeconds(ass.duration)
-
- // TODO: 原逻辑要删除新录音后边的数据, 新逻辑是插入覆盖
- while let m = self?.recordList.last{
- if model.startTime < m.startTime {
- self?.recordList.removeLast()
- }else if m.endTime > model.startTime {
- m.endTime = model.startTime
- }else{
- break
- }
- }
- BFLog(1, message: "添加录音文件:\(model.startTime) -- \(model.endTime)")
- self?.recordList.append(model)
- self?.drawOrUpdateRecordProgessLable()
- self?.currentPlayRecordIndex = -3 // 刚录音完,不需要播放录音
- }
-
- }
- return manager
- }()
- // MARK: - 视图参数
- var beginOnStartBtn:Bool = false
- var touchStart:CGPoint = CGPoint(x: 0, y: 0)
- var avplayerTimeObserver: NSKeyValueObservation?
- 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 playBtn:UIButton = {
- let btn = UIButton(frame: view.bounds)
- btn.addTarget(self, action: #selector(playVideo(btn:)), for: .touchUpInside)
- return btn
- }()
-
- lazy var bottomeView:UIImageView = {
- let iv = UIImageView(image: imageInRecordScreenKit(by: "bottom_shadow"))
- iv.contentMode = .scaleAspectFill
- iv.isUserInteractionEnabled = true
- // 拖曳手勢
- let pan = UIPanGestureRecognizer(target: self, action: #selector(pan(recognizer:)))
- pan.delegate = self
- pan.minimumNumberOfTouches = 1
- pan.maximumNumberOfTouches = 1
- iv.addGestureRecognizer(pan)
-
- return iv
- }()
-
- lazy var recordBtn:UIButton = {
- let btn = UIButton(type: .custom)
- btn.setImage(imageInRecordScreenKit(by: "mic1"), for: .normal)
- btn.adjustsImageWhenHighlighted = false
- btn.addTarget(self, action: #selector(startRecord), for: .touchDown)
- btn.addTarget(self, action: #selector(endRecord), for: .touchUpInside)
- return btn
- }()
-
- lazy var progessSildeBackV : UIView = {
- let vv = UIView()
- vv.backgroundColor = UIColor.hexColor(hexadecimal: "#303030")
-
- return vv
- }()
-
- lazy var progessSilde:BFPlayerSlider = {
- let sliderView = BFPlayerSlider()
- let tjbV = UIView(frame: CGRect(x: 0, y: 0, width: 4, height: 16))
- tjbV.backgroundColor = .white
- let thbImage = tjbV.graphicsGetImage()//UIImage(named: "icon_point")
- sliderView.setMinimumTrackImage(thbImage, for: .normal)
- sliderView.setMaximumTrackImage(thbImage, for: .normal)
- sliderView.setThumbImage(thbImage, for: .highlighted)
- sliderView.setThumbImage(thbImage, for: .normal)
- sliderView.maximumTrackTintColor = .clear // UIColor.hexColor(hexadecimal: "#303030")
- sliderView.minimumTrackTintColor = .clear //UIColor.hexColor(hexadecimal: "#303030")
- // sliderView.minimumTrackTintColor = UIColor.hexColor(hexadecimal: "#FA6400")
- sliderView.addTarget(self, action: #selector(sliderTouchBegan(sender:)), for: .touchDown)
- sliderView.addTarget(self, action: #selector(sliderTouchEnded(sender:)), for: .touchUpInside)
- sliderView.addTarget(self, action: #selector(sliderTouchEnded(sender:)), for: .touchUpOutside)
- sliderView.addTarget(self, action: #selector(sliderTouchEnded(sender:)), for: .touchCancel)
- return sliderView
- }()
-
- lazy var closeBtn:UIButton = {
- let btn = UIButton(type: .custom)
- btn.setImage(imageInRecordScreenKit(by: "xx"), for: .normal)
- btn.addTarget(self, action: #selector(closePage), for: .touchUpInside)
- return btn
- }()
-
- lazy var nextBtn:UIButton = {
- let btn = UIButton(type: .custom)
- btn.setImage(imageInRecordScreenKit(by: "gou"), for: .normal)
- btn.addTarget(self, action: #selector(nextAction), for: .touchUpInside)
- return btn
- }()
-
- lazy var toolV : BFIntroduceToolView = {
- let toolV = BFIntroduceToolView()
- toolV.centerY = view.centerY
-
- toolV.choosedToolHandle = {[weak self] tool in
- guard let sself = self else {
- return
- }
- tool.center = sself.view.center
- sself.view.addSubview(tool)
- }
-
- return toolV
-
- }()
-
- //MARK: ------------------ 生命周期
- deinit {
- cleanMovieTarget()
- NotificationCenter.default.removeObserver(self)
- avplayerTimeObserver?.invalidate()
- recorderManager.stopRecord(isCancel: true)
- assetPlayer?.pause()
- recordPlayer?.pause()
-
- }
-
- public override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
- self.navigationController?.isNavigationBarHidden = true
- hiddenNavigation()
- }
-
- public override func viewDidLoad(){
- super.viewDidLoad()
- _ = disablePopGesture()
-
- view.backgroundColor = .lightGray
-
- playView = GPUImageView(frame: view.bounds)
- view.addSubview(playView!)
- fetchVideo()
-
- view.addSubview(playBtn)
- view.addSubview(bottomeView)
- view.addSubview(progreddL)
- // view.addSubview(toolV)
- bottomeView.addSubview(recordBtn)
- bottomeView.addSubview(progessSildeBackV)
- bottomeView.addSubview(progessSilde)
- bottomeView.addSubview(closeBtn)
- bottomeView.addSubview(nextBtn)
-
- if checkStatus() {
- try? AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: .defaultToSpeaker)
- }
-
- }
-
- public override func viewWillLayoutSubviews() {
- super.viewWillLayoutSubviews()
- bottomeView.snp.makeConstraints { make in
- make.left.bottom.right.equalToSuperview()
- make.height.equalTo(adapterWidth(width: 220))
- }
-
- recordBtn.snp.makeConstraints { make in
- make.width.height.equalTo(120)
- make.centerX.equalToSuperview()
- make.top.equalTo(27)
- }
-
- closeBtn.snp.makeConstraints { make in
- make.left.equalToSuperview()
- make.width.height.equalTo(60)
- make.top.equalTo(recordBtn.snp.bottom).offset(-10)
- }
- nextBtn.snp.makeConstraints { make in
- make.right.equalToSuperview()
- make.top.width.height.equalTo(closeBtn)
- }
-
- progessSildeBackV.snp.makeConstraints { make in
- make.left.equalTo(closeBtn.snp.right).offset(16)
- make.right.equalTo(nextBtn.snp.left).offset(-16)
- make.centerY.equalTo(closeBtn)
- make.height.equalTo(8)
- }
-
- progessSilde.snp.makeConstraints { make in
- make.left.right.centerY.equalTo(progessSildeBackV)
- make.height.equalTo(20)
- }
-
- }
-
- // MARK: - 按钮事件响应
-
- // 触发拖曳手势后,执行的动作
- @objc func pan(recognizer: UIPanGestureRecognizer) {
- // 设置 UIView 新的位置
- if !checkStatus(show: false) {
- return
- }
- let point = recognizer.location(in: bottomeView)
- switch recognizer.state {
- case .began:
- touchStart = recognizer.location(in: bottomeView)
- beginOnStartBtn = recordBtn.frame.contains(touchStart)
- case .changed:
- if beginOnStartBtn == true {
- let nowPoint = recognizer.location(in: bottomeView)
- BFLog(1, message: "nowPoint x: \(nowPoint.x) y:\(nowPoint.y)")
- if recordBtn.frame.contains(nowPoint) {
-
- } else {
-
- }
- }
- case .ended:
- BFLog(1, message: "移动结束 \(beginOnStartBtn)")
- if beginOnStartBtn == true {
- beginOnStartBtn = false
- if recordBtn.frame.contains(point) {
- // 结束录制
- endRecord()
- } else {
- cancleRecord()
- }
- }
- default:
- break
- }
- }
-
- @objc func startRecord(){
- recordBtn.setImage(imageInRecordScreenKit(by: "mic2"), for: .normal)
- BFLog(1, message: "start \(UIControl.Event.touchDown)")
- pause()
- let model = PQVoiceModel()
- model.startTime = CMTimeGetSeconds(self.currentAssetProgress)
- model.volume = 100
- recorderManager.voiceModel = model
- recorderManager.startRecord(index: recordList.count)
- movie?.startProcessing()
- assetPlayer?.volume = 0
- assetPlayer?.play()
- isRecording = true
- }
-
- @objc func endRecord(){
- recordBtn.setImage(imageInRecordScreenKit(by: "mic1"), for: .normal)
- // 存储录音
- recorderManager.endRecord()
- isRecording = false
- pause()
- }
-
- func cancleRecord(){
- recordBtn.setImage(imageInRecordScreenKit(by: "mic1"), for: .normal)
- recorderManager.cancleRecord()
- isRecording = false
-
- pause()
- }
- @objc func closePage(){
- pause()
- closeActionHandle?()
- }
-
- @objc func nextAction(){
- nextActionHandle?()
- pause()
- }
-
- @objc func playVideo(btn:UIButton){
- btn.isSelected ? pause() : play()
- }
- @objc public func sliderTouchBegan(sender _: UISlider) {
- isDragingProgressSlder = true
- pause()
- }
- @objc public func sliderTouchEnded(sender: UISlider) {
- changeProgress(progress: sender.value)
- isDragingProgressSlder = false
- currentPlayRecordIndex = -1
- hadPrepareToPlayRecord = false
- }
-
- // MARK: - 权限申请
- func checkStatus(show: Bool = true) -> Bool {
- let status = AVCaptureDevice.authorizationStatus(for: .audio)
- switch status {
- case .denied, .restricted:
- BFLog(message: "麦克风权限被拒绝,请在设置中打开")
- if show {
- let remindData = BFBaseModel()
- remindData.title = "票圈视频需要访问你的麦克风才能录音"
- remindData.summary = ""
- let remindView = BFRemindView(frame: CGRect(x: 0, y: 0, width: cScreenWidth, height: cScreenHeigth))
- remindView.isBanned = true
- remindView.confirmBtn.setTitle("去设置", for: .normal)
- UIApplication.shared.keyWindow?.addSubview(remindView)
- remindView.remindData = remindData
- remindView.remindBlock = { item, _ in
- if item.tag == 2 {
- openAppSetting()
- }
- }
- }
- return false
- case .authorized:
- return true
- case .notDetermined:
- if show {
- requestMicroPhoneAuth()
- }
- return false
- default:
- break
- }
- return false
- }
-
- func requestMicroPhoneAuth() {
- AVCaptureDevice.requestAccess(for: .audio) { granted in
- if !granted {
- BFLog(message: "麦克风权限被拒绝,请在设置中打开")
- }
- }
- }
-
- // MARK: - 音视频处理
- func playRecord(at currentT:CMTime){
- if currentPlayRecordIndex == -3 { // 刚录音完,不需要播放
- return
- }
- let (shouldPlayRecordIndex, recordedAudio) = recordList.enumerated().first { model in
- model.1.endTime > CMTimeGetSeconds(currentT)
- } ?? (-1, nil)
-
- guard let recordedAudio = recordedAudio else {
- return
- }
-
- BFLog(1, message: "当前时间:\(CMTimeGetSeconds(currentT)), 找到的音频:\(recordedAudio.startTime), \(recordedAudio.endTime)")
-
- // 创建播放器
- if self.recordPlayer == nil || (self.recordPlayer?.currentItem?.asset as? AVURLAsset)?.url.lastPathComponent != (recordedAudio.wavFilePath as NSString).lastPathComponent {
- let newItem = AVPlayerItem(url: URL(fileURLWithPath: recordedAudio.wavFilePath))
- if let player = self.recordPlayer {
- player.pause()
- if let playItem = player.currentItem {
- NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: playItem)
- recordPlayer?.replaceCurrentItem(with: newItem)
- }
- }else {
- self.recordPlayer = AVPlayer(playerItem: newItem)
- }
- self.recordPlayer!.volume = 1
- // self.recordPlayer?.prepareToPlay()
- currentPlayRecordIndex = -1
- hadPrepareToPlayRecord = false
- BFLog(1, message: "录音播放器初始化(有时候不准)")
-
- NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: newItem, queue: .main) { [weak self] notify in
- self?.hadPrepareToPlayRecord = false
- self?.currentPlayRecordIndex = -1
- }
- }
-
- synced(currentPlayRecordIndex) {
- if !hadPrepareToPlayRecord
- && CMTimeGetSeconds(currentT) >= recordedAudio.startTime
- && CMTimeGetSeconds(currentT) <= recordedAudio.endTime - 0.2 // 这个条件是避免录音结束后有小幅度回退导致播放最新录音
- {
- // 应当开始播放了
- // 两个逻辑:如果在播,则跳过;如果暂停拖动到中间,则seek
- if currentPlayRecordIndex == -1 && self.isNormalPlaying{
- let second = CMTimeGetSeconds(currentT) - recordedAudio.startTime
- DispatchQueue.main.async {[weak self] in
- self?.recordPlayer?.seek(to: CMTime(value: CMTimeValue(second), timescale: 100), toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000), completionHandler: {[weak self] finished in
- if finished && (self?.isNormalPlaying ?? false) {
- self?.recordPlayer?.play()
- BFLog(1, message: "录音开始播放 playing, \(second), \(CMTimeGetSeconds(self?.recordPlayer?.currentItem?.duration ?? .zero))")
- }
- })
- }
- currentPlayRecordIndex = shouldPlayRecordIndex
- hadPrepareToPlayRecord = true
- BFLog(1, message: "录音开始播放2, \(second), \(CMTimeGetSeconds(recordPlayer?.currentItem?.duration ?? .zero))")
- }
- }
-
- }
- BFLog(1, message: "应当播放:\(shouldPlayRecordIndex), 当前播放:\(currentPlayRecordIndex)")
- // if let recordedAudio = recordedAudio {
- //
- //
- // if shouldPlayRecordIndex != currentPlayRecordIndex {
- // // 设置新的播放资源
- //
- //// self.recordPlayer.delegate = self
- // self.recordPlayer.play()
- //
- // } else {
- // // 更新播放进度
- // let second = CMTimeGetSeconds(duration) - recordedAudio.startTime
- // self.recordPlayer.seek(to: CMTime(seconds: second, preferredTimescale: 25), toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000))
- // }
- // }
- }
-
- func play(){
- BFLog(1, message: "开始播放")
- isNormalPlaying = true
- assetPlayer?.volume = 0.2
- movie?.startProcessing()
- self.assetPlayer?.play()
- }
-
- func pause(){
- BFLog(1, message: "暂停播放")
- isNormalPlaying = false
- movie?.cancelProcessing()
- assetPlayer?.pause()
- recordPlayer?.pause()
-
- let second = self.currentAssetProgress
- assetPlayer?.seek(to: second , toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000), completionHandler: { finished in
- })
- }
-
- func fetchVideo(){
- if let asset = self.asset {
- let options = PHVideoRequestOptions()
- options.isNetworkAccessAllowed = true
- options.deliveryMode = .automatic
-
- PHImageManager.default().requestPlayerItem(forVideo:asset, options: options, resultHandler: { [weak self] playerItem, info in
- guard let item = playerItem else {
- cShowHUB(superView: nil, msg: "视频获取失败")
- return
- }
- self?.setAudioPlay(item: item)
- self?.setVideoPlay(item: item)
-
- })
-
- let option = PHImageRequestOptions()
- option.isNetworkAccessAllowed = true //允许下载iCloud的图片
- option.resizeMode = .fast
- option.deliveryMode = .highQualityFormat
- PHImageManager.default().requestImage(for: asset,
- targetSize: self.view.bounds.size,
- contentMode: .aspectFit,
- options: option)
- { (image, nil) in
- //image就是图片
- if image != nil {
- let pic = GPUImagePicture(image: image)
- let filet = GPUImageFilter()
- pic?.addTarget(filet)
- filet.addTarget(self.playView)
- pic?.processImage()
- }
-
- }
-
- // 使用copy资源到本地的方式
- // let outFilePath = NSHomeDirectory().appending("/Documents/simple.mp4")
- // let outFileUrl = URL(fileURLWithPath: outFilePath)
- // if FileManager.default.fileExists(atPath: outFilePath) {
- // try? FileManager.default.removeItem(atPath: outFilePath)
- // }
- //
- // let assetResources = PHAssetResource.assetResources(for: asset)
-
- // if let rsc = assetResources.first(where: { res in
- // res.type == .video || res.type == .pairedVideo
- // }) {
- // PHAssetResourceManager.default().writeData(for: rsc, toFile:outFileUrl, options: nil) {[weak self] error in
- // if error == nil {
- // DispatchQueue.main.async {[weak self] in
- // self?.setVideoPlay(url: outFileUrl)
- // self?.setAudioPlay(url: outFileUrl)
- // }
- // }else{
- // BFLog(1, message: "导出视频相exportAsynchro faile")
- // }
- // }
- // }else{
- //
- // }
- PHCachingImageManager().requestAVAsset(forVideo: asset, options: options, resultHandler: {[weak self] (asset: AVAsset?, audioMix: AVAudioMix?, info) in
- if let urlass = asset as? AVURLAsset {
- self?.avasset = urlass
- }
- })
- }
- }
-
- func setVideoPlay(item:AVPlayerItem){
- if movie != nil {
- cleanMovieTarget()
- }
- movie = GPUImageMovie(playerItem: item)
- // movie?.runBenchmark = true
- movie?.playAtActualSpeed = true
- let filter = GPUImageFilter()
- movie?.addTarget(filter)
- filter.addTarget(playView)
- }
-
- func setAudioPlay(item:AVPlayerItem){
- if let playItem = assetPlayer?.currentItem {
- NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: playItem)
- assetPlayer?.replaceCurrentItem(with: item)
- }else {
- assetPlayer = AVPlayer(playerItem: item)
- avplayerTimeObserver = assetPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 100), queue: DispatchQueue.global()) {[weak self] time in
- // 进度监控
- if !((self?.isNormalPlaying ?? false) || (self?.isRecording ?? false)) {
- return
- }
- self?.currentAssetProgress = time
- BFLog(1, message: "curr:\(CMTimeGetSeconds(time))")
- if CMTimeGetSeconds(item.duration) > 0, !(self?.isDragingProgressSlder ?? false) {
- DispatchQueue.main.async { [weak self] in
- self?.progessSilde.value = Float(CMTimeGetSeconds(time) / CMTimeGetSeconds(item.duration))
- self?.progreddL.text = String(format: "%.2f / %.2f", CMTimeGetSeconds(time), CMTimeGetSeconds(item.duration))
- }
- }
- // 播放对应的录音音频
- self?.playRecord(at: time)
- } as? NSKeyValueObservation
- }
-
- NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: assetPlayer?.currentItem, queue: .main) { [weak self] notify in
- BFLog(1, message: "AVPlayerItemDidPlayToEndTime = \(notify)")
- self?.isNormalPlaying = false
- self?.assetPlayer?.seek(to: CMTime.zero)
- self?.currentPlayRecordIndex = -1
- if self?.isRecording ?? false {
- self?.endRecord()
- }
- }
- }
-
- func cleanMovieTarget(){
- movie?.cancelProcessing()
- movie?.targets().forEach({ target in
- if let objc = target as? GPUImageOutput{
- objc.removeAllTargets()
- }
- })
- movie?.removeAllTargets()
- movie?.removeFramebuffer()
- GPUImageContext.sharedFramebufferCache().purgeAllUnassignedFramebuffers()
-
- }
-
- //MARK: - 录音对应图像绘制
-
- func changeProgress(progress:Float) {
- if let duration = assetPlayer?.currentItem?.duration {
- assetPlayer!.seek(to: CMTime(value: CMTimeValue(progress * Float(CMTimeGetSeconds(duration)) * 100), timescale: 100), toleranceBefore: CMTime(value: 1, timescale: 1000), toleranceAfter: CMTime(value: 1, timescale: 1000)) {[weak self] finished in
- if finished{
- BFLog(1, message: "拖动成功")
- self?.movie?.startProcessing()
- }
- }
- }
- }
-
- func drawOrUpdateRecordProgessLable(){
- DispatchQueue.main.async {[weak self] in
- progessSildeBackV.subviews.forEach { vv in
- vv.removeFromSuperview()
- }
- if let totalDur = self?.asset?.duration, totalDur > 0, let list = self?.recordList {
- let width = self?.progessSildeBackV.width ?? 0
- let height = self?.progessSildeBackV.height ?? 0
- list.forEach { model in
- let lineV = UIView(frame: CGRect(x: model.startTime * width / totalDur , y: 0, width: (model.endTime - model.startTime) * width / totalDur, height: height))
- lineV.backgroundColor = UIColor.hexColor(hexadecimal: "#28BE67")
- self?.progessSildeBackV.addSubview(lineV)
- }
- }
- }
- }
- }
- extension BFRecordScreenController:GPUImageMovieDelegate {
- public func didCompletePlayingMovie(){
- BFLog(1, message: "播放结束")
- currentPlayRecordIndex = -1
- }
- }
- extension BFRecordScreenController:AVAudioRecorderDelegate {
- public func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
- BFLog(1, message: "录音结束")
- }
- }
- extension BFRecordScreenController : AVAudioPlayerDelegate {
- public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
- BFLog(1, message: "录音播放结束")
- }
- }
|