BFRecordItemModel.swift 4.8 KB

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