Pārlūkot izejas kodu

add codeformat(swiftformat)

wenweiwei 3 gadi atpakaļ
vecāks
revīzija
118027205c
23 mainītis faili ar 943 papildinājumiem un 931 dzēšanām
  1. 65 0
      .swiftformat
  2. 3 3
      BFRecordScreenKit/Classes/BFRSComm.swift
  3. 86 94
      BFRecordScreenKit/Classes/BFRecordExport.swift
  4. 40 46
      BFRecordScreenKit/Classes/BFRecordItemModel.swift
  5. 17 19
      BFRecordScreenKit/Classes/BFVideoThumbImageFetchHelper.swift
  6. 8 10
      BFRecordScreenKit/Classes/BFVideoThumbProgressStrategy.swift
  7. 21 24
      BFRecordScreenKit/Classes/BFVoiceRecordManager.swift
  8. 280 304
      BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenController.swift
  9. 0 1
      BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenImageController.swift
  10. 0 1
      BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenVideoController.swift
  11. 12 19
      BFRecordScreenKit/Classes/RecordScreen/View/BFIntroduceToolView.swift
  12. 84 93
      BFRecordScreenKit/Classes/RecordScreen/View/BFRecordAvatarView.swift
  13. 25 37
      BFRecordScreenKit/Classes/RecordScreen/View/BFSubtitleEditView.swift
  14. 99 117
      BFRecordScreenKit/Classes/RecordScreen/View/BFSubtitleSettingView.swift
  15. 46 50
      BFRecordScreenKit/Classes/RecordScreen/View/BFVideoThumbProgressView.swift
  16. 18 23
      BFRecordScreenKit/Classes/RecordScreen/ViewModel/BFRecordScreenViewModel.swift
  17. 11 16
      Example/BFRecordScreenKit/AppDelegate.swift
  18. 6 7
      Example/BFRecordScreenKit/IntroduceController.swift
  19. 23 27
      Example/BFRecordScreenKit/PhotoVideoListController.swift
  20. 19 20
      Example/BFRecordScreenKit/VideoExportController.swift
  21. 8 13
      Example/BFRecordScreenKit/ViewController.swift
  22. 5 7
      Example/Tests/Tests.swift
  23. 67 0
      rules.swiftformat

+ 65 - 0
.swiftformat

@@ -0,0 +1,65 @@
+--allman false
+--assetliterals visual-width
+--beforemarks 
+--binarygrouping none
+--categorymark "MARK: %c"
+--classthreshold 0
+--closingparen balanced
+--commas always
+--conflictmarkers reject
+--decimalgrouping none
+--elseposition same-line
+--enumthreshold 0
+--exponentcase lowercase
+--exponentgrouping disabled
+--extensionacl on-extension
+--extensionlength 0
+--extensionmark "MARK: - %t + %c"
+--fractiongrouping disabled
+--fragment false
+--funcattributes preserve
+--groupedextension "MARK: %c"
+--guardelse auto
+--header ignore
+--hexgrouping 4,8
+--hexliteralcase uppercase
+--ifdef indent
+--importgrouping alphabetized
+--indent 4
+--indentcase false
+--lifecycle 
+--linebreaks lf
+--markextensions always
+--marktypes always
+--maxwidth none
+--modifierorder 
+--nevertrailing 
+--nospaceoperators ...,..<
+--nowrapoperators 
+--octalgrouping none
+--operatorfunc spaced
+--organizetypes class,enum,struct
+--patternlet hoist
+--ranges spaced
+--redundanttype inferred
+--self remove
+--selfrequired 
+--semicolons inline
+--shortoptionals always
+--smarttabs enabled
+--stripunusedargs closure-only
+--structthreshold 0
+--tabwidth unspecified
+--trailingclosures 
+--trimwhitespace always
+--typeattributes preserve
+--typemark "MARK: - %t"
+--varattributes preserve
+--voidtype void
+--wraparguments preserve
+--wrapcollections preserve
+--wrapconditions preserve
+--wrapparameters preserve
+--wrapreturntype preserve
+--xcodeindentation disabled
+--yodaswap always

+ 3 - 3
BFRecordScreenKit/Classes/BFRSComm.swift

@@ -9,7 +9,7 @@ import Foundation
 
 import BFCommonKit
 
-//class BFUIConfig{}
+// class BFUIConfig{}
 
 public func imageInRecordScreenKit(by name: String) -> UIImage? {
     return UIImage(named: name, in: currentBundle(), compatibleWith: nil)
@@ -19,7 +19,7 @@ func currentBundle() -> Bundle? {
     return Bundle.current(moduleName: "BFRecordScreenKit", isAssets: false)
 }
 
-//func ThemeStyleGreen() -> UIColor {
+// func ThemeStyleGreen() -> UIColor {
 //    return UIColor.hexColor(hexadecimal: "#28BE67")
-//}
+// }
 public var ThemeStyleColor = UIColor.hexColor(hexadecimal: "#28BE67")

+ 86 - 94
BFRecordScreenKit/Classes/BFRecordExport.swift

@@ -5,19 +5,19 @@
 //  Created by 胡志强 on 2021/11/25.
 //  录屏视频导出
 
-import Foundation
 import AVFoundation
-import Photos
-import GPUImage
 import BFCommonKit
 import BFMediaKit
+import Foundation
+import GPUImage
+import Photos
 
 public class BFRecordExport {
-    public var progress : ((Float)->Void)?
-    public var exportCompletion : ((Error?, URL?)->Void)?
-        
-    public var data:[BFRecordItemModel]? {
-        didSet{
+    public var progress: ((Float) -> Void)?
+    public var exportCompletion: ((Error?, URL?) -> Void)?
+
+    public var data: [BFRecordItemModel]? {
+        didSet {
             if data?.count ?? 0 > 0 {
                 for item in data! {
                     item.generationTimeRanges()
@@ -27,30 +27,28 @@ public class BFRecordExport {
     }
 
     var count = 0
-    
+
     var stickerRanges = [CMTimeRange]()
-    
-    var exporter : PQCompositionExporter?
+
+    var exporter: PQCompositionExporter?
 //    var mStickers = [PQEditVisionTrackMaterialsModel]()
-    
-    deinit {
-    }
-    public init(){}
 
-    
-    //MARK: -
+    deinit {}
+
+    public init() {}
+
+    // MARK: -
 
     /// synthesisAll: 合成所有还是只合成录音部分
-    public func startExprot(synthesisAll:Bool){
+    public func startExprot(synthesisAll: Bool) {
         // 1,背景视频素材
         if let itemModels = data {
-            
             var totalDur = 0.0
-            
+
             // 切割视频素材
             for (_, itemModel) in itemModels.enumerated() {
                 itemModel.videoStickers.removeAll()
-                
+
                 if synthesisAll {
                     // 保留全部
                     //                        let bgMovieInfo = splitBaseMaterial(timelineIn: totalDur, model_in: 0, duration: dur)
@@ -61,7 +59,7 @@ public class BFRecordExport {
                     let drangs = itemModel.dealedDurationRanges
                     for srange in drangs {
                         let range = srange.range
-                        let sticker = splitBaseMaterial(timelineIn: (totalDur + subDur), model_in: range.start.seconds, duration: range.duration.seconds)
+                        let sticker = splitBaseMaterial(timelineIn: totalDur + subDur, model_in: range.start.seconds, duration: range.duration.seconds)
                         sticker.volumeGain = srange.isRecord ? 0 : 100
                         itemModel.videoStickers.append(sticker)
                         subDur += range.duration.seconds
@@ -73,7 +71,7 @@ public class BFRecordExport {
                     var drangs = itemModel.dealedDurationRanges.filter { srange in
                         srange.isRecord == true
                     }
-                    
+
                     // 是否按录音顺序排列
                     let needSort = false
                     if needSort {
@@ -83,7 +81,7 @@ public class BFRecordExport {
                     }
                     for srange in drangs {
                         let range = srange.range
-                        let sticker = splitBaseMaterial(timelineIn: (totalDur + subDur), model_in: range.start.seconds, duration: range.duration.seconds)
+                        let sticker = splitBaseMaterial(timelineIn: totalDur + subDur, model_in: range.start.seconds, duration: range.duration.seconds)
                         sticker.volumeGain = 0
                         itemModel.videoStickers.append(sticker)
                         subDur += range.duration.seconds
@@ -91,40 +89,38 @@ public class BFRecordExport {
                     totalDur += subDur
                 }
             }
-            beginExport(synthesisAll:synthesisAll)
+            beginExport(synthesisAll: synthesisAll)
         }
     }
-    
-    public func cancelExport(){
-        self.exporter?.cancel()
+
+    public func cancelExport() {
+        exporter?.cancel()
     }
-    
-    public func clearFileCache(){
-        data?.forEach({ itemModel in
+
+    public func clearFileCache() {
+        data?.forEach { itemModel in
             itemModel.voiceStickers.forEach { model in
-                if let localPath = model.wavFilePath{
+                if let localPath = model.wavFilePath {
                     try? FileManager.default.removeItem(atPath: localPath)
                 }
             }
-        })
+        }
     }
-    
-    
+
     enum DispatchError: Error {
         case timeout
     }
-    
-    func getOutputFilePath() -> URL{
+
+    func getOutputFilePath() -> URL {
         var outPutMP4Path = exportVideosDirectory
         if !directoryIsExists(dicPath: outPutMP4Path) {
             createDirectory(path: outPutMP4Path)
         }
         outPutMP4Path.append("video_\(String.qe.timestamp()).mp4")
         return URL(fileURLWithPath: outPutMP4Path)
-        
     }
-    
-    func splitBaseMaterial(timelineIn:Double, model_in:Double, duration:Double) -> PQEditVisionTrackMaterialsModel{
+
+    func splitBaseMaterial(timelineIn: Double, model_in: Double, duration: Double) -> PQEditVisionTrackMaterialsModel {
         let bgMovieInfo: PQEditVisionTrackMaterialsModel = PQEditVisionTrackMaterialsModel()
         bgMovieInfo.type = StickerType.VIDEO.rawValue
         bgMovieInfo.timelineIn = timelineIn
@@ -139,11 +135,11 @@ public class BFRecordExport {
             bgMovieInfo.locationPath = localPath
         }
         BFLog(1, message: "hhh- timIn:\(timelineIn), modIn:\(model_in), dur:\(duration)")
-        
+
         return bgMovieInfo
     }
-    
-    func beginExport(synthesisAll:Bool) {
+
+    func beginExport(synthesisAll: Bool) {
         // 输出视频地址
 //        exprotVideo()
 //        return;
@@ -154,13 +150,13 @@ public class BFRecordExport {
         outPutMP4Path.append("video_\(String.qe.timestamp()).mp4")
         let outPutMP4URL = URL(fileURLWithPath: outPutMP4Path)
         BFLog(1, message: "导出视频地址 \(outPutMP4URL)")
-        
+
         guard let itemData = data else {
-            let error = NSError(domain: "err", code: -1, userInfo: ["msg":"voiceStickers count += nil"])
-            self.exportCompletion?(error as Error, nil)
+            let error = NSError(domain: "err", code: -1, userInfo: ["msg": "voiceStickers count += nil"])
+            exportCompletion?(error as Error, nil)
             return
         }
-        
+
         // 处理导出
         var voiceList = [PQVoiceModel]()
         var videoStickers = [PQEditVisionTrackMaterialsModel]()
@@ -170,54 +166,52 @@ public class BFRecordExport {
             videoStickers.append(contentsOf: itemModel.videoStickers)
             titleStickers.append(contentsOf: itemModel.titleStickers)
         }
-        
-        
+
         guard let voiceCount = data?.reduce(0, { partialResult, itemModell in
             itemModell.voiceStickers.count + partialResult
         }) else {
             BFLog(1, message: "voiceStickers count += nil")
-            let error = NSError(domain: "err", code: -1, userInfo: ["msg":"voiceStickers count += nil"])
-            self.exportCompletion?(error as Error, nil)
+            let error = NSError(domain: "err", code: -1, userInfo: ["msg": "voiceStickers count += nil"])
+            exportCompletion?(error as Error, nil)
             return
         }
-        
+
         guard let totalDuration = data?.reduce(0, { partialResult, itemModell in
-            (itemModell.materialDuraion ) + partialResult
+            itemModell.materialDuraion + partialResult
         }) else {
-            let error = NSError(domain: "err", code: -1, userInfo: ["msg":"时长计算出错"])
-            self.exportCompletion?(error as Error, nil)
+            let error = NSError(domain: "err", code: -1, userInfo: ["msg": "时长计算出错"])
+            exportCompletion?(error as Error, nil)
             return
         }
-        
+
         // 有录音操作或者多个视频,就会进入合成步骤,否则就是一个没有处理的素材,直接导出就行了
         if voiceCount > 0 || videoStickers.count > 1 {
+            let (audioMix, composition) = mergeAudio(videoStickers: videoStickers, audios: voiceList, synthesisAll: synthesisAll)
 
-            let (audioMix, composition) = mergeAudio(videoStickers: videoStickers, audios: voiceList,synthesisAll:synthesisAll)
-            
             let filter = videoStickers.map { sticker in
                 PQMovieFilter(movieSticker: sticker)
             }
-  
+
             exporter = PQCompositionExporter(asset: composition, videoComposition: nil, audioMix: audioMix, filters: filter, animationTool: nil, exportURL: outPutMP4URL)
-            
+
 //            let asset = data?.first?.baseMaterial // 可能为空
 
-            let size = UIScreen.main.bounds.size //getVideoSize(asset: asset!)
+            let size = UIScreen.main.bounds.size // getVideoSize(asset: asset!)
             var orgeBitRate = Int(size.width * size.height * 3)
-            
+
             for stick in videoStickers {
                 if stick.type == StickerType.VIDEO.rawValue {
                     let asset = AVURLAsset(url: URL(fileURLWithPath: stick.locationPath), options: avAssertOptions)
-                    
+
                     let cbr = asset.tracks(withMediaType: .video).first?.estimatedDataRate
                     if Int(cbr ?? 0) > orgeBitRate {
                         orgeBitRate = Int(cbr ?? 0)
                     }
                 }
             }
-            
+
             BFLog(message: "导出设置的码率为:\(orgeBitRate)")
- 
+
             if exporter!.prepare(videoSize: size, videoAverageBitRate: orgeBitRate) {
                 exporter!.start(playeTimeRange: CMTimeRange(start: CMTime.zero, end: synthesisAll ? CMTime(seconds: totalDuration, preferredTimescale: 100) : composition.duration))
             }
@@ -232,9 +226,9 @@ public class BFRecordExport {
                 // 输出视频时长
                 if let url = url {
                     let outSeconds = CMTimeGetSeconds(AVAsset(url: url).duration)
-                    
+
                     BFLog(1, message: "无水印的视频导出完成: \(String(describing: url)) 生成视频时长为:\(outSeconds)")
-                    cShowHUB(superView: nil, msg: ( outSeconds == 0) ? "合成失败请重试。" : "合成成功")
+                    cShowHUB(superView: nil, msg: (outSeconds == 0) ? "合成失败请重试。" : "合成成功")
                     self?.exportCompletion?(nil, url)
 
                 } else {
@@ -242,47 +236,46 @@ public class BFRecordExport {
                     self?.exportCompletion?(error as Error, nil)
                     cShowHUB(superView: nil, msg: "导出失败")
                 }
-                
+
                 // 导出完成后取消导出
                 self?.exporter?.cancel()
             }
         } else {
             // 没有处理,直接copy原文件
-            if let localPath = data?.first?.localPath{
-                self.exportCompletion?(nil, URL(fileURLWithPath: localPath))
+            if let localPath = data?.first?.localPath {
+                exportCompletion?(nil, URL(fileURLWithPath: localPath))
             }
         }
-
     }
-    
-    func dealAsset(){
+
+    func dealAsset() {
 //        asset?.tracks.first(where: { track in
 //            if track.mediaType == .audio{
 //
 //            }
 //        })
     }
-    
-    func getVideoSize(asset:AVURLAsset) -> CGSize{
+
+    func getVideoSize(asset: AVURLAsset) -> CGSize {
         var size = CGSize.zero
-        asset.tracks.forEach({ track in
-            if track.mediaType == .video{
+        asset.tracks.forEach { track in
+            if track.mediaType == .video {
                 let realSize = __CGSizeApplyAffineTransform(track.naturalSize, track.preferredTransform)
                 size = CGSize(width: ceil(abs(realSize.width)), height: ceil(abs(realSize.height)))
             }
-        })
-        
+        }
+
         return size
     }
 }
 
 extension BFRecordExport {
-    func mergeAudio(videoStickers:[PQEditVisionTrackMaterialsModel], audios:[PQVoiceModel]?, synthesisAll:Bool) -> (AVMutableAudioMix, AVMutableComposition){
+    func mergeAudio(videoStickers: [PQEditVisionTrackMaterialsModel], audios: [PQVoiceModel]?, synthesisAll: Bool) -> (AVMutableAudioMix, AVMutableComposition) {
         let composition = AVMutableComposition()
         let audioMix = AVMutableAudioMix()
         var tempParameters = [AVMutableAudioMixInputParameters]()
-        
-        var totalDuration : Float64 = 0
+
+        var totalDuration: Float64 = 0
         for sticker in videoStickers {
             if sticker.volumeGain == 0 {
                 // 如果添加了会有刺啦音
@@ -295,18 +288,18 @@ extension BFRecordExport {
         }
         if let voices = audios {
             if synthesisAll {
-                tempParameters += mergeRecordVoiceAll(voices:voices, composition)
-            }else {
-                tempParameters += mergeRecordVoiceOnly(voices:voices, composition)
+                tempParameters += mergeRecordVoiceAll(voices: voices, composition)
+            } else {
+                tempParameters += mergeRecordVoiceOnly(voices: voices, composition)
             }
         }
         audioMix.inputParameters = tempParameters
         return (audioMix, composition)
     }
-    
-    func mergeRecordVoiceOnly(voices:[PQVoiceModel], _ composition:AVMutableComposition) -> [AVMutableAudioMixInputParameters] {
+
+    func mergeRecordVoiceOnly(voices: [PQVoiceModel], _ composition: AVMutableComposition) -> [AVMutableAudioMixInputParameters] {
         var tempParameters = [AVMutableAudioMixInputParameters]()
-        var totalDur:Double = 0.0
+        var totalDur: Double = 0.0
         for model in voices {
             if model.volume == 0 {
                 // 如果添加了会有刺啦音
@@ -322,15 +315,15 @@ extension BFRecordExport {
             sticker.aptDuration = duration
             sticker.duration = duration
             sticker.locationPath = model.wavFilePath
-            sticker.volumeGain = 100 //Float64(model.volume)
+            sticker.volumeGain = 100 // Float64(model.volume)
             tempParameters += PQPlayerViewModel.dealWithMaterialTrack(stickerModel: sticker, composition: composition)
             totalDur += duration
         }
 
         return tempParameters
     }
-    
-    func mergeRecordVoiceAll(voices:[PQVoiceModel], _ composition:AVMutableComposition) -> [AVMutableAudioMixInputParameters] {
+
+    func mergeRecordVoiceAll(voices: [PQVoiceModel], _ composition: AVMutableComposition) -> [AVMutableAudioMixInputParameters] {
         var tempParameters = [AVMutableAudioMixInputParameters]()
         for model in voices {
             if model.volume == 0 {
@@ -345,11 +338,10 @@ extension BFRecordExport {
             sticker.aptDuration = model.endTime - model.startTime
             sticker.duration = sticker.aptDuration
             sticker.locationPath = model.wavFilePath
-            sticker.volumeGain = 100 //Float64(model.volume)
+            sticker.volumeGain = 100 // Float64(model.volume)
             tempParameters += PQPlayerViewModel.dealWithMaterialTrack(stickerModel: sticker, composition: composition)
         }
-        
+
         return tempParameters
     }
-    
 }

+ 40 - 46
BFRecordScreenKit/Classes/BFRecordItemModel.swift

@@ -5,55 +5,53 @@
 //  Created by 胡志强 on 2021/12/6.
 //
 
+import BFCommonKit
+import BFMediaKit
 import Foundation
 import Photos
-import BFMediaKit
-import BFCommonKit
 
 struct SplitRecordRange {
-    var isRecord:Bool = false
-    var range:CMTimeRange
-    var index:Int
+    var isRecord: Bool = false
+    var range: CMTimeRange
+    var index: Int
 }
 
 public class BFRecordItemModel: NSObject {
 //    var baseMaterial : AVURLAsset?
-    var localPath : String?
+    var localPath: String?
     var materialDuraion: Double = 0.0
-    var fetchCoverImg : ((UIImage)->Void)?
-    var fetchAVUrlAsset : ((AVURLAsset)->Void)?
-    var fetchPlayItem : ((AVPlayerItem)->Void)?
-    var dealedDurationRanges = [SplitRecordRange]()                     // 录音切割的时间区间,合成导出时计算
-    public var voiceStickers = [PQVoiceModel]()                         //
-    public var videoStickers = [PQEditVisionTrackMaterialsModel]()      // 合成导出时计算
-    public var imageStickers = [PQEditVisionTrackMaterialsModel]()      //
-    public var titleStickers = [PQEditSubTitleModel]()                  // 字幕贴纸
-    public var coverImg : UIImage?
+    var fetchCoverImg: ((UIImage) -> Void)?
+    var fetchAVUrlAsset: ((AVURLAsset) -> Void)?
+    var fetchPlayItem: ((AVPlayerItem) -> Void)?
+    var dealedDurationRanges = [SplitRecordRange]() // 录音切割的时间区间,合成导出时计算
+    public var voiceStickers = [PQVoiceModel]() //
+    public var videoStickers = [PQEditVisionTrackMaterialsModel]() // 合成导出时计算
+    public var imageStickers = [PQEditVisionTrackMaterialsModel]() //
+    public var titleStickers = [PQEditSubTitleModel]() // 字幕贴纸
+    public var coverImg: UIImage?
     public var index = 0
     public var width = 0
     public var height = 0
-    
-    func initOriginData(phasset:PHAsset){
+
+    func initOriginData(phasset: PHAsset) {
         width = phasset.pixelWidth
         height = phasset.pixelHeight
-        
+
         fetchCoverImage(phasset)
         fetchPlayItem(phasset)
         fetchAVUrlAsset(phasset)
-        
     }
-    
-    func fetchCoverImage(_ phasset:PHAsset) {
+
+    func fetchCoverImage(_ phasset: PHAsset) {
         let option = PHImageRequestOptions()
-        option.isNetworkAccessAllowed = true //允许下载iCloud的图片
+        option.isNetworkAccessAllowed = true // 允许下载iCloud的图片
         option.resizeMode = .fast
         option.deliveryMode = .highQualityFormat
         PHImageManager.default().requestImage(for: phasset,
-                                       targetSize: CGSize(width: width, height: height),
-                                      contentMode: .aspectFit,
-                                          options: option)
-        { [weak self] (image, nil) in
-             // 设置首帧/封面
+                                              targetSize: CGSize(width: width, height: height),
+                                              contentMode: .aspectFit,
+                                              options: option) { [weak self] image, _ in
+            // 设置首帧/封面
             if image != nil {
                 self?.fetchCoverImg?(image!)
                 self?.coverImg = image
@@ -61,15 +59,14 @@ public class BFRecordItemModel: NSObject {
         }
     }
 
-    func fetchPlayItem(_ phasset:PHAsset) {
+    func fetchPlayItem(_ phasset: PHAsset) {
         let options = PHVideoRequestOptions()
         options.isNetworkAccessAllowed = true
         options.deliveryMode = .automatic
         if phasset.mediaType == .image {
-            
-        }else if phasset.mediaType == .video{
-            PHImageManager.default().requestPlayerItem(forVideo:phasset, options: options, resultHandler: { [weak self] playerItem, info in
-                
+        } else if phasset.mediaType == .video {
+            PHImageManager.default().requestPlayerItem(forVideo: phasset, options: options, resultHandler: { [weak self] playerItem, _ in
+
                 guard let item = playerItem else {
                     cShowHUB(superView: nil, msg: "视频获取失败:\(self?.index ?? 0)")
                     return
@@ -78,35 +75,33 @@ public class BFRecordItemModel: NSObject {
             })
         }
     }
-    
-    func fetchAVUrlAsset(_ phasset:PHAsset){
+
+    func fetchAVUrlAsset(_ phasset: PHAsset) {
         let options = PHVideoRequestOptions()
         options.isNetworkAccessAllowed = true
         options.deliveryMode = .automatic
 
-        PHCachingImageManager().requestAVAsset(forVideo: phasset, options: options, resultHandler: {[weak self] (asset: AVAsset?, audioMix: AVAudioMix?, info) in
+        PHCachingImageManager().requestAVAsset(forVideo: phasset, options: options, resultHandler: { [weak self] (asset: AVAsset?, _: AVAudioMix?, _) in
             if let urlAsset = asset as? AVURLAsset {
                 self?.materialDuraion = urlAsset.duration.seconds
-                self?.localPath = ((urlAsset.url.absoluteString).removingPercentEncoding)?.replacingOccurrences(of: "file://", with: "")
+                self?.localPath = (urlAsset.url.absoluteString.removingPercentEncoding)?.replacingOccurrences(of: "file://", with: "")
                 self?.fetchAVUrlAsset?(urlAsset)
             }
         })
     }
-    
-    func generationTimeRanges(needSort:Bool = false) {
-        
+
+    func generationTimeRanges(needSort _: Bool = false) {
         dealedDurationRanges.removeAll()
-        
-        var start : Double = 0
-        
+
+        var start: Double = 0
+
         var list: [PQVoiceModel]
         list = voiceStickers.sorted { model1, model2 in
             model1.startTime < model2.startTime
         }
-        
+
         for model in list {
-            
-            if model.startTime > start{
+            if model.startTime > start {
                 //
                 let range = CMTimeRange(start: CMTime(seconds: start, preferredTimescale: 100), duration: CMTime(seconds: model.startTime - start, preferredTimescale: 100))
                 dealedDurationRanges.append(SplitRecordRange(isRecord: false, range: range, index: -1))
@@ -121,6 +116,5 @@ public class BFRecordItemModel: NSObject {
             let range = CMTimeRange(start: CMTime(seconds: start, preferredTimescale: 100), end: CMTime(seconds: materialDuraion, preferredTimescale: 100))
             dealedDurationRanges.append(SplitRecordRange(isRecord: false, range: range, index: -1))
         }
-        
     }
 }

+ 17 - 19
BFRecordScreenKit/Classes/BFVideoThumbImageFetchHelper.swift

@@ -5,44 +5,44 @@
 //  Created by 胡志强 on 2021/12/3.
 //
 
-import Foundation
 import AVFoundation
 import BFCommonKit
+import Foundation
 
 /// 视频分解成帧
 /// - parameter fileUrl                 : 视频地址
 /// - parameter fps                          : 自定义帧数 每秒内取的帧数
 /// - parameter range                     : 获取其中几张连续视频帧
 /// - parameter splitCompleteClosure    : 回调
-func splitVideoFileUrlFps(urlAsset:AVURLAsset, fps:Double, range:NSRange? = nil, splitCompleteClosure:@escaping (([UIImage]) -> Void)) {
+func splitVideoFileUrlFps(urlAsset: AVURLAsset, fps: Double, range: NSRange? = nil, splitCompleteClosure: @escaping (([UIImage]) -> Void)) {
     var splitImages = [UIImage]()
-    
+
     var times = [NSValue]()
-    
+
     var start = 0
     var end = Int(urlAsset.duration.seconds * Float64(fps))
-    
+
     if range != nil {
         start = min(range!.location, end)
         end = min(start + range!.length, end)
     }
-    
+
     for i in start...end {
-        let timeValue = NSValue(time: CMTimeMake(value: Int64(i * 1000), timescale: Int32(fps * 1000)) )
-        
+        let timeValue = NSValue(time: CMTimeMake(value: Int64(i * 1000), timescale: Int32(fps * 1000)))
+
         times.append(timeValue)
     }
-    
+
     let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
     imgGenerator.requestedTimeToleranceBefore = CMTime.zero
     imgGenerator.requestedTimeToleranceAfter = CMTime.zero
-    
+
     let timesCount = times.count
     var cocu = 0
-    //获取每一帧的图片
-    imgGenerator.generateCGImagesAsynchronously(forTimes: times) { (requestedTime, image, actualTime, result, error) in
+    // 获取每一帧的图片
+    imgGenerator.generateCGImagesAsynchronously(forTimes: times) { _, image, _, result, _ in
         cocu += 1
-        switch (result) {
+        switch result {
         case AVAssetImageGenerator.Result.cancelled:
             BFLog(1, message: "splitVideo: cancel")
 
@@ -56,26 +56,24 @@ func splitVideoFileUrlFps(urlAsset:AVURLAsset, fps:Double, range:NSRange? = nil,
         @unknown default:
             break
         }
-        if cocu == timesCount { //最后一帧时 回调赋值
+        if cocu == timesCount { // 最后一帧时 回调赋值
             splitCompleteClosure(splitImages)
             BFLog(1, message: "splitVideo: complete")
-
         }
     }
-   
 }
 
 /// 视频分解成帧
 /// - parameter fileUrl                 : 视频地址
 /// - parameter fps                     : 自定义帧数 每秒内取的帧数
 /// - parameter splitCompleteClosure    : 回调
-func getThumbImageAtTime(urlAsset: AVURLAsset, time:CMTime) -> UIImage? {
+func getThumbImageAtTime(urlAsset: AVURLAsset, time: CMTime) -> UIImage? {
     let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
     imgGenerator.requestedTimeToleranceBefore = CMTime.zero
     imgGenerator.requestedTimeToleranceAfter = CMTime.zero
-    
+
     var cgImg = try? imgGenerator.copyCGImage(at: time, actualTime: nil)
-    if cgImg == nil  {
+    if cgImg == nil {
         imgGenerator.requestedTimeToleranceBefore = CMTime.positiveInfinity
         imgGenerator.requestedTimeToleranceAfter = CMTime.positiveInfinity
         cgImg = try? imgGenerator.copyCGImage(at: time, actualTime: nil)

+ 8 - 10
BFRecordScreenKit/Classes/BFVideoThumbProgressStrategy.swift

@@ -5,30 +5,28 @@
 //  Created by 胡志强 on 2021/12/6.
 //
 
-import Foundation
 import AVFoundation
+import Foundation
 
 protocol BFVideoThumbProgressStrategyProtocol {
-    
     // 根据视频时长获取需要的缩略图数量
     func frameNumberOfVideo(assetDuration: Double) -> Int
 }
 
-class BFVideoThumbProgressStrategy : BFVideoThumbProgressStrategyProtocol {
-
+class BFVideoThumbProgressStrategy: BFVideoThumbProgressStrategyProtocol {
     func frameNumberOfVideo(assetDuration: Double) -> Int {
         var count = -1
-        
-        if assetDuration > 0 && assetDuration <= 10 {
+
+        if assetDuration > 0, assetDuration <= 10 {
             count = 5
-        }else if assetDuration >= 10 && assetDuration < 60 {
+        } else if assetDuration >= 10, assetDuration < 60 {
             count = 10
-        }else if assetDuration >= 60 && assetDuration < 300 {
+        } else if assetDuration >= 60, assetDuration < 300 {
             count = 20
-        }else if assetDuration >= 300{
+        } else if assetDuration >= 300 {
             count = 30
         }
-        
+
         return count
     }
 }

+ 21 - 24
BFRecordScreenKit/Classes/BFVoiceRecordManager.swift

@@ -5,26 +5,24 @@
 //  Created by 胡志强 on 2021/11/24.
 //
 
-import Foundation
 import BFCommonKit
 import BFMediaKit
+import Foundation
 
 class BFVoiceRecordManager {
-    
     // 录音相关
     var audioRecorder: NXAudioRecorder?
-    var limitedDuration:Double = 600       // 限制录制时长
-    var endRecordHandle : ((PQVoiceModel?, Error?) -> Void)?
-    var cancelRecordHandle : ((Error?) -> Void)?
-
-    var recorderFilePath : String = ""
-    var beginRecordTime:Date = Date()
-    var voiceModel : PQVoiceModel?
-    
+    var limitedDuration: Double = 600 // 限制录制时长
+    var endRecordHandle: ((PQVoiceModel?, Error?) -> Void)?
+    var cancelRecordHandle: ((Error?) -> Void)?
+
+    var recorderFilePath: String = ""
+    var beginRecordTime: Date = Date()
+    var voiceModel: PQVoiceModel?
+
     /// 录制音频。 index初衷是记录录音顺序,废弃了
     ///
-    func startRecord(index:Int){
-        
+    func startRecord(index: Int) {
         recorderFilePath = exportAudiosDirectory
 
         if !directoryIsExists(dicPath: recorderFilePath) {
@@ -38,7 +36,7 @@ class BFVoiceRecordManager {
 
         } catch {
             BFLog(message: "录音准备失败,当前无法录音 \(error))")
-            self.cancelRecordHandle?(error)
+            cancelRecordHandle?(error)
             return
         }
 
@@ -57,18 +55,18 @@ class BFVoiceRecordManager {
 
 //        beginRecordTime = Date().timeIntervalSince1970
     }
-    
+
     /// 取消音频录制
-    func cancleRecord(){
+    func cancleRecord() {
         stopRecord(isCancel: true)
         cancelRecordHandle?(nil)
     }
-    
+
     /// 结束音频录制
-    func endRecord(){
+    func endRecord() {
         stopRecord(isCancel: false)
     }
-    
+
     // 取所有声音文件的时长
     func getAudioFileslDuration() -> Float64 {
         let duration: Float64 = 0.0
@@ -79,7 +77,7 @@ class BFVoiceRecordManager {
 //        }
         return duration
     }
-    
+
     /// 停止录制 1,正常停止 2,取消停止
     /// - Parameter isCancel: 是否为取消
     func stopRecord(isCancel: Bool) {
@@ -91,11 +89,11 @@ class BFVoiceRecordManager {
         audioRecorder?.stopRecord { [weak self] isSuccess, url in
             guard let strongSelf = self else { return }
 
-            if strongSelf.getAudioFileslDuration() < 599, (Date().timeIntervalSince( strongSelf.beginRecordTime)) < 1 {
+            if strongSelf.getAudioFileslDuration() < 599, Date().timeIntervalSince(strongSelf.beginRecordTime) < 1 {
                 cShowHUB(superView: nil, msg: "说话时间太短")
             }
 
-            let duration = Date().timeIntervalSince( strongSelf.beginRecordTime)
+            let duration = Date().timeIntervalSince(strongSelf.beginRecordTime)
             if isSuccess && !isCancel && duration > 1 {
                 BFLog(1, message: "结束录音  结果:\(isSuccess) \n url is \(url)")
 
@@ -103,7 +101,7 @@ class BFVoiceRecordManager {
                 let noiseFilePath = url.replacingOccurrences(of: ".wav", with: "_noise_\(1)_.wav")
                 BFLog(1, message: "降噪后地址:\(noiseFilePath)")
                 NXNoiseReduction().denoise(url, outFile: noiseFilePath)
-                if let model = self?.voiceModel{
+                if let model = self?.voiceModel {
                     model.wavFilePath = noiseFilePath
                     self?.endRecordHandle?(model, nil)
                 }
@@ -118,11 +116,10 @@ class BFVoiceRecordManager {
                 } catch {
                     print("Failed to remove recorder file. \(url)")
                 }
-
             }
-
         }
     }
+
     // 合并 成 MP3文件
     func mergeToMP3file() {
 //        isMergeIng = true

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 280 - 304
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenController.swift


+ 0 - 1
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenImageController.swift

@@ -10,6 +10,5 @@ import Foundation
 class BFRecordScreenImageController: BFRecordScreenController {
     override func startRecord() {
         super.startRecord()
-        
     }
 }

+ 0 - 1
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenVideoController.swift

@@ -10,6 +10,5 @@ import Foundation
 class BFRecordScreenVideoController: BFRecordScreenController {
     override func startRecord() {
         super.startRecord()
-        
     }
 }

+ 12 - 19
BFRecordScreenKit/Classes/RecordScreen/View/BFIntroduceToolView.swift

@@ -9,21 +9,20 @@ import Foundation
 import UIKit
 
 class BFIntroduceToolView: UIView {
-    
-    var choosedToolHandle:((UIView) -> Void)?
-    
+    var choosedToolHandle: ((UIView) -> Void)?
+
     fileprivate let toolImgs = ["", "", ""]
-    
-    required init?(coder: NSCoder) {
+
+    required init?(coder _: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
-    
-    override init(frame: CGRect) {
-        super.init(frame: CGRect(x: 0, y: 0, width: 40, height: 40*toolImgs.count))
+
+    override init(frame _: CGRect) {
+        super.init(frame: CGRect(x: 0, y: 0, width: 40, height: 40 * toolImgs.count))
         isUserInteractionEnabled = true
         clipsToBounds = true
-        
-        for i in 0 ..< toolImgs.count {
+
+        for i in 0..<toolImgs.count {
             let btn = UIButton(frame: CGRect(x: 0, y: i * 40, width: 40, height: 40))
             btn.backgroundColor = UIColor.randomColor()
             btn.setTitle("\(i)", for: .normal)
@@ -31,20 +30,14 @@ class BFIntroduceToolView: UIView {
             btn.addTarget(self, action: #selector(toolAction(btn:)), for: .touchUpInside)
             addSubview(btn)
         }
-        
-        
-        
     }
-    
-    @objc func toolAction(btn:UIButton) {
+
+    @objc func toolAction(btn _: UIButton) {
         let v = UILabel(frame: CGRect(x: 0, y: 0, width: 10, height: 40))
         v.backgroundColor = UIColor.randomColor()
         v.layer.shadowColor = UIColor.black.cgColor
         v.layer.shadowRadius = 3
-            
+
         choosedToolHandle?(v)
-    
-        
     }
-    
 }

+ 84 - 93
BFRecordScreenKit/Classes/RecordScreen/View/BFRecordAvatarView.swift

@@ -5,104 +5,103 @@
 //  Created by ak on 2021/12/2.
 //  功能:录制头像 ,生成多个 MP4 文件。
 
-import Foundation
 import BFCommonKit
 import BFMediaKit
 import BFUIKit
+import Foundation
 
-//录制完成回调
-typealias recordEndCallBack = (_ isSucess: Bool,_ material: PQEditVisionTrackMaterialsModel?) -> Void
+// 录制完成回调
+typealias recordEndCallBack = (_ isSucess: Bool, _ material: PQEditVisionTrackMaterialsModel?) -> Void
 
 class BFRecordAvatarView: UIView {
-    
-    //画布
+    // 画布
     var renderView: RenderView!
-    //摄像机
-    var camera:Camera!
-    //是否是录制状态
+    // 摄像机
+    var camera: Camera!
+    // 是否是录制状态
     var isRecording = false
-    //视频输出源
-    var movieOutput:MovieOutput? = nil
-    //录制完成回调
+    // 视频输出源
+    var movieOutput: MovieOutput?
+    // 录制完成回调
     var recordEndCallBack: recordEndCallBack?
-    //录制完成生成的视频文件地址
-    var recorderFilePath:String?
-    //开始录制时间
-    var startRecordeTime:CMTime = .zero
-    
-    //打开摄像头
-    lazy var closedBtn:UIButton = {
+    // 录制完成生成的视频文件地址
+    var recorderFilePath: String?
+    // 开始录制时间
+    var startRecordeTime: CMTime = .zero
+
+    // 打开摄像头
+    lazy var closedBtn: UIButton = {
         let btn = UIButton(type: .custom)
         btn.setImage(imageInRecordScreenKit(by: "CameraClosed"), for: .normal)
         btn.addTarget(self, action: #selector(cameraClosed), for: .touchUpInside)
         return btn
     }()
-    
-    //预览时纹理大小&合成视频大小
-    var videoPixelsSize:Size = Size(width: 120 * Float(UIScreen.main.scale), height: 120 * Float(UIScreen.main.scale))
-    
+
+    // 预览时纹理大小&合成视频大小
+    var videoPixelsSize: Size = Size(width: 120 * Float(UIScreen.main.scale), height: 120 * Float(UIScreen.main.scale))
+
     override init(frame: CGRect) {
         super.init(frame: frame)
-        self.backgroundColor = .yellow
-        
-        renderView = RenderView.init(frame: self.bounds)
+        backgroundColor = .yellow
+
+        renderView = RenderView(frame: bounds)
         addSubview(renderView)
-        
-        self.addSubview(closedBtn)
-        closedBtn.frame = CGRect.init(x: frame.maxX - 68, y: frame.maxY - 68, width: 68, height: 68)
+
+        addSubview(closedBtn)
+        closedBtn.frame = CGRect(x: frame.maxX - 68, y: frame.maxY - 68, width: 68, height: 68)
         do {
-            camera = try Camera(sessionPreset:.high,location: .frontFacing,captureAsYUV: true)
+            camera = try Camera(sessionPreset: .high, location: .frontFacing, captureAsYUV: true)
             //            camera.runBenchmark = true
-           
-            let conertFilter = PQCornerFilter.init()
-            let cropFilter = Crop.init()
+
+            let conertFilter = PQCornerFilter()
+            let cropFilter = Crop()
             cropFilter.cropSizeInPixels = videoPixelsSize
-            cropFilter.cropSizeInPixels =  Size(width: 1080, height:1080)
-            cropFilter.locationOfCropInPixels = Position.init(0, (1920 - 1080) / 2)
-            
+            cropFilter.cropSizeInPixels = Size(width: 1080, height: 1080)
+            cropFilter.locationOfCropInPixels = Position(0, (1920 - 1080) / 2)
+
 //            camera  --> cropFilter --> conertFilter --> renderView
 //            camera  --> cropFilter --> conertFilter --> renderView
         } catch {
             fatalError("Could not initialize rendering pipeline: \(error)")
         }
-        
-       let  Drag = UIPanGestureRecognizer(target: self, action: #selector(onDrag(gesture:)))
+
+        let Drag = UIPanGestureRecognizer(target: self, action: #selector(onDrag(gesture:)))
         addGestureRecognizer(Drag)
     }
-    
+
     required init?(coder _: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
-    
+
     deinit {
         BFLog(message: "BFRecordAvatarView deinit")
         closeCamera()
     }
-    
-    @objc func cameraClosed(){
-        self.isHidden = true
+
+    @objc func cameraClosed() {
+        isHidden = true
         closeCamera()
     }
-    
-    //打开摄像头
-    func openCamera()  {
+
+    // 打开摄像头
+    func openCamera() {
         camera.startCapture()
     }
-    //关闭摄像头
-    func closeCamera()  {
+
+    // 关闭摄像头
+    func closeCamera() {
         camera.stopCapture()
     }
-    
-    //开始录制
-    func beginRecord(startTime:CMTime = .zero) {
-        
-        if(!camera.captureSession.isRunning){
+
+    // 开始录制
+    func beginRecord(startTime: CMTime = .zero) {
+        if !camera.captureSession.isRunning {
             BFLog(message: "摄像机不可用")
             return
         }
         startRecordeTime = startTime
         BFLog(message: "开始录制时间:\(CMTimeGetSeconds(startRecordeTime))")
-        
+
         do {
             recorderFilePath = recordVideosDirectory
             if !directoryIsExists(dicPath: recorderFilePath ?? "") {
@@ -111,40 +110,38 @@ class BFRecordAvatarView: UIView {
             }
             recorderFilePath!.append("recordAvatar_\(Date().timeIntervalSince1970).mp4")
             BFLog(message: "开始录制视频到: \(recorderFilePath ?? "")")
-            
-            movieOutput = try MovieOutput(URL:URL(fileURLWithPath: recorderFilePath ?? ""), size:videoPixelsSize, liveVideo:true)
-            
-            let cropFilter = Crop.init()
-            let conertFilter = PQCornerFilter.init()
-            
+
+            movieOutput = try MovieOutput(URL: URL(fileURLWithPath: recorderFilePath ?? ""), size: videoPixelsSize, liveVideo: true)
+
+            let cropFilter = Crop()
+            let conertFilter = PQCornerFilter()
+
             cropFilter.cropSizeInPixels = videoPixelsSize
-            cropFilter.locationOfCropInPixels = Position.init(0, 0)
-            
-            camera  --> cropFilter --> conertFilter --> movieOutput!
-           
+            cropFilter.locationOfCropInPixels = Position(0, 0)
+
+            camera --> cropFilter --> conertFilter --> movieOutput!
+
             camera.audioEncodingTarget = movieOutput
             movieOutput!.startRecording()
-            
+
         } catch {
             fatalError("Couldn't initialize movie, error: \(error)")
         }
-        
     }
-    
-    //结束录制
+
+    // 结束录制
     func endRecord() {
-        
-        movieOutput?.finishRecording{
+        movieOutput?.finishRecording {
             self.camera.audioEncodingTarget = nil
             self.movieOutput = nil
-            
-            if(self.recorderFilePath != nil && (self.recorderFilePath?.count ?? 0) > 0){
+
+            if self.recorderFilePath != nil && (self.recorderFilePath?.count ?? 0) > 0 {
                 BFLog(message: "录制成功:\(self.recorderFilePath ?? "")")
                 self.recorderFilePath = self.recorderFilePath?.replacingOccurrences(of: documensDirectory, with: "")
-                
-                //拼接回调 model
+
+                // 拼接回调 model
                 let movieAsset = AVURLAsset(url: URL(fileURLWithPath: self.recorderFilePath!), options: avAssertOptions)
-                
+
                 let movieInfo: PQEditVisionTrackMaterialsModel = PQEditVisionTrackMaterialsModel()
                 movieInfo.type = StickerType.VIDEO.rawValue
                 movieInfo.locationPath = self.recorderFilePath ?? ""
@@ -153,22 +150,20 @@ class BFRecordAvatarView: UIView {
                 movieInfo.model_in = 0
                 movieInfo.out = movieInfo.timelineOut
                 movieInfo.canvasFillType = stickerContentMode.aspectFitStr.rawValue
-                
-                if(self.recordEndCallBack != nil){
-                    self.recordEndCallBack!(false,movieInfo)
+
+                if self.recordEndCallBack != nil {
+                    self.recordEndCallBack!(false, movieInfo)
                 }
-                
-            }else{
+
+            } else {
                 BFLog(message: "录制失败:\(self.recorderFilePath ?? "")")
-                if(self.recordEndCallBack != nil){
-                    self.recordEndCallBack!(false,nil)
+                if self.recordEndCallBack != nil {
+                    self.recordEndCallBack!(false, nil)
                 }
             }
-            
         }
-        
     }
-    
+
 //
 //                let movieAsset = AVURLAsset(url: URL(fileURLWithPath: fileURL), options: avAssertOptions)
 //
@@ -182,21 +177,17 @@ class BFRecordAvatarView: UIView {
 //                movieInfo.canvasFillType = stickerContentMode.aspectFitStr.rawValue
 //                recordEndCallBack!(movieInfo)
 //            }
-            
-    
-    //拖拽手势方法具体实现
+
+    // 拖拽手势方法具体实现
     @objc func onDrag(gesture: UIPanGestureRecognizer) {
-        let translation = gesture.translation(in: self.superview)
+        let translation = gesture.translation(in: superview)
         var center = gesture.view!.center
         BFLog(message: "translationtranslationtranslation\(center.x) \(center.y)")
         center.x += translation.x
         center.y += translation.y
-        if(center.x > self.bounds.width / 2 && center.x < cScreenWidth - self.bounds.width / 2 && center.y > self.bounds.height / 2 && center.y < cScreenHeigth - self.bounds.height / 2  ){
+        if center.x > bounds.width / 2, center.x < cScreenWidth - bounds.width / 2, center.y > bounds.height / 2, center.y < cScreenHeigth - bounds.height / 2 {
             gesture.view!.center = center
-            gesture.setTranslation(CGPoint.zero, in: self.superview)
+            gesture.setTranslation(CGPoint.zero, in: superview)
         }
-      
-        
     }
-    
 }

+ 25 - 37
BFRecordScreenKit/Classes/RecordScreen/View/BFSubtitleEditView.swift

@@ -5,16 +5,16 @@
 //  Created by ak on 2021/12/8.
 //
 
-import Foundation
 import BFCommonKit
-import BFUIKit
 import BFMediaKit
+import BFUIKit
+import Foundation
 
 typealias EditSubtitleDone = (_ text: String) -> Void
 
 class BFSubtitleEditView: UIView {
-    var editSubtitleDone:EditSubtitleDone?
-    
+    var editSubtitleDone: EditSubtitleDone?
+
 //    var settingModel:BFSubtitileSettingModel = BFSubtitileSettingModel.init()
     /// 输入框
     lazy var textView: BFTextView = {
@@ -29,23 +29,21 @@ class BFSubtitleEditView: UIView {
         textView.placeHolderColor = UIColor.hexColor(hexadecimal: "#555555")
         textView.delegate = self
 
-        
-        textView.textDidChangedHandle = { [weak self] textView in
-          
+        textView.textDidChangedHandle = { [weak self] _ in
         }
         if #available(iOS 11.0, *) {
             textView.contentInsetAdjustmentBehavior = .never
         }
         return textView
     }()
-    
-    required init?(coder: NSCoder) {
+
+    required init?(coder _: NSCoder) {
         fatalError("init(coder:) has not been implemented")
-        
     }
+
     override init(frame: CGRect) {
-       super.init(frame: frame)
-        backgroundColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.7)
+        super.init(frame: frame)
+        backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.7)
         addSubview(textView)
         textView.snp.makeConstraints { make in
             make.left.equalTo(37)
@@ -53,14 +51,13 @@ class BFSubtitleEditView: UIView {
             make.height.equalTo(280)
             make.top.equalToSuperview().offset(134)
         }
-        
-        
+
         let doneBtn = UIButton()
         doneBtn.backgroundColor = UIColor.hexColor(hexadecimal: "#28BE67")
         doneBtn.setTitle("完成", for: .normal)
         doneBtn.titleLabel?.font = UIFont.systemFont(ofSize: 16)
         doneBtn.addTarget(self, action: #selector(doneAction), for: .touchUpInside)
-        doneBtn.addCorner(corner:4)
+        doneBtn.addCorner(corner: 4)
         addSubview(doneBtn)
         doneBtn.snp.makeConstraints { make in
             make.right.equalTo(-12)
@@ -68,7 +65,7 @@ class BFSubtitleEditView: UIView {
             make.height.equalTo(36)
             make.top.equalToSuperview().offset(48)
         }
-        
+
         let cancelBtn = UIButton()
         cancelBtn.backgroundColor = .clear
         cancelBtn.setTitle("取消", for: .normal)
@@ -83,43 +80,34 @@ class BFSubtitleEditView: UIView {
             make.top.equalToSuperview().offset(45)
         }
     }
-    
-    @objc func cancelAction(){
-        self.isHidden = true
+
+    @objc func cancelAction() {
+        isHidden = true
         textView.resignFirstResponder()
     }
-    
-    @objc func doneAction(){
-        self.isHidden = true
+
+    @objc func doneAction() {
+        isHidden = true
         textView.resignFirstResponder()
-        if(editSubtitleDone != nil){
+        if editSubtitleDone != nil {
             BFLog(message: "最后修改的文字为:\(String(describing: textView.text))")
             editSubtitleDone!(textView.text)
         }
     }
-    
-    func setNewText(text:String) {
-        
+
+    func setNewText(text: String) {
         textView.text = text.substring(to: 30)
 //        BFLog(message: "传值\(textView.text)")
 //
 //        let attributedText = NSMutableAttributedString(string: textView.text,attributes: [.font: UIFont.systemFont(ofSize: CGFloat(settingModel.subtitleSize)  * 375 / 1080),.strokeWidth:-6,.strokeColor: settingModel.strokeColor,.foregroundColor:settingModel.fontColor])
 //        textView.attributedText = attributedText
-
-
-        
     }
-
 }
 
-extension BFSubtitleEditView: UITextViewDelegate{
-    
-    func textViewDidBeginEditing(_ textView: UITextView) {
-       
-    }
+extension BFSubtitleEditView: UITextViewDelegate {
+    func textViewDidBeginEditing(_: UITextView) {}
 
     func textViewDidEndEditing(_ textView: UITextView) {
-     
         BFLog(message: "textViewDidEndEditing 输入完成 \(textView.text ?? "")")
     }
 
@@ -129,7 +117,7 @@ extension BFSubtitleEditView: UITextViewDelegate{
             return false
         }
         BFLog(message: "inputText \(String(describing: textView.text))")
- 
+
         return true
     }
 }

+ 99 - 117
BFRecordScreenKit/Classes/RecordScreen/View/BFSubtitleSettingView.swift

@@ -5,41 +5,39 @@
 //  Created by ak on 2021/12/7.
 //  功能:设置字幕操作面板
 
-import Foundation
-import BFMediaKit
 import BFCommonKit
+import BFMediaKit
 import BFUIKit
+import Foundation
 
 typealias SubtitleSettingCallBack = (_ subtitileModel: PQEditSubTitleModel) -> Void
 
 class BFSubtitleSettingView: UIView {
-    
-    required init?(coder: NSCoder) {
+    required init?(coder _: NSCoder) {
         fatalError("init(coder:) has not been implemented")
-        
     }
-    
-    //最后一次选择的样式 BTN
-    var lastSelectStyleBtn:UIButton = UIButton.init();
-    //最后一次选择的位置 BTN
-    var lastSelectPointBtn:UIButton = UIButton.init();
-    //最后一次选择的字号的 BTN
-    var lastSelectwordSizeBtn:UIButton = UIButton.init();
-    
-    var subtitleSettingCallBack:SubtitleSettingCallBack?
-    
-    var subtitle:PQEditSubTitleModel = PQEditSubTitleModel.init()
-    
-    //样式配置
-    var styleConfig:Dictionary<Int,Dictionary<String,Any>> = Dictionary.init()
-     
+
+    // 最后一次选择的样式 BTN
+    var lastSelectStyleBtn: UIButton = UIButton()
+    // 最后一次选择的位置 BTN
+    var lastSelectPointBtn: UIButton = UIButton()
+    // 最后一次选择的字号的 BTN
+    var lastSelectwordSizeBtn: UIButton = UIButton()
+
+    var subtitleSettingCallBack: SubtitleSettingCallBack?
+
+    var subtitle: PQEditSubTitleModel = PQEditSubTitleModel()
+
+    // 样式配置
+    var styleConfig: [Int: [String: Any]] = Dictionary()
+
     override init(frame: CGRect) {
         super.init(frame: frame)
-        
-        self.backgroundColor = UIColor.clear
+
+        backgroundColor = UIColor.clear
         addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(hidden)))
-        
-        let backView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: cScreenWidth, height: cScreenHeigth))
+
+        let backView = UIView(frame: CGRect(x: 0, y: 0, width: cScreenWidth, height: cScreenHeigth))
         backView.backgroundColor = .black
         addSubview(backView)
         backView.snp.makeConstraints { make in
@@ -48,41 +46,37 @@ class BFSubtitleSettingView: UIView {
             make.width.equalTo(cScreenWidth)
             make.height.equalTo(220)
         }
- 
-        styleConfig = [0:["fontColor":UIColor.hexColor(hexadecimal:               "#FFCF53"),"backgroundColor":UIColor.clear,"strokeColor":UIColor.black,"backgroundAlpha":0.0],
-                       1:["fontColor":UIColor.hexColor(hexadecimal: "#FF9292"),"backgroundColor":UIColor.clear,"strokeColor":UIColor.black,"backgroundAlpha":0.0],
-                       2:["fontColor":UIColor.hexColor(hexadecimal: "#80C2FF"),"backgroundColor":UIColor.clear,"strokeColor":UIColor.black,"backgroundAlpha":0.0],
-                       3:["fontColor":UIColor.hexColor(hexadecimal: "#80E4AB"),"backgroundColor":UIColor.clear,"strokeColor":UIColor.black,"backgroundAlpha":0.0],
-                       4:["fontColor":UIColor.hexColor(hexadecimal: "#FFFFFF"),"backgroundColor":UIColor.clear,"strokeColor":UIColor.black,"backgroundAlpha":0.0],
-                       5:["fontColor":UIColor.hexColor(hexadecimal: "#000000"),"backgroundColor":UIColor.clear,"strokeColor":UIColor.white,"backgroundAlpha":0.0],
-                     6:["fontColor":UIColor.hexColor(hexadecimal: "#FFFFFF"),"backgroundColor":UIColor.black,"strokeColor":UIColor.black,"backgroundAlpha":0.6]
-        ]
-
-        
-        //字体样式
+
+        styleConfig = [0: ["fontColor": UIColor.hexColor(hexadecimal: "#FFCF53"), "backgroundColor": UIColor.clear, "strokeColor": UIColor.black, "backgroundAlpha": 0.0],
+                       1: ["fontColor": UIColor.hexColor(hexadecimal: "#FF9292"), "backgroundColor": UIColor.clear, "strokeColor": UIColor.black, "backgroundAlpha": 0.0],
+                       2: ["fontColor": UIColor.hexColor(hexadecimal: "#80C2FF"), "backgroundColor": UIColor.clear, "strokeColor": UIColor.black, "backgroundAlpha": 0.0],
+                       3: ["fontColor": UIColor.hexColor(hexadecimal: "#80E4AB"), "backgroundColor": UIColor.clear, "strokeColor": UIColor.black, "backgroundAlpha": 0.0],
+                       4: ["fontColor": UIColor.hexColor(hexadecimal: "#FFFFFF"), "backgroundColor": UIColor.clear, "strokeColor": UIColor.black, "backgroundAlpha": 0.0],
+                       5: ["fontColor": UIColor.hexColor(hexadecimal: "#000000"), "backgroundColor": UIColor.clear, "strokeColor": UIColor.white, "backgroundAlpha": 0.0],
+                       6: ["fontColor": UIColor.hexColor(hexadecimal: "#FFFFFF"), "backgroundColor": UIColor.black, "strokeColor": UIColor.black, "backgroundAlpha": 0.6]]
+
+        // 字体样式
         for i in 0...6 {
             let btn = UIButton(type: .custom)
             btn.setImage(imageInRecordScreenKit(by: "wordStyle\(i + 1)"), for: .normal)
-            btn.setBackgroundImage(UIImage.init(color:.black), for: .normal)
-            btn.frame = CGRect.init(x: 18 + i * ( 40 + 10) , y: 22, width: 40, height: 40)
+            btn.setBackgroundImage(UIImage(color: .black), for: .normal)
+            btn.frame = CGRect(x: 18 + i * (40 + 10), y: 22, width: 40, height: 40)
             btn.tag = i
-            if(i == 0){
+            if i == 0 {
                 btn.isSelected = true
                 btn.layer.borderColor = UIColor.hexColor(hexadecimal: "#28BE67").cgColor
                 btn.layer.borderWidth = 1.5
                 lastSelectStyleBtn = btn
-                
+
                 styleSetting(sender: lastSelectStyleBtn)
-                
             }
-        
+
             btn.addTarget(self, action: #selector(styleSetting(sender:)), for: .touchUpInside)
             backView.addSubview(btn)
             btn.addCorner(corner: 20.0)
-
         }
-        
-        //位置
+
+        // 位置
         let pointTitle = UILabel()
         pointTitle.textAlignment = .center
         pointTitle.font = UIFont.systemFont(ofSize: 15)
@@ -96,38 +90,36 @@ class BFSubtitleSettingView: UIView {
             make.left.equalToSuperview().offset(16)
             make.top.equalToSuperview().offset(89)
         }
-        for i  in 0...2 {
+        for i in 0...2 {
             let pointBtn = UIButton(type: .custom)
             pointBtn.setTitleColor(UIColor.hexColor(hexadecimal: "#28BE67"), for: .selected)
             pointBtn.setTitleColor(.white, for: .normal)
             pointBtn.addTarget(self, action: #selector(pointSetting(sender:)), for: .touchUpInside)
             pointBtn.backgroundColor = UIColor.hexColor(hexadecimal: "#1A1A1A")
-            if(i == 0){
+            if i == 0 {
                 pointBtn.isSelected = true
                 pointBtn.layer.borderColor = UIColor.hexColor(hexadecimal: "#28BE67").cgColor
                 pointBtn.layer.borderWidth = 1.5
                 lastSelectPointBtn = pointBtn
                 pointBtn.setTitle("下", for: .normal)
-            }else if(i == 1){
+            } else if i == 1 {
                 pointBtn.setTitle("中", for: .normal)
-            }else{
+            } else {
                 pointBtn.setTitle("上", for: .normal)
             }
-            pointBtn.addCorner(corner:10)
+            pointBtn.addCorner(corner: 10)
             pointBtn.tag = i
             backView.addSubview(pointBtn)
             pointBtn.snp.makeConstraints { make in
                 make.width.equalTo(40)
                 make.height.equalTo(30)
-                make.centerX.equalTo(pointTitle.snp.centerX).offset(60 + i * (Int(40  + 10)))
-                
+                make.centerX.equalTo(pointTitle.snp.centerX).offset(60 + i * Int(40 + 10))
+
                 make.centerY.equalTo(pointTitle.snp.centerY)
             }
-            
-            
         }
-        
-        //字号
+
+        // 字号
         let wordSizeTitle = UILabel()
         wordSizeTitle.textAlignment = .center
         wordSizeTitle.font = UIFont.systemFont(ofSize: 15)
@@ -141,7 +133,7 @@ class BFSubtitleSettingView: UIView {
             make.right.equalToSuperview().offset(-100)
             make.top.equalTo(pointTitle.snp.top)
         }
-        for i  in 0...1 {
+        for i in 0...1 {
             let wordSizeBtn = UIButton(type: .custom)
             wordSizeBtn.addTarget(self, action: #selector(wordSizeSetting(sender:)), for: .touchUpInside)
             wordSizeBtn.backgroundColor = UIColor.hexColor(hexadecimal: "#1A1A1A")
@@ -150,36 +142,34 @@ class BFSubtitleSettingView: UIView {
             wordSizeBtn.setTitle(i == 0 ? "-" : "+", for: .normal)
             backView.addSubview(wordSizeBtn)
             wordSizeBtn.tag = i
-            if(i == 0){
+            if i == 0 {
                 wordSizeBtn.isSelected = true
                 wordSizeBtn.layer.borderColor = UIColor.hexColor(hexadecimal: "#28BE67").cgColor
                 wordSizeBtn.layer.borderWidth = 1.5
                 lastSelectwordSizeBtn = wordSizeBtn
             }
-            wordSizeBtn.addCorner(corner:10)
+            wordSizeBtn.addCorner(corner: 10)
             wordSizeBtn.snp.makeConstraints { make in
                 make.width.equalTo(30)
                 make.height.equalTo(30)
-                make.left.equalTo(wordSizeTitle.snp.right).offset( 10 + i * (Int(30  + 10)))
-                
+                make.left.equalTo(wordSizeTitle.snp.right).offset(10 + i * Int(30 + 10))
+
                 make.centerY.equalTo(pointTitle.snp.centerY)
             }
-            
-            
         }
-        //就是一个线
-        let line = UIView.init()
-        line.backgroundColor =  UIColor.hexColor(hexadecimal: "#121212")
+        // 就是一个线
+        let line = UIView()
+        line.backgroundColor = UIColor.hexColor(hexadecimal: "#121212")
         backView.addSubview(line)
-        
+
         line.snp.makeConstraints { make in
             make.width.equalTo(340)
             make.height.equalTo(2)
             make.left.equalToSuperview().offset(18)
             make.top.equalTo(wordSizeTitle.snp.bottom).offset(23)
         }
-        
-        //不显示字幕
+
+        // 不显示字幕
         let disabelTitle = UILabel()
         disabelTitle.textAlignment = .left
         disabelTitle.font = UIFont.boldSystemFont(ofSize: 17)
@@ -203,94 +193,86 @@ class BFSubtitleSettingView: UIView {
             make.right.equalToSuperview().offset(-18)
             make.top.equalTo(line.snp.top).offset(13)
         }
-     
-        
-        
+
         //        addCorner(roundingCorners: .topLeft, corner: 10)
         //        addCorner(roundingCorners: .topRight, corner: 10)
         BFLog(message: "")
-        
     }
-    
-    @objc func hidden(){
-        self.isHidden = true
+
+    @objc func hidden() {
+        isHidden = true
     }
-    
-    @objc func styleSetting(sender: UIButton){
+
+    @objc func styleSetting(sender: UIButton) {
         lastSelectStyleBtn.isSelected = false
         lastSelectStyleBtn.layer.borderColor = UIColor.clear.cgColor
-        
+
         sender.isSelected = true
         lastSelectStyleBtn = sender
-        
+
         sender.layer.borderColor = UIColor.hexColor(hexadecimal: "#28BE67").cgColor
         sender.layer.borderWidth = 1.5
-        
+
         subtitle.setting.subtitleStyle = sender.tag
-        
+
         let config = styleConfig[sender.tag]
-        
+
         subtitle.setting.fontColor = config?["fontColor"] as! UIColor
         subtitle.setting.backgroundColor = config?["backgroundColor"] as! UIColor
         subtitle.setting.backgroundAlpha = Float(config?["backgroundAlpha"] as! Double)
         subtitle.setting.strokeColor = config?["strokeColor"] as! UIColor
- 
-        if(subtitleSettingCallBack != nil){
+
+        if subtitleSettingCallBack != nil {
             subtitleSettingCallBack!(subtitle)
         }
-     
     }
-    @objc func pointSetting(sender:UIButton){
-        
+
+    @objc func pointSetting(sender: UIButton) {
         lastSelectPointBtn.isSelected = false
         lastSelectPointBtn.layer.borderColor = UIColor.clear.cgColor
-        
+
         sender.isSelected = true
         lastSelectPointBtn = sender
-        
+
         sender.layer.borderColor = UIColor.hexColor(hexadecimal: "#28BE67").cgColor
         sender.layer.borderWidth = 1.5
-        
+
         subtitle.setting.subtitlePoint = sender.tag
-    
-        if(subtitleSettingCallBack != nil){
+
+        if subtitleSettingCallBack != nil {
             subtitleSettingCallBack!(subtitle)
         }
     }
-    @objc func wordSizeSetting(sender:UIButton){
-     
+
+    @objc func wordSizeSetting(sender: UIButton) {
         lastSelectwordSizeBtn.isSelected = false
         lastSelectwordSizeBtn.layer.borderColor = UIColor.clear.cgColor
-        
+
         sender.isSelected = true
         lastSelectwordSizeBtn = sender
-        
+
         sender.layer.borderColor = UIColor.hexColor(hexadecimal: "#28BE67").cgColor
         sender.layer.borderWidth = 1.5
 
-            if(sender.tag == 0 && subtitle.setting.subtitleSize > 20){
-                subtitle.setting.subtitleSize -= 10
-            }else if(sender.tag == 1 && subtitle.setting.subtitleSize < 120){
-                subtitle.setting.subtitleSize += 10
-            }else{
-                BFLog(message: "设置字号超出范围!")
-            }
-            if(subtitleSettingCallBack != nil){
-                subtitleSettingCallBack!(subtitle)
-            }
-            
-        
-   
+        if sender.tag == 0, subtitle.setting.subtitleSize > 20 {
+            subtitle.setting.subtitleSize -= 10
+        } else if sender.tag == 1, subtitle.setting.subtitleSize < 120 {
+            subtitle.setting.subtitleSize += 10
+        } else {
+            BFLog(message: "设置字号超出范围!")
+        }
+        if subtitleSettingCallBack != nil {
+            subtitleSettingCallBack!(subtitle)
+        }
     }
-    @objc func switchChange(uiswitch:UISwitch) {
-        print("字幕开关状态\(uiswitch.isOn )")
-        
+
+    @objc func switchChange(uiswitch: UISwitch) {
+        print("字幕开关状态\(uiswitch.isOn)")
+
         subtitle.setting.subtitleIsShow = !uiswitch.isOn
-        
-        if(subtitleSettingCallBack != nil){
+
+        if subtitleSettingCallBack != nil {
             subtitleSettingCallBack!(subtitle)
         }
     }
 }
-
-

+ 46 - 50
BFRecordScreenKit/Classes/RecordScreen/View/BFVideoThumbProgressView.swift

@@ -5,26 +5,26 @@
 //  Created by 胡志强 on 2021/12/3.
 //
 
-import Foundation
-import UIKit
 import AVFoundation
 import BFCommonKit
-import SnapKit
 import BFUIKit
+import Foundation
+import SnapKit
+import UIKit
 
 class BFVideoThumbProgressView: UIView {
-    var videoAsset : AVURLAsset? {
-        didSet{
+    var videoAsset: AVURLAsset? {
+        didSet {
             if let videoAsset = videoAsset {
                 let dur = videoAsset.duration.seconds
-                if dur > 0{
+                if dur > 0 {
                     let fps = Double(fetchThumbStrategy.frameNumberOfVideo(assetDuration: dur)) / dur
-                    
-                    splitVideoFileUrlFps(urlAsset: videoAsset, fps: fps) {[weak self] images in
-                        if images.count > 0{
+
+                    splitVideoFileUrlFps(urlAsset: videoAsset, fps: fps) { [weak self] images in
+                        if images.count > 0 {
                             self?.thumbImgs = images
-                            DispatchQueue.main.async {[weak self] in
-                                if let sself = self{
+                            DispatchQueue.main.async { [weak self] in
+                                if let sself = self {
                                     var lastiv = UIImageView()
                                     for (i, img) in images.enumerated() {
                                         let iv = UIImageView(image: img)
@@ -42,7 +42,7 @@ class BFVideoThumbProgressView: UIView {
                                     lastiv.snp.makeConstraints { make in
                                         make.right.equalTo(sself.width * -0.5)
                                     }
-                                    
+
                                     sself.progressView.contentView.addSubview(sself.progessIndicateBackV)
                                     sself.progessIndicateBackV.snp.makeConstraints { make in
                                         make.left.equalTo(sself.width * 0.5)
@@ -54,49 +54,48 @@ class BFVideoThumbProgressView: UIView {
                             }
                         }
                     }
-                    
                 }
             }
         }
     }
-    
-    var dragScrollProgressHandle : ((Bool, Float) -> Void)?
-    var dragEndHandle : ((Float) -> Void)?
-    var dragStartHandle : (() -> Void)?
+
+    var dragScrollProgressHandle: ((Bool, Float) -> Void)?
+    var dragEndHandle: ((Float) -> Void)?
+    var dragStartHandle: (() -> Void)?
     var isDrag = false
-    
+
     let thumbImageWidth = 70.0
-    
-    let fetchThumbStrategy : BFVideoThumbProgressStrategyProtocol = BFVideoThumbProgressStrategy()
-    
-    var progress:Double = 0 {
-        didSet{
-            if let second = self.videoAsset?.duration.seconds, second > 0 {
+
+    let fetchThumbStrategy: BFVideoThumbProgressStrategyProtocol = BFVideoThumbProgressStrategy()
+
+    var progress: Double = 0 {
+        didSet {
+            if let second = videoAsset?.duration.seconds, second > 0 {
                 let w = progressView.contentSize.width - width
                 progressView.contentOffset = CGPoint(x: progress * Double(w) / second, y: 0)
             }
         }
     }
-    
+
     var thumbImgs = [UIImage]()
-    
-    lazy var progressView : BFAutolayoutScrollView = {
+
+    lazy var progressView: BFAutolayoutScrollView = {
         let sv = BFAutolayoutScrollView()
         sv.bounces = false
         sv.backgroundColor = .clear
         sv.decelerationRate = .fast
         sv.showsHorizontalScrollIndicator = false
         sv.delegate = self
-        
+
         return sv
     }()
-    
-    lazy var progessIndicateBackV : UIView = {
+
+    lazy var progessIndicateBackV: UIView = {
         let vv = UIView()
         return vv
     }()
-    
-    //MARK: - 生命周期
+
+    // MARK: - 生命周期
 
     override init(frame: CGRect) {
         super.init(frame: frame)
@@ -112,50 +111,47 @@ class BFVideoThumbProgressView: UIView {
             make.width.equalTo(3)
             make.center.height.equalToSuperview()
         }
-        
     }
 
-    required init?(coder: NSCoder) {
+    required init?(coder _: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
-    
+
     override func layoutSubviews() {
         super.layoutSubviews()
-        
+
         progressView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
         }
-        
     }
 }
 
-extension BFVideoThumbProgressView : UIScrollViewDelegate {
+extension BFVideoThumbProgressView: UIScrollViewDelegate {
     func scrollViewDidScroll(_ scrollView: UIScrollView) {
-        if isDrag{
-            let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - self.width)
-            self.dragScrollProgressHandle?(false, Float(dur))
+        if isDrag {
+            let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
+            dragScrollProgressHandle?(false, Float(dur))
         }
     }
-    
+
     func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
         isDrag = true
-        let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - self.width)
-        self.dragStartHandle?()
-        self.dragScrollProgressHandle?(true, Float(dur))
+        let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
+        dragStartHandle?()
+        dragScrollProgressHandle?(true, Float(dur))
     }
-    
+
     func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
         if !decelerate {
-            let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - self.width)
+            let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
             isDrag = false
             dragEndHandle?(Float(dur))
         }
     }
-    
+
     func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
-        let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - self.width)
+        let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
         isDrag = false
         dragEndHandle?(Float(dur))
     }
-    
 }

+ 18 - 23
BFRecordScreenKit/Classes/RecordScreen/ViewModel/BFRecordScreenViewModel.swift

@@ -5,18 +5,17 @@
 //  Created by ak on 2021/12/7.
 //
 
-import Foundation
+import BFCommonKit
 import BFMediaKit
+import BFNetRequestKit
+import Foundation
 import ObjectMapper
 import RealmSwift
-import BFCommonKit
-import BFNetRequestKit
 
-public class BFRecordScreenViewModel:NSObject{
-   
+public class BFRecordScreenViewModel: NSObject {
     /// 取文本转语言 token
     /// - Parameter completeHander: <#completeHander description#>
-    class public func getNlsAccessToken(completeHander: @escaping (_ token: String, _ appkey:String) -> Void) {
+    public class func getNlsAccessToken(completeHander: @escaping (_ token: String, _ appkey: String) -> Void) {
         let NlsAccessTokenKey: String = "NlsAccessTokenKey_JiangjieApp"
 
         let nowTime: TimeInterval = Date().timeIntervalSince1970
@@ -26,39 +25,36 @@ public class BFRecordScreenViewModel:NSObject{
         let saveToken: Dictionary? = getUserDefaults(key: NlsAccessTokenKey) as? [String: Any] ?? nil
         if saveToken != nil && Double(saveToken!["expireTime"] as! Double) > nowTime * 1000 {
             BFLog(message: "nls token 还有效期内不用重新请求 \(String(describing: saveToken!["expireTime"])) nowTime:\(nowTime * 1000)")
-            completeHander(saveToken!["token"] as! String,saveToken!["appkey"] as! String)
+            completeHander(saveToken!["token"] as! String, saveToken!["appkey"] as! String)
             return
         }
         BFNetRequestAdaptor.getRequestData(url: PQENVUtil.shared.clipapiapi + getNlsAccessTokenForJiangjieApp, parames: nil, commonParams: commonParams()) { response, _, _, _ in
 
-            if let response = response as? [String: Any], let token = response["token"] as? String , let appkey = response["appkey"] as? String {
+            if let response = response as? [String: Any], let token = response["token"] as? String, let appkey = response["appkey"] as? String {
                 let nowTime: TimeInterval = Date().timeIntervalSince1970
 
                 BFLog(message: "nowTime is \(nowTime) token is \(token)")
                 saveUserDefaults(key: NlsAccessTokenKey, value: response)
 
-                completeHander(token,appkey)
+                completeHander(token, appkey)
             } else {
-                completeHander("","")
+                completeHander("", "")
             }
         }
     }
-    
-    
+
     /// 分段识别录音
     /// - Parameters:
     ///   - sectionIndex: 段落id
     ///   - locationPaths: 分段录音
     ///   - completeHander: <#completeHander description#>
     /// - Returns: description
-    class public func batchUploadRecordVoiceMatarialData(beginTime: CMTime, locationPath: String, completeHander: @escaping (_ subTitleList: List<PQEditVisionTrackMaterialsModel>?, _ msg: String?) -> Void) {
-      
+    public class func batchUploadRecordVoiceMatarialData(beginTime _: CMTime, locationPath: String, completeHander _: @escaping (_ subTitleList: List<PQEditVisionTrackMaterialsModel>?, _ msg: String?) -> Void) {
         BFLog(message: "录音文件开始上传--\(locationPath)")
-     
-        if !FileManager.default.fileExists(atPath:documensDirectory + locationPath) {
+
+        if !FileManager.default.fileExists(atPath: documensDirectory + locationPath) {
             BFLog(message: "上传录音-录音文件不存在")
         } else {
-
             let assert = AVURLAsset(url: URL(fileURLWithPath: documensDirectory + locationPath), options: nil)
             let voiceMaterials: PQEditVisionTrackMaterialsModel = PQEditVisionTrackMaterialsModel()
             voiceMaterials.locationPath = locationPath
@@ -68,7 +64,7 @@ public class BFRecordScreenViewModel:NSObject{
 //            PQVideoEditViewModel.uploadMatarialData(isBatchUpload: false, materialData: voiceMaterials) { _, _, _, _, _, _, matarialInfo, _ in
 //                let materialType: String = "\(matarialInfo?["materialType"] ?? "")"
 //                let localPath: String = "\(matarialInfo?["localPath"] ?? "")"
-//                
+//
 //                BFLog(message: "上传录音-录音上传返回--\(String(describing: matarialInfo))")
 //                if matarialInfo != nil, matarialInfo?.keys.contains("localPath") ?? false, materialType == StickerType.VOICE.rawValue && localPath.contains("_noise_") {
 //                    BFLog(message: "上传录音-录音上传成功开始转化字幕")
@@ -76,16 +72,16 @@ public class BFRecordScreenViewModel:NSObject{
 //                    let duration: Float64 = Float64("\(matarialInfo?["duration"] ?? "")") ?? 0
 //                    PQVideoEditViewModel.transferAudioMaterialToTextData(Int64(materialId) ?? 0, dutation: duration) { _, _, subTitleList, _ in
 //                        BFLog(message: "上传录音-字幕转化完成:\(subTitleList.count)")
-// 
+//
 //                        if subTitleList.count > 0 {
-//                    
+//
 //                        }
-//                
+//
 //                    }
 //                }
 //            }
         }
-        
+
         //        dispatchGroup.notify(queue: DispatchQueue.main) {
         //            BFLog(message: "语音均已识别完成")
         //            let subTitleList: List<PQEditVisionTrackMaterialsModel> = List<PQEditVisionTrackMaterialsModel>.init()
@@ -98,5 +94,4 @@ public class BFRecordScreenViewModel:NSObject{
         //            completeHander(sectionIndex, subTitleList, nil)
         //        }
     }
-    
 }

+ 11 - 16
Example/BFRecordScreenKit/AppDelegate.swift

@@ -6,17 +6,15 @@
 //  Copyright (c) 2021 harry. All rights reserved.
 //
 
-import UIKit
-import BFMaterialKit
 import BFCommonKit
+import BFMaterialKit
+import UIKit
 
 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {
-
     var window: UIWindow?
 
-
-    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
+    func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
         // Override point for customization after application launch.
         BFConfig.shared.styleColor = .nomal
         BFConfig.shared.statusBarStyle = .light
@@ -25,18 +23,18 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
         BFConfig.shared.cutViewStyleColor = UIColor.white
         BFConfig.shared.cutViewTintColor = UIColor.black
         BFConfig.shared.pointEditNamalBackgroundColor = UIColor.hexColor(hexadecimal: "#1A1A1A")
-        BFMaterialConfig.shared.materialDeleteImage =  UIImage.moduleImage(named: "icon_search_delete", moduleName: "BFMaterialKit") ?? UIImage.init()
+        BFMaterialConfig.shared.materialDeleteImage = UIImage.moduleImage(named: "icon_search_delete", moduleName: "BFMaterialKit") ?? UIImage()
         BFConfig.shared.cutDurationColor = UIColor(red: 238.0 / 255.0, green: 0 / 255.0, blue: 81.0 / 255.0, alpha: 0.1)
         BFConfig.shared.hiddenMusicMask = false
         BFConfig.shared.otherTintColor = UIColor.hexColor(hexadecimal: "#333333")
         BFConfig.shared.statusBarStyle = .light
         BFMaterialConfig.shared.choseType = .single
-        if let tbc = self.window?.rootViewController as? UITabBarController {
+        if let tbc = window?.rootViewController as? UITabBarController {
             tbc.selectedIndex = 1
             tbc.tabBar.barTintColor = .black
             tbc.tabBar.backgroundColor = .black
             tbc.tabBar.tintColor = .black
-            
+
             for item in tbc.tabBar.items! {
                 item.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
             }
@@ -44,28 +42,25 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
         return true
     }
 
-    func applicationWillResignActive(_ application: UIApplication) {
+    func applicationWillResignActive(_: UIApplication) {
         // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
         // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
     }
 
-    func applicationDidEnterBackground(_ application: UIApplication) {
+    func applicationDidEnterBackground(_: UIApplication) {
         // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
         // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
     }
 
-    func applicationWillEnterForeground(_ application: UIApplication) {
+    func applicationWillEnterForeground(_: UIApplication) {
         // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
     }
 
-    func applicationDidBecomeActive(_ application: UIApplication) {
+    func applicationDidBecomeActive(_: UIApplication) {
         // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     }
 
-    func applicationWillTerminate(_ application: UIApplication) {
+    func applicationWillTerminate(_: UIApplication) {
         // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
     }
-
-
 }
-

+ 6 - 7
Example/BFRecordScreenKit/IntroduceController.swift

@@ -6,18 +6,17 @@
 //  Copyright © 2021 CocoaPods. All rights reserved.
 //
 
-import Foundation
-import BFUIKit
 import BFRecordScreenKit
+import BFUIKit
+import Foundation
 import Photos
 
-class IntroduceController : BFBaseViewController {
-    
-    var asset:PHAsset?
+class IntroduceController: BFBaseViewController {
+    var asset: PHAsset?
 
     override func viewDidLoad() {
         super.viewDidLoad()
-        
+
         let vc = BFRecordScreenController()
         if asset != nil {
             vc.assets = [asset!]
@@ -33,7 +32,7 @@ class IntroduceController : BFBaseViewController {
         vc.closeActionHandle = {
             self.backBtnClick()
         }
-        vc.view.frame = self.view.frame
+        vc.view.frame = view.frame
         addChildViewController(vc)
         view.addSubview(vc.view)
     }

+ 23 - 27
Example/BFRecordScreenKit/PhotoVideoListController.swift

@@ -6,18 +6,17 @@
 //  Copyright © 2021 CocoaPods. All rights reserved.
 //
 
-import Foundation
-import BFUIKit
+import BFCommonKit
 import BFMaterialKit
-import UIKit
 import BFRecordScreenKit
+import BFUIKit
+import Foundation
 import Photos
-import BFCommonKit
+import UIKit
 
 class PhotoVideoListController: BFBaseViewController {
-    
-    var chosedAsset:PHAsset?
-    
+    var chosedAsset: PHAsset?
+
     lazy var albumController: BFPhotoAlbumController = {
         let albumController = BFPhotoAlbumController()
         albumController.mediaType = .video
@@ -35,14 +34,14 @@ class PhotoVideoListController: BFBaseViewController {
         }
         return albumController
     }()
-    
+
     lazy var changeCollecBtn: UIButton = {
         let changeCollecBtn = UIButton(frame: CGRect(x: cDefaultMargin * 5, y: cDevice_iPhoneStatusBarHei, width: cScreenWidth - cDefaultMargin * 10, height: cDefaultMargin * 4))
         changeCollecBtn.titleLabel?.lineBreakMode = .byTruncatingTail
         changeCollecBtn.tintColor = BFConfig.shared.styleTitleColor
         changeCollecBtn.setTitle("我的相册", for: .normal)
-        changeCollecBtn.setImage(UIImage.moduleImage(named: "icon_selected_down", moduleName: "BFFramework",isAssets: false)?.withRenderingMode(.alwaysTemplate), for: .normal)
-        changeCollecBtn.setImage(UIImage.moduleImage(named: "icon_selected_up", moduleName: "BFFramework",isAssets: false)?.withRenderingMode(.alwaysTemplate), for: .selected)
+        changeCollecBtn.setImage(UIImage.moduleImage(named: "icon_selected_down", moduleName: "BFFramework", isAssets: false)?.withRenderingMode(.alwaysTemplate), for: .normal)
+        changeCollecBtn.setImage(UIImage.moduleImage(named: "icon_selected_up", moduleName: "BFFramework", isAssets: false)?.withRenderingMode(.alwaysTemplate), for: .selected)
         changeCollecBtn.setTitleColor(BFConfig.shared.styleTitleColor, for: .normal)
         changeCollecBtn.titleLabel?.font = UIFont.systemFont(ofSize: 18, weight: .medium)
         changeCollecBtn.tag = 1
@@ -50,32 +49,30 @@ class PhotoVideoListController: BFBaseViewController {
         changeCollecBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
         return changeCollecBtn
     }()
-    
+
     lazy var photoMaterialVc: BFPhotosMaterialController = {
         let vc = BFPhotosMaterialController()
         vc.view.backgroundColor = .black
         vc.updateFrame(newFrame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei - cDevice_iPhoneTabBarHei))
         vc.selectedMaterialHandle = { [weak self] currentMaterialData, selectedPhotoData, _, _ in
-            if currentMaterialData?.isSelected ?? false{
+            if currentMaterialData?.isSelected ?? false {
                 self?.chosedAsset = currentMaterialData
                 if selectedPhotoData.count == 2 {
                     cShowHUB(superView: nil, msg: "临时:最新选择的视频是有效的视频")
                 }
-            }else{
+            } else {
                 self?.chosedAsset = selectedPhotoData.first
             }
-            
         }
         return vc
     }()
-    
+
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
         showNavigation()
         photoMaterialVc.hiddenNavigation()
-
     }
-    
+
     override func viewDidLoad() {
         super.viewDidLoad()
 
@@ -84,11 +81,11 @@ class PhotoVideoListController: BFBaseViewController {
         navHeadImageView?.addSubview(changeCollecBtn)
         addChildViewController(photoMaterialVc)
         view.addSubview(photoMaterialVc.view)
-        
+
         let bottomV = UIView(frame: CGRect(x: 0, y: cScreenHeigth - cDevice_iPhoneTabBarHei, width: cScreenWidth, height: cDevice_iPhoneTabBarHei))
         bottomV.backgroundColor = .black
         view.addSubview(bottomV)
-        
+
         let nextBtn = UIButton(type: .custom)
         nextBtn.frame = CGRect(x: cScreenWidth - 80, y: 10, width: 70, height: 29)
         nextBtn.backgroundColor = UIColor.hexColor(hexadecimal: "#28BE67")
@@ -96,9 +93,8 @@ class PhotoVideoListController: BFBaseViewController {
         nextBtn.layer.cornerRadius = 4
         nextBtn.addTarget(self, action: #selector(rightBtnClick(sender:)), for: .touchUpInside)
         bottomV.addSubview(nextBtn)
-        
     }
-    
+
     /// 按钮点击事件
     /// - Parameter sender: <#sender description#>
     /// - Returns: <#description#>
@@ -115,7 +111,7 @@ class PhotoVideoListController: BFBaseViewController {
             break
         }
     }
-    
+
     /// 图库选择的回调
     /// - Parameter seletedData: <#seletedData description#>
     /// - Returns: <#description#>
@@ -127,18 +123,18 @@ class PhotoVideoListController: BFBaseViewController {
             photoMaterialVc.assetCollection = seletedData?.assetCollection
         }
     }
-    
+
     override func rightBtnClick(sender _: UIButton) {
-        if let asset = self.chosedAsset{
+        if let asset = chosedAsset {
             let vc = IntroduceController()
             vc.asset = asset
             navigationController?.pushViewController(vc, animated: true)
-        }else{
+        } else {
             cShowHUB(superView: nil, msg: "需要选择一个视频")
         }
     }
-    
+
     override open var preferredStatusBarStyle: UIStatusBarStyle {
-            return .lightContent
+        return .lightContent
     }
 }

+ 19 - 20
Example/BFRecordScreenKit/VideoExportController.swift

@@ -6,23 +6,22 @@
 //  Copyright © 2021 CocoaPods. All rights reserved.
 //
 
-import Foundation
+import AVFoundation
 import BFRecordScreenKit
 import BFUIKit
+import Foundation
 import UIKit
-import AVFoundation
 
-class VideoExportController: BFBaseViewController{
-    
-    var videoAsset : AVURLAsset?
-    
-    lazy var progressView : UIView = {
+class VideoExportController: BFBaseViewController {
+    var videoAsset: AVURLAsset?
+
+    lazy var progressView: UIView = {
         let v = UIView(frame: CGRect(x: 0, y: navHeadImageView!.bottomY, width: 0, height: 10))
         v.backgroundColor = .red
         return v
     }()
-    
-    lazy var progressL : UILabel = {
+
+    lazy var progressL: UILabel = {
         let la = UILabel(frame: CGRect(x: 0, y: navHeadImageView!.bottomY, width: cScreenWidth, height: 10))
         la.textColor = .white
         la.textAlignment = .center
@@ -30,19 +29,19 @@ class VideoExportController: BFBaseViewController{
         la.font = UIFont.systemFont(ofSize: 8)
         return la
     }()
-    
-    lazy var export : BFRecordExport = {
+
+    lazy var export: BFRecordExport = {
         let export = BFRecordExport()
-        
-        export.progress = {[weak self] progress in
-            self?.progressView.frame = CGRect(x: 0, y: self?.navHeadImageView?.bottomY ?? 0, width: (cScreenWidth) * CGFloat(progress), height: 10)
-            self?.progressL.text = String(format: "%d%%", Int(progress*100))
+
+        export.progress = { [weak self] progress in
+            self?.progressView.frame = CGRect(x: 0, y: self?.navHeadImageView?.bottomY ?? 0, width: cScreenWidth * CGFloat(progress), height: 10)
+            self?.progressL.text = String(format: "%d%%", Int(progress * 100))
         }
-        export.exportCompletion = {[weak self] (error, url) in
+        export.exportCompletion = { [weak self] _, url in
             guard let strongSelf = self else {
                 return
             }
-            
+
             if let fileUrl = url {
                 DispatchQueue.main.async {
                     let item = AVPlayerItem(url: fileUrl)
@@ -56,12 +55,12 @@ class VideoExportController: BFBaseViewController{
         }
         return export
     }()
-    
+
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
         showNavigation()
     }
-    
+
     override func backBtnClick() {
         export.cancelExport()
         super.backBtnClick()
@@ -72,7 +71,7 @@ class VideoExportController: BFBaseViewController{
         view.backgroundColor = .black
         navHeadImageView?.backgroundColor = .black
         leftButton(image: nil, imageName: nil, tintColor: UIColor.white)
-        
+
         let backV = UIView(frame: CGRect(x: 0, y: navHeadImageView!.bottomY, width: cScreenWidth, height: 10))
         backV.backgroundColor = .gray
         view.addSubview(backV)

+ 8 - 13
Example/BFRecordScreenKit/ViewController.swift

@@ -6,26 +6,24 @@
 //  Copyright (c) 2021 harry. All rights reserved.
 //
 
-import UIKit
+import BFMaterialKit
 import BFMediaKit
 import BFRecordScreenKit
-import BFMaterialKit
-
+import UIKit
 
 class ViewController: UIViewController {
-
-    lazy var addVideoBtn:UIButton = {
+    lazy var addVideoBtn: UIButton = {
         let btn = UIButton(type: .custom)
 //        btn.setTitle("Add", for: .normal)
         btn.setImage(UIImage(named: "add"), for: .normal)
         btn.addTarget(self, action: #selector(addVideo), for: .touchUpInside)
         return btn
     }()
-    
+
     override func viewDidLoad() {
         super.viewDidLoad()
         view.backgroundColor = .black
-        self.navigationController?.isNavigationBarHidden = true
+        navigationController?.isNavigationBarHidden = true
         view.addSubview(addVideoBtn)
         addVideoBtn.snp.makeConstraints { make in
             make.width.height.equalTo(170)
@@ -37,13 +35,10 @@ class ViewController: UIViewController {
         super.didReceiveMemoryWarning()
         // Dispose of any resources that can be recreated.
     }
-    
-    @objc func addVideo(){
+
+    @objc func addVideo() {
         let vc = PhotoVideoListController()
         vc.hidesBottomBarWhenPushed = true
-        self.navigationController?.pushViewController(vc, animated: true)
+        navigationController?.pushViewController(vc, animated: true)
     }
-
 }
-
-

+ 5 - 7
Example/Tests/Tests.swift

@@ -1,28 +1,26 @@
-import XCTest
 import BFRecordScreenKit
+import XCTest
 
 class Tests: XCTestCase {
-    
     override func setUp() {
         super.setUp()
         // Put setup code here. This method is called before the invocation of each test method in the class.
     }
-    
+
     override func tearDown() {
         // Put teardown code here. This method is called after the invocation of each test method in the class.
         super.tearDown()
     }
-    
+
     func testExample() {
         // This is an example of a functional test case.
         XCTAssert(true, "Pass")
     }
-    
+
     func testPerformanceExample() {
         // This is an example of a performance test case.
-        self.measure() {
+        measure {
             // Put the code you want to measure the time of here.
         }
     }
-    
 }

+ 67 - 0
rules.swiftformat

@@ -0,0 +1,67 @@
+--allman false
+--assetliterals visual-width
+--beforemarks 
+--binarygrouping 4,8
+--categorymark "MARK: %c"
+--classthreshold 0
+--closingparen balanced
+--commas always
+--conflictmarkers reject
+--decimalgrouping 3,6
+--elseposition same-line
+--enumthreshold 0
+--exponentcase lowercase
+--exponentgrouping disabled
+--extensionacl on-extension
+--extensionlength 0
+--extensionmark "MARK: - %t + %c"
+--fractiongrouping disabled
+--fragment false
+--funcattributes preserve
+--groupedextension "MARK: %c"
+--guardelse auto
+--header ignore
+--hexgrouping 4,8
+--hexliteralcase uppercase
+--ifdef indent
+--importgrouping alphabetized
+--indent 4
+--indentcase false
+--lifecycle 
+--linebreaks lf
+--markextensions always
+--marktypes always
+--maxwidth none
+--modifierorder 
+--nevertrailing 
+--nospaceoperators 
+--nowrapoperators 
+--octalgrouping 4,8
+--operatorfunc spaced
+--organizetypes class,enum,struct
+--patternlet hoist
+--ranges spaced
+--redundanttype inferred
+--self remove
+--selfrequired 
+--semicolons inline
+--shortoptionals always
+--smarttabs enabled
+--stripunusedargs always
+--structthreshold 0
+--swiftversion 4.0
+--tabwidth unspecified
+--trailingclosures 
+--trimwhitespace always
+--typeattributes preserve
+--typemark "MARK: - %t"
+--varattributes preserve
+--voidtype void
+--wraparguments preserve
+--wrapcollections preserve
+--wrapconditions preserve
+--wrapparameters preserve
+--wrapreturntype preserve
+--xcodeindentation disabled
+--yodaswap always
+--disable initCoderUnavailable,redundantType

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels