BFRecordItemModel.swift 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. //
  2. // BFRecordItemModel.swift
  3. // BFRecordScreenKit
  4. //
  5. // Created by 胡志强 on 2021/12/6.
  6. //
  7. import Foundation
  8. import Photos
  9. import BFFramework
  10. struct SplitRecordRange {
  11. var isRecord:Bool = false
  12. var range:CMTimeRange
  13. var index:Int
  14. }
  15. public class BFRecordItemModel: NSObject {
  16. // var baseMaterial : AVURLAsset?
  17. var localPath : String?
  18. var materialDuraion: Double = 0.0
  19. var fetchCoverImg : ((UIImage)->Void)?
  20. var fetchAVUrlAsset : ((AVURLAsset)->Void)?
  21. var fetchPlayItem : ((AVPlayerItem)->Void)?
  22. var dealedDurationRanges = [SplitRecordRange]() // 录音切割的时间区间,合成导出时计算
  23. public var voiceStickers = [PQVoiceModel]() //
  24. public var videoStickers = [PQEditVisionTrackMaterialsModel]() // 合成导出时计算
  25. public var imageStickers = [PQEditVisionTrackMaterialsModel]() //
  26. public var titleStickers = [PQEditSubTitleModel]() // 字幕贴纸
  27. public var coverImg : UIImage?
  28. public var index = 0
  29. public var width = 0
  30. public var height = 0
  31. func initOriginData(phasset:PHAsset){
  32. width = phasset.pixelWidth
  33. height = phasset.pixelHeight
  34. fetchCoverImage(phasset)
  35. fetchPlayItem(phasset)
  36. fetchAVUrlAsset(phasset)
  37. }
  38. func fetchCoverImage(_ phasset:PHAsset) {
  39. let option = PHImageRequestOptions()
  40. option.isNetworkAccessAllowed = true //允许下载iCloud的图片
  41. option.resizeMode = .fast
  42. option.deliveryMode = .highQualityFormat
  43. PHImageManager.default().requestImage(for: phasset,
  44. targetSize: CGSize(width: width, height: height),
  45. contentMode: .aspectFit,
  46. options: option)
  47. { [weak self] (image, nil) in
  48. // 设置首帧/封面
  49. if image != nil {
  50. self?.fetchCoverImg?(image!)
  51. self?.coverImg = image
  52. }
  53. }
  54. }
  55. func fetchPlayItem(_ phasset:PHAsset) {
  56. let options = PHVideoRequestOptions()
  57. options.isNetworkAccessAllowed = true
  58. options.deliveryMode = .automatic
  59. if phasset.mediaType == .image {
  60. }else if phasset.mediaType == .video{
  61. PHImageManager.default().requestPlayerItem(forVideo:phasset, options: options, resultHandler: { [weak self] playerItem, info in
  62. guard let item = playerItem else {
  63. cShowHUB(superView: nil, msg: "视频获取失败:\(self?.index ?? 0)")
  64. return
  65. }
  66. self?.fetchPlayItem?(item)
  67. })
  68. }
  69. }
  70. func fetchAVUrlAsset(_ phasset:PHAsset){
  71. let options = PHVideoRequestOptions()
  72. options.isNetworkAccessAllowed = true
  73. options.deliveryMode = .automatic
  74. PHCachingImageManager().requestAVAsset(forVideo: phasset, options: options, resultHandler: {[weak self] (asset: AVAsset?, audioMix: AVAudioMix?, info) in
  75. if let urlAsset = asset as? AVURLAsset {
  76. self?.materialDuraion = urlAsset.duration.seconds
  77. self?.localPath = ((urlAsset.url.absoluteString).removingPercentEncoding)?.replacingOccurrences(of: "file://", with: "")
  78. self?.fetchAVUrlAsset?(urlAsset)
  79. }
  80. })
  81. }
  82. func generationTimeRanges(needSort:Bool = false) {
  83. dealedDurationRanges.removeAll()
  84. var start : Double = 0
  85. var list: [PQVoiceModel]
  86. list = voiceStickers.sorted { model1, model2 in
  87. model1.startTime < model2.startTime
  88. }
  89. for model in list {
  90. if model.startTime > start{
  91. //
  92. let range = CMTimeRange(start: CMTime(seconds: start, preferredTimescale: 100), duration: CMTime(seconds: model.startTime - start, preferredTimescale: 100))
  93. dealedDurationRanges.append(SplitRecordRange(isRecord: false, range: range, index: -1))
  94. }
  95. let ind = voiceStickers.firstIndex(of: model)
  96. let range = CMTimeRange(start: CMTime(seconds: model.startTime, preferredTimescale: 100), end: CMTime(seconds: model.endTime, preferredTimescale: 100))
  97. dealedDurationRanges.append(SplitRecordRange(isRecord: true, range: range, index: ind ?? -1))
  98. start = model.endTime
  99. }
  100. if start < materialDuraion {
  101. let range = CMTimeRange(start: CMTime(seconds: start, preferredTimescale: 100), end: CMTime(seconds: materialDuraion, preferredTimescale: 100))
  102. dealedDurationRanges.append(SplitRecordRange(isRecord: false, range: range, index: -1))
  103. }
  104. }
  105. }