瀏覽代碼

1,三种玩法模式逻辑 2, 不在修改推荐卡点的结束时音

jsonwang 3 年之前
父節點
當前提交
316a25122d
共有 1 個文件被更改,包括 440 次插入130 次删除
  1. 440 130
      BFFramework/Classes/Stuckpoint/Controller/PQStuckPointEditerController.swift

+ 440 - 130
BFFramework/Classes/Stuckpoint/Controller/PQStuckPointEditerController.swift

@@ -10,6 +10,7 @@
 enum createStickersModel {
     case createStickersModelPoint // 卡点
     case createStickersModelSpeed // 快慢速
+    case createStickersModelOnlyMusic //仅配乐
 }
 
 import Foundation
@@ -26,7 +27,7 @@ class PQStuckPointEditerController: PQBaseViewController {
     var isSynchroMusicInfoSuccess: Bool = false
     /// 当前所有的filter
     var filters: Array = Array<ImageProcessingOperation>.init()
-    // 选中的总时长
+    // 选中所有素材的的总时长 其中图片时长为1.5
     var selectedTotalDuration: Float64 = 0
     // 选择的总数
     var selectedDataCount: Int = 0
@@ -48,6 +49,23 @@ class PQStuckPointEditerController: PQBaseViewController {
     var isReCreate: Bool = false
     // 最后一个选择的模式 BTN 用于还原选中状态
     var lastEditModelBtn: UIButton?
+    
+    // add by ak  最大、最小速度 有固定值和自定义,当快慢速下两个值都有效,当跳跃卡点只有maxSpeed有效
+    var maxSpeed: Float = 0.0
+    var minSpeed: Float = 0.0
+    
+    //快慢速最后一次选择的速度位置
+    var lastSpeedSelectIndex:Int = 0
+    //跳跃卡点最后一次选择的速度位置
+    var lastJumpSpeedSelectIndex:Int = 0
+    
+    //当前选择的玩法模式
+    var currentCreateStickersModel:createStickersModel = .createStickersModelSpeed
+    
+    //最终使用的卡点数据
+    var finallyStuckPoints: Array = Array<Float>.init()
+    //最终使用的音频时长
+    var finallyUserAudioTime:Float = 0.0
     // 下一步
     lazy var nextBtn: UIButton = {
         let nextBtn = UIButton(type: .custom)
@@ -235,10 +253,9 @@ class PQStuckPointEditerController: PQBaseViewController {
     lazy var speedStuckBtn: UIButton = {
         let speedStuckBtn = UIButton(type: .custom)
         speedStuckBtn.addTarget(self, action: #selector(editModelClick(sender:)), for: .touchUpInside)
-        speedStuckBtn.isSelected = true
         speedStuckBtn.setBackgroundImage(UIImage().BF_Image(named: "speedstuck_n"), for: .normal)
         speedStuckBtn.setBackgroundImage(UIImage().BF_Image(named: "speedstuck_h"), for: .selected)
-        lastEditModelBtn = speedStuckBtn
+
         speedStuckBtn.tag = 1
         speedStuckBtn.adjustsImageWhenHighlighted = false
         return speedStuckBtn
@@ -298,8 +315,16 @@ class PQStuckPointEditerController: PQBaseViewController {
         let speedSettingView = PQSpeedSettingView()
         speedSettingView.backgroundColor = .clear
         speedSettingView.viewType = 1
-        speedSettingView.selectSpeedCallBack = { [weak self] maxSpeed, minSpeed in
-            BFLog(message: "maxSpeed is\(maxSpeed) minSpeed \(minSpeed)")
+        speedSettingView.selectSpeedCallBack = { [weak self] maxSpeed, minSpeed,selectIndex in
+            BFLog(message: "固定maxSpeed is\(maxSpeed) minSpeed \(minSpeed)")
+            //更新最后一次选择的位置恢复时使用
+            if(speedSettingView.viewType == 2){
+                self?.lastJumpSpeedSelectIndex = selectIndex
+            }else{
+                self?.lastSpeedSelectIndex = selectIndex
+            }
+            self?.maxSpeed = maxSpeed
+            self?.minSpeed = minSpeed
             if maxSpeed == 0 && minSpeed == 0 {
                 self?.customSpeedSettingView.isHidden = false
                 self?.customSpeedSettingView.isJumpSpeedModel = speedSettingView.viewType == 2
@@ -314,6 +339,12 @@ class PQStuckPointEditerController: PQBaseViewController {
         let customSpeedSettingView = PQCustomSpeedSettingView(frame: CGRect(x: 0, y: cScreenHeigth - 354, width: cScreenWidth, height: 354))
         customSpeedSettingView.isHidden = true
         customSpeedSettingView.isJumpSpeedModel = false
+        customSpeedSettingView.selectSpeedCallBack = { [weak self] maxSpeed, minSpeed ,isJumpSpeedModel in
+            self?.maxSpeed = maxSpeed
+            self?.minSpeed = minSpeed
+            BFLog(message: "自定义速度maxSpeed is\(maxSpeed) minSpeed \(minSpeed) \(isJumpSpeedModel)")
+        
+        }
         return customSpeedSettingView
 
     }()
@@ -470,18 +501,24 @@ class PQStuckPointEditerController: PQBaseViewController {
         if sender.tag == 1 { // 快慢速
             speedStuckBtnGifName = "speedstuck_h"
             jumpPointBtnGifName = "jumpPoint_n"
+            currentCreateStickersModel = .createStickersModelSpeed
+            speedSettingView.setSelectItem(index: lastSpeedSelectIndex)
          
             
         } else if sender.tag == 2 { // 跳跃卡点
             speedStuckBtnGifName = "speedstuck_n"
             jumpPointBtnGifName = "jumpPoint_h"
- 
+            speedSettingView.setSelectItem(index: lastJumpSpeedSelectIndex)
+            currentCreateStickersModel = .createStickersModelPoint
+
         } else if sender.tag == 3 { // 仅音乐
             speedStuckBtnGifName = "speedstuck_n"
             jumpPointBtnGifName = "jumpPoint_n"
-       
+            currentCreateStickersModel = .createStickersModelOnlyMusic
+
         }
         
+        settingPlayerView()
         speedStuckBtnGif.kf.setImage(with: URL(fileURLWithPath:  Bundle.init().BF_mainbundle().path(forResource:speedStuckBtnGifName , ofType: ".gif")!))
         jumpPointBtnGif.kf.setImage(with: URL(fileURLWithPath:  Bundle.init().BF_mainbundle().path(forResource: jumpPointBtnGifName  , ofType: ".gif")!))
     }
@@ -739,7 +776,7 @@ class PQStuckPointEditerController: PQBaseViewController {
             videoSize = CGSize(width: minSlider, height: maxSlider)
         }
 
-        let maxValue = max(videoSize.width, videoSize.height ?? 0)
+        let maxValue = max(videoSize.width, videoSize.height )
         if maxValue > 1920 {
             let maxRation = 1920 / maxValue
 
@@ -760,7 +797,7 @@ class PQStuckPointEditerController: PQBaseViewController {
 
         // 2,创建滤镜
         let beginTime: TimeInterval = Date().timeIntervalSince1970
-        mStickers = createStickers(sections: projectModel.sData?.sections ?? List(), inputSize: CGSize(width: CGFloat(projectModel.sData?.videoMetaData?.videoWidth ?? 0), height: CGFloat(projectModel.sData?.videoMetaData?.videoHeight ?? 0)), model: .createStickersModelPoint)
+        mStickers = createStickers(sections: projectModel.sData?.sections ?? List(), inputSize: CGSize(width: CGFloat(projectModel.sData?.videoMetaData?.videoWidth ?? 0), height: CGFloat(projectModel.sData?.videoMetaData?.videoHeight ?? 0)), model: currentCreateStickersModel)
         playerView.mStickers = mStickers
 
         let end: TimeInterval = Date().timeIntervalSince1970
@@ -768,12 +805,20 @@ class PQStuckPointEditerController: PQBaseViewController {
 
         // 3,设置音频
         let audioPath = stuckPointMusicData?.localPath ?? ""
+    
         BFLog(message: "初始化音频播放器的音频地址为:\(audioPath)")
         playerView.stop()
         // 这里的测试这个音乐播放有问题
 //        self.playerView.updateAsset(URL(fileURLWithPath: "63930549652d74e477141e3b79c8d29a9ef8af81625053214516.mp3", relativeTo:Bundle.main.resourceURL!), videoComposition: nil, audioMixModel: nil)
-        playerView.updateAsset(URL(fileURLWithPath: documensDirectory + audioPath), videoComposition: nil, audioMixModel: nil)
-
+        
+        
+        //设置音乐的拼接范围,开始:推荐的卡点  结束:点到的倒数第二位
+        let lastSecondPoint =   Float((stuckPointMusicData!.rhythmSdata[0].pointTimes[stuckPointMusicData!.rhythmSdata[0].pointTimes.count - 2] )) / Float(BASE_FILTER_TIMESCALE)
+        let clipAudioRange =
+        CMTimeRange(start: CMTime(value: CMTimeValue( Float(stuckPointMusicData?.startTime ?? 0) * Float(BASE_FILTER_TIMESCALE)), timescale: BASE_FILTER_TIMESCALE), end: CMTime(value: CMTimeValue((Float(lastSecondPoint)) * Float(BASE_FILTER_TIMESCALE)), timescale: BASE_FILTER_TIMESCALE))
+ 
+        playerView.updateAsset(URL(fileURLWithPath: documensDirectory + audioPath), videoComposition: nil, audioMixModel: nil,originMusicDuration:finallyUserAudioTime,clipAudioRange: clipAudioRange)
+ 
         let end2: TimeInterval = Date().timeIntervalSince1970
         BFLog(message: "updateAsset tiskskskskme  \(end2 - end)")
         // 4, 设置播放器的输出画布大小
@@ -891,9 +936,14 @@ extension PQStuckPointEditerController {
     ///   - inputSize: 画布大小
     /// - Returns: filters 数据 播放器可直接使用
     func createStickers(sections: List<PQEditSectionModel>, inputSize _: CGSize = .zero, model: createStickersModel = .createStickersModelPoint) -> [PQEditVisionTrackMaterialsModel] {
+        
+        // 推荐卡点数
+        dealParameter(model: model)
+        let stuckPoints: Array = finallyStuckPoints
+        
         // 保存滤镜对象数据
         var stickers: Array = Array<PQEditVisionTrackMaterialsModel>.init()
-        if model == .createStickersModelPoint {
+        if model == .createStickersModelPoint { //跳跃卡点
             for section in sections {
                 if section.sectionType == "normal" {
                     // 推荐卡点数
@@ -907,13 +957,12 @@ extension PQStuckPointEditerController {
                         }
                     }
 
-                    /* 快慢速模式下取卡点
+                    /* 快慢速模式下取卡点 1 3 5
                      - 快节奏为选中区域的所有点位,即0,1,2,3,4 5 6 7 8 9 10 ……
                      - 适中为每两个点位取一个,即0,3,6,9 12
                      - 慢节奏为每三个点位取一个,即0 5 10 15
                      慢节奏要做特殊处理
-                     5d or L/1.23
-                     (*当输入素材为L ∈(0-10.5]s 时,判断与5d之间的关系,若L/1.2≥5d,则取5d;若L/1.2<5d,则取L/1.2)
+                 
                      */
                     // 跳跃卡点模式下根据不同速度 取卡点 1,2,3
                     /*
@@ -1001,7 +1050,7 @@ extension PQStuckPointEditerController {
                                     BFLog(message: "bbbbbindexindeindexxindexindexindex \(index) \(point)")
                                     let sticker: PQEditVisionTrackMaterialsModel = clipFilters[index]
                                     sticker.timelineIn = Float64("\(stuckPoints[index])") ?? 0.0
-                                    // TODO: 不是最好方案
+                                 
                                     sticker.timelineOut = Float64("\(stuckPoints[index + 1])") ?? 0.0
                                     // 卡点的时间 >  in out 值 这里就会出现鬼畜效果
                                     let timelineInterval = sticker.timelineOut - sticker.timelineIn
@@ -1034,136 +1083,312 @@ extension PQStuckPointEditerController {
                     }
                 }
             }
-        } else {
+        } else if model == .createStickersModelSpeed{//快慢速
             for section in sections {
                 if section.sectionType == "normal" {
-                    // 推荐卡点数
-                    var stuckPoints: Array = Array<Float>.init()
-
-                    var stuckPointsTemp = Array<Float>.init()
-                    for (index, dunshu) in stuckPointMusicData!.rhythmSdata[0].pointTimes.enumerated() {
-                        BFLog(message: "原所有卡点数:\(index) \(Float(dunshu) / Float(BASE_FILTER_TIMESCALE))")
-                        if Float64(dunshu) / Float64(BASE_FILTER_TIMESCALE) > CMTimeGetSeconds(playeTimeRange.start), Float64(dunshu) / Float64(BASE_FILTER_TIMESCALE) < CMTimeGetSeconds(playeTimeRange.end) {
-                            stuckPointsTemp.append(Float(dunshu) / Float(BASE_FILTER_TIMESCALE))
-                        }
-                    }
-
-                    // 根据不同速度 取卡点 1,2,3
-                    /*
-                     - 快节奏为选中区域的所有点位,即0,1,2,3,4……
-                     - 适中为每两个点位取一个,即0,2,4,6……
-                     - 慢节奏为每三个点位取一个,即0,3,6,9……
-                     */
-                    BFLog(message: "stuckPointMusicData?.speed is \(String(describing: stuckPointMusicData?.speed))")
-                    for (index, point) in stuckPointsTemp.enumerated() {
-                        if stuckPointMusicData?.speed == 1 {
-                            stuckPoints.append(Float(point))
-                        } else if stuckPointMusicData?.speed == 2 {
-                            if index % 2 == 0 {
-                                stuckPoints.append(point)
+              
+                    BFLog(message: "stuckPoints count is \(stuckPoints.count)")
+                  
+                    //一共裁剪的段数
+                    var totalClipNum:Int = 0
+                    for sticker in section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials() {
+                        if sticker.type == StickerType.VIDEO.rawValue {
+                            let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: documensDirectory + sticker.locationPath), options: nil)
+                        
+                            var i:Int = 0
+                            //一个视频切的的段落
+                            var oneVideoClipNum:Int = 0
+                         
+                            var realUsedMusicDuration = 0.0
+                            while realUsedMusicDuration <= CMTimeGetSeconds(asset.duration) {
+                                //快速段
+                                let LA = maxSpeed * (stuckPoints[i+1] - stuckPoints[i])
+                                realUsedMusicDuration = realUsedMusicDuration + Float64(LA)
+                                if(realUsedMusicDuration > CMTimeGetSeconds(asset.duration)){ break}
+                                oneVideoClipNum = oneVideoClipNum + 1
+                                //慢速段
+                                let LB = minSpeed * (stuckPoints[i+2] - stuckPoints[i+1])
+                                realUsedMusicDuration = realUsedMusicDuration + Float64(LB)
+                                oneVideoClipNum = oneVideoClipNum + 1
+                                i = i + 1
                             }
+                            BFLog(message: "单个视频\(sticker.locationPath)时长::\(CMTimeGetSeconds(asset.duration)) ,clipNum is:\(oneVideoClipNum)")
+                        
+                            for clipindex in 0 ... oneVideoClipNum - 1 {
+                                // deep copy sticker model 防止只有一个对象
+                                let stickerjson = sticker.toJSONString(prettyPrint: false)
+                                let deepCopySticker = Mapper<PQEditVisionTrackMaterialsModel>().map(JSONString: stickerjson!)
+                                // 设置循环模式和适配模式
+                                deepCopySticker?.generateDefaultValues()
+                                //当前分段的速度
+                                let tempSpeed = (totalClipNum + clipindex) % 2 == 0 ? maxSpeed : minSpeed
+                                if(totalClipNum + 1 + clipindex < stuckPoints.count){
+                                    deepCopySticker?.speedRate = tempSpeed
+                                    deepCopySticker?.model_in = Float64(tempSpeed) * Float64(stuckPoints[totalClipNum + clipindex] - (stuckPoints.first ?? 0.0))
+                                    deepCopySticker?.out = Float64(tempSpeed) * Float64(stuckPoints[totalClipNum + 1 + clipindex] - (stuckPoints.first ?? 0.0))
+                                    deepCopySticker?.timelineIn = Float64(stuckPoints[totalClipNum + clipindex])
+                                    deepCopySticker?.timelineOut = Float64(stuckPoints[totalClipNum + 1 + clipindex])
+                                }
+                            
+                                BFLog(message: " crilp is in \(deepCopySticker?.model_in ?? 0) out \(deepCopySticker?.out ?? 0) timelineIN:\(deepCopySticker?.timelineIn ?? 0) timelineOUT:\(deepCopySticker?.timelineOut ?? 0) 总时长\(CMTimeGetSeconds(asset.duration)) speedRate:\(String(describing: deepCopySticker?.speedRate))")
 
-                        } else if stuckPointMusicData?.speed == 3 {
-                            if index % 3 == 0 {
-                                stuckPoints.append(point)
+                                if deepCopySticker != nil {
+                                    stickers.append(deepCopySticker!)
+                                }
+                              
                             }
+                            totalClipNum = totalClipNum + oneVideoClipNum - 1
+                        } else if sticker.type == StickerType.IMAGE.rawValue {
+                            sticker.generateDefaultValues()
+                            sticker.timelineIn = Float64(stuckPoints[totalClipNum])
+                            sticker.timelineOut = Float64(stuckPoints[totalClipNum + 1])
+                            stickers.append(sticker)
                         }
                     }
-
-                    for point in stuckPoints {
-                        BFLog(message: "没有 start end 计算后的卡点数\(point)")
-                    }
-                    if stuckPoints.first != nil {
-                        stuckPoints.removeFirst()
-                    }
-                    if stuckPoints.last != nil {
-                        stuckPoints.removeLast()
-                    }
-                    // 开始时间是服务器返回, 结果时间根据策略计算的
-                    stuckPoints.insert(Float(CMTimeGetSeconds(playeTimeRange.start)), at: 0)
-                    stuckPoints.insert((Float(CMTimeGetSeconds(playeTimeRange.end))), at: stuckPoints.count)
-
-                    for point in stuckPoints {
-                        BFLog(message: "有 start end 计算后的卡点数\(point)")
-                    }
+                }
+            
+            
+            }
+        } else if model == .createStickersModelOnlyMusic{ //仅音乐 首尾相连播放
+            for section in sections {
+                if section.sectionType == "normal" {
 
                     BFLog(message: "stuckPoints count is \(stuckPoints.count)")
-                    // 当用户上传视觉素材个数大于等于音乐选择区域节拍分割个数时,无需进行视频分割,只显示卡点数-1 个素材
-                    if section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials().count >= stuckPointMusicData!.rhythmSdata[0].pointTimes.count {
-                        for (index, sticker) in section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials().enumerated() {
-                            if index == stuckPointMusicData!.rhythmSdata[0].pointTimes.count {
-                                BFLog(message: "到达卡点数量")
-                                break
-                            }
-                            BFLog(message: "创建 filter start :\(sticker.timelineIn) end :\(sticker.timelineOut) type is \(sticker.type) \(sticker.locationPath)")
-                            sticker.timelineIn = Float64("\(stuckPoints[index])") ?? 0.0
-                            sticker.timelineOut = Float64("\(stuckPoints[index + 1])") ?? 0.0
-                            BFLog(message: "卡点 间隔 \(sticker.timelineIn - sticker.timelineOut)")
+                    //已经计算过所有贴纸的累计时长
+                    var totalStickerTimer:Float64 = 0
+                    for sticker in section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials() {
+                        if sticker.type == StickerType.VIDEO.rawValue {
+                            let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: documensDirectory + sticker.locationPath), options: nil)
+     
+                            BFLog(message: "单个视频\(sticker.locationPath)时长::\(CMTimeGetSeconds(asset.duration))")
                             sticker.generateDefaultValues()
-                            stickers.append(sticker)
-                        }
-
-                    } else {
-                        // 卡点数 > 选择素材数
-
-                        // 第一种情况:全是图片,图片回环播放
-                        if section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials(type: "video").count == 0, section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials(type: "image").count > 0 {
-                            for (index, point) in stuckPoints.enumerated() {
-                                let sticker: PQEditVisionTrackMaterialsModel = section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials()[index % section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials().count]
-                                BFLog(message: "stickerlocationPath sticker : \(sticker.locationPath)")
-                                let stickerjson = sticker.toJSONString(prettyPrint: false)
+                            sticker.model_in = 0
+                            sticker.out = CMTimeGetSeconds(asset.duration)
+
+                            sticker.timelineIn = totalStickerTimer
+                            sticker.timelineOut = sticker.timelineIn + sticker.out
+                            
+                            totalStickerTimer = totalStickerTimer +  sticker.out
+                     
+                   
+                        } else if sticker.type == StickerType.IMAGE.rawValue {
+                            sticker.generateDefaultValues()
+                            sticker.timelineIn = totalStickerTimer
+                            sticker.timelineOut =  sticker.timelineIn + sticker.out
+                            
+                            totalStickerTimer = totalStickerTimer +  sticker.out
 
-                                let deepCopySticker = Mapper<PQEditVisionTrackMaterialsModel>().map(JSONString: stickerjson!)
-                                if deepCopySticker!.type == StickerType.IMAGE.rawValue {
-                                    if index + 1 < stuckPoints.count {
-                                        deepCopySticker!.timelineIn = Float64("\(stuckPoints[index])") ?? 0.0
-                                        deepCopySticker!.timelineOut = Float64("\(stuckPoints[index + 1])") ?? 0.0
-                                        if deepCopySticker != nil {
-                                            deepCopySticker?.generateDefaultValues()
-                                            stickers.append(deepCopySticker!)
-                                        }
-                                    }
-                                }
-                            }
-                        } else {
-                            // 第二种情况:有视频要进行分割
-                            let clipFilters = clipVideoMerage(section: section, stuckPoints: stuckPoints)
-                            for (index, point) in stuckPoints.enumerated() {
-                                BFLog(message: "aaaaaindexindeindexxindexindexindex \(index) \(point)")
-                                if index + 1 < stuckPoints.count, index < clipFilters.count {
-                                    BFLog(message: "bbbbbindexindeindexxindexindexindex \(index) \(point)")
-                                    let sticker: PQEditVisionTrackMaterialsModel = clipFilters[index]
-                                    let spit: Int = 2
-                                    sticker.timelineIn = 57.5 + Double(index * spit)
-                                    sticker.timelineOut = sticker.timelineIn + Double(spit)
-                                    sticker.speedRate = index % 2 == 0 ? 0.1 : 2
-
-                                    sticker.model_in = Double(index * spit)
-                                    sticker.out = sticker.model_in + Double(spit)
-
-//                                    let spit: Int = 2
-//                                    sticker.timelineIn = 57.5
-//                                    sticker.timelineOut = sticker.timelineIn + 24
-//                                    sticker.speedRate = index % 2 == 0 ? 0.1 : 2
-                                    ////                                    sticker.speedRate = 0.1
-//                                    sticker.model_in = 0
-//                                    sticker.out = sticker.model_in + 24
-
-                                    if stickers.count < 12 {
-                                        BFLog(message: "index is \(index)分割后 创建 filter timelineIn :\(sticker.timelineIn) timelineOut :\(sticker.timelineOut)  in :\(sticker.model_in) out:\(sticker.out) type is \(sticker.type) 显示总时长为:\(sticker.timelineOut - sticker.timelineIn)  裁剪总时长\(sticker.out - sticker.model_in)")
-
-                                        stickers.append(sticker)
-                                    }
-                                }
-                            }
                         }
+                        
+                        stickers.append(sticker)
                     }
                 }
+            
+            
             }
         }
 
         return stickers
     }
+    
+    
+    /// 根据档位取最后使用的卡点数据
+    /// - Parameter seed: 档位速度
+    /// - Returns: 最后使用的卡点
+    func getUsedStuckPoint(seed:Int) -> Array<Float> {
+        // 推荐卡点数
+        var stuckPoints: Array = Array<Float>.init()
+
+        var stuckPointsTemp = Array<Float>.init()
+        for (index, dunshu) in stuckPointMusicData!.rhythmSdata[0].pointTimes.enumerated() {
+            BFLog(message: "原所有卡点数:\(index) \(Float(dunshu) / Float(BASE_FILTER_TIMESCALE))")
+            if Float64(dunshu) / Float64(BASE_FILTER_TIMESCALE) > (stuckPointMusicData?.startTime ?? 0) {
+                stuckPointsTemp.append(Float(dunshu) / Float(BASE_FILTER_TIMESCALE))
+            }
+        }
+
+        /*
+         一,快慢速模式下取卡点 1 3 5
+           快节奏为选中区域的所有点位,即0,1,2,3,4 5 6 7 8 9 10 ……
+           适中为每两个点位取一个,即0,3,6,9 12
+           慢节奏为每三个点位取一个,即0 5 10 15
+         
+         二,跳跃卡点模式下根据不同速度 取卡点 1,2,3
+           快节奏为选中区域的所有点位,即0,1,2,3,4 5 6 7 8 9 10 ……
+           适中为每两个点位取一个,即0,2,4,6……
+           慢节奏为每三个点位取一个,即0,3,6,9……
+         */
+        BFLog(message: "stuckPointMusicData?.speed is \(String(describing: stuckPointMusicData?.speed))")
+    
+        //不丢
+        if(seed == 1){
+            stuckPoints = stuckPointsTemp
+        }else{
+            //根据档位要丢
+            for (index, point) in stuckPointsTemp.enumerated() {
+                if index % seed == 0 {
+                    stuckPoints.append(point)
+                }
+            }
+        }
+  
+        for point in stuckPoints {
+            BFLog(message: "没有 start end 计算后的卡点数\(point)")
+        }
+        if stuckPoints.first != nil {
+            stuckPoints.removeFirst()
+        }
+        if stuckPoints.last != nil {
+            stuckPoints.removeLast()
+        }
+        // 开始时间是服务器返回, 结果时间根据策略计算的
+        stuckPoints.insert(Float(stuckPointMusicData?.startTime ?? 0), at: 0)
+        stuckPoints.insert(Float(stuckPointMusicData?.endTime ?? 0), at: stuckPoints.count)
+
+        for point in stuckPoints {
+            BFLog(message: "有 start end 计算后的卡点数\(point)")
+        }
+
+        BFLog(message: "stuckPoints count is \(stuckPoints.count)")
+        
+        return stuckPoints
+        
+        
+         
+    }
+    
+    /// 根据不同模式model,    maxSpeed ,minSpeed,      self?.stuckPointMusicData?.speed 档位,生成音乐时长和最终使用的卡点信息
+    func dealParameter(model:createStickersModel){
+ 
+        //清空上一次使用的卡点数据
+        finallyStuckPoints.removeAll()
+        //注意推荐时间位置和后面最近的卡点时间与0.3的关系
+        //保存丢卡点处理后的卡点信息推荐开始到最后倒数第二个
+        let stuckPointsTemp = getUsedStuckPoint(seed: stuckPointMusicData?.speed ?? 0)
+        
+        //最后真正要使用推荐结束时长
+        var realUsedMusicDuration:Float = 0.0
+        switch model {
+        case .createStickersModelPoint://跳跃卡点
+            // L/(n+1)  L -原视觉素材总时长  n-抛留倍数
+            realUsedMusicDuration = Float(selectedTotalDuration) / (Float(maxSpeed) + 1)
+            
+            //要拼接的段数
+            var clipNum:Int = 0
+            //所有段的时长总和
+            var tempTime:Float = 0.0
+            var i:Int = 0
+            while tempTime < Float(selectedTotalDuration) {
+            
+                //回环从头取
+                if(i+2 > stuckPointsTemp.count){
+                    i = 0
+                }
+                //快速段
+                let LA =  (stuckPointsTemp[i+1] - stuckPointsTemp[i])
+                tempTime = tempTime + Float(LA)
+                if(tempTime > Float(selectedTotalDuration)){ break}
+                //慢速段
+                let LB = (stuckPointsTemp[i+2] - stuckPointsTemp[i+1])
+                tempTime = tempTime + Float(LB)
+                i = i + 1
+                clipNum = clipNum + 1
+            }
+            
+            //拼接要使用的卡点信息
+            for i in 0...clipNum {
+                finallyStuckPoints.append(stuckPointsTemp[i % stuckPointsTemp.count] + Float(i / stuckPointsTemp.count) * (stuckPointsTemp.first ?? 0))
+            }
+  
+            break
+        case .createStickersModelSpeed://快慢速
+
+            /*
+             - A-视频中的快速片段
+             - B-视频中的慢速片段
+             - d-在一档下音乐每个点位时长
+             - n-不同音乐档位对应的d倍数,快节奏时,n=1;适中时,n=3;慢节奏时,n=5
+             - L-原视觉素材时长
+             - x-视频在A片段的播放倍速
+             - y-视频在B片段的播放倍速
+             */
+            //LA=x*n*d,LB=y*n*d (n=1/3/5) 注:视频经过快慢速处理后的总时长约=L*2/(x+y)
+            BFLog(message: "Ax快速为:\(maxSpeed) By慢速为:\(minSpeed) 档位 N为:\(stuckPointMusicData?.speed ?? 0)  使用的卡点总数:\(stuckPointsTemp.count)")
+            
+            //1,计算 AB 段的个数
+            var i:Int = 0
+            var LACount:Int = 0
+            var LBCount:Int = 0
+            while realUsedMusicDuration <= Float(selectedTotalDuration) {
+            
+                //回环从头取
+                if(i+2 > stuckPointsTemp.count){
+                    i = 0
+                }
+                //快速段
+                let LA = maxSpeed * (stuckPointsTemp[i+1] - stuckPointsTemp[i])
+                realUsedMusicDuration = realUsedMusicDuration + Float(LA)
+                if(realUsedMusicDuration > Float(selectedTotalDuration)){ break}
+                LACount = LACount + 1
+                BFLog(message: "快速段段段段段段后LACount:\(LACount) realUsedMusicDuration:\(realUsedMusicDuration)")
+                //慢速段
+                let LB = minSpeed * (stuckPointsTemp[i+2] - stuckPointsTemp[i+1])
+                realUsedMusicDuration = realUsedMusicDuration + Float(LB)
+                LBCount = LBCount + 1
+                BFLog(message: "慢速段段段段段段后LACount:\(LACount) realUsedMusicDuration:\(realUsedMusicDuration)")
+                
+                i = i + 1
+            }
+            
+            //2,拼接要使用的卡点信息
+            for (index,point) in stuckPointsTemp.enumerated() {
+                 
+                if(index < LACount + LBCount){
+                    finallyStuckPoints.append(point)
+                }
+            }
+            //2.1不足所有卡点回环拼接
+            if( LACount + LBCount > stuckPointsTemp.count ){
+        
+                for (index,point) in stuckPointsTemp.enumerated() {
+                    if(index <=  LACount + LBCount - stuckPointsTemp.count){
+                        finallyStuckPoints.append(Float((stuckPointsTemp.last ?? 0) + point))
+                    }
+                }
+            }
+ 
+            BFLog(message: "计算后的\(realUsedMusicDuration) LACount:\(LACount) LBCount \(LBCount) 估算时长为:\(selectedTotalDuration * 2 / Float64(maxSpeed + minSpeed))")
+       
+            break
+        case .createStickersModelOnlyMusic://仅音乐
+            //时长为所有素材总时长
+            finallyStuckPoints.append(Float(stuckPointMusicData?.startTime ?? 0) + Float(selectedTotalDuration))
+         
+            break
+     
+        }
+        
+        //计算最后使用的音频时长, 如果不用拼接音频时长度是卡点的倒数第二位时间
+        let asset = AVURLAsset(url: URL(fileURLWithPath: documensDirectory + (stuckPointMusicData?.localPath ?? "")), options: nil)
+ 
+        //原推荐卡点的倒数第二位时间
+        let lastSecondPoint =   Float((stuckPointMusicData!.rhythmSdata[0].pointTimes[stuckPointMusicData!.rhythmSdata[0].pointTimes.count - 2] )) / Float(BASE_FILTER_TIMESCALE)
+        
+        finallyUserAudioTime = Float(lastSecondPoint)
+        if(finallyStuckPoints.last ?? 0 > Float(CMTimeGetSeconds(asset.duration))){
+           
+            finallyUserAudioTime = Float(finallyStuckPoints.last ?? 0) + (Float(CMTimeGetSeconds(asset.duration)) - Float(lastSecondPoint))
+            
+        }
+        
+        playeTimeRange = CMTimeRange(start: CMTime(value: CMTimeValue( Float(stuckPointMusicData?.startTime ?? 0) * Float(BASE_FILTER_TIMESCALE)), timescale: BASE_FILTER_TIMESCALE), end: CMTime(value: CMTimeValue((Float(finallyStuckPoints.last ?? 0)) * Float(BASE_FILTER_TIMESCALE)), timescale: BASE_FILTER_TIMESCALE))
+  
+        // 更新裁剪时间条的的ui数据
+        stuckPointCuttingView.videoDuration = CGFloat(finallyUserAudioTime)
+        stuckPointCuttingView.updateEndTime(startTime:CGFloat(CMTimeGetSeconds( playeTimeRange.start)), endTime: CGFloat(  CMTimeGetSeconds( playeTimeRange.end)))
+        
+   
+    }
 }
 
 // MARK: - 同步/下载素材相关
@@ -1187,7 +1412,7 @@ extension PQStuckPointEditerController {
                         self?.stuckPointMusicData?.speed = newMusicData?.speed ?? 2
                     }
                     if (self?.stuckPointMusicData?.rhythmSdata.count ?? 0) > 0 && (((self?.selectedDataCount ?? 0) - (self?.selectedImageDataCount ?? 0)) > 0 || (self?.selectedImageDataCount ?? 0) > 0 || (self?.selectedTotalDuration ?? 0) > 0) {
-                        self?.stuckPointMusicData?.endTime = (self?.stuckPointMusicData?.startTime ?? 0) + (self?.stuckPointMusicData?.stuckPointCuttingTime(videoCount: (self?.selectedDataCount ?? 0) - (self?.selectedImageDataCount ?? 0), imageCount: self?.selectedImageDataCount ?? 0, totalDuration: self?.selectedTotalDuration ?? 0) ?? 0)
+//                        self?.stuckPointMusicData?.endTime = (self?.stuckPointMusicData?.startTime ?? 0) + (self?.stuckPointMusicData?.stuckPointCuttingTime(videoCount: (self?.selectedDataCount ?? 0) - (self?.selectedImageDataCount ?? 0), imageCount: self?.selectedImageDataCount ?? 0, totalDuration: self?.selectedTotalDuration ?? 0) ?? 0)
                     }
                     self?.stuckPointCuttingView.updateEndTime(startTime: CGFloat(self?.stuckPointMusicData?.startTime ?? 0), endTime: CGFloat(self?.stuckPointMusicData?.endTime ?? 0))
                     if self?.stuckPointMusicData?.localPath == nil || (self?.stuckPointMusicData?.localPath?.count ?? 0) > 0 {
@@ -1337,8 +1562,93 @@ extension PQStuckPointEditerController {
             return
         }
 
-        playeTimeRange = CMTimeRange(start: CMTimeMakeWithSeconds(stuckPointMusicData?.startTime ?? 0, preferredTimescale: BASE_FILTER_TIMESCALE), end: CMTimeMakeWithSeconds(stuckPointMusicData?.endTime ?? 0, preferredTimescale: BASE_FILTER_TIMESCALE))
         createPorjectData()
-        settingPlayerView()
+      
+        BFLog(message: "界面编辑界面时参数 选择素材时长:\(selectedTotalDuration) 选择素材总数:\(selectedDataCount) 选择图片总数\(selectedImageDataCount)")
+        
+        
+        //1 生成默认参数值
+        /*
+         - 当素材总时长∈[0-6)s 时,提示推荐仅配乐模式 or 快慢速模式
+         - 当素材总时长∈[6-80)s 时,卡点抛留倍数为1x,即留1抛1
+         - 当素材总时长∈[80,120)s 时,卡点抛留倍数为2x,即留1抛2
+         - 当素材总时长∈[120,160)s 时,卡点抛留倍数为3x,即留1抛3
+         - 当素材总时长∈[160,200)s 时,卡点抛留倍数为4x,即留1抛4
+         - 当素材总时长∈[200,240)s 时,卡点抛留倍数为5x,即留1抛5
+         - 当素材总时长∈[240,∞)s 时,卡点抛留倍数为5x,即留1抛5
+         */
+        //1.1) 生成跳跃卡点的默认值
+        if(selectedTotalDuration >= 6 && selectedTotalDuration < 80){
+            lastJumpSpeedSelectIndex = 0
+        }else if(selectedTotalDuration >= 80 && selectedTotalDuration < 120){
+            lastJumpSpeedSelectIndex = 1
+        }else if(selectedTotalDuration >= 120 && selectedTotalDuration < 160){
+            lastJumpSpeedSelectIndex = 2
+        }else if(selectedTotalDuration >= 160 && selectedTotalDuration < 200){
+            lastJumpSpeedSelectIndex = 3
+        }else if(selectedTotalDuration >= 200 && selectedTotalDuration < 240){
+            lastJumpSpeedSelectIndex = 4
+        }else if(selectedTotalDuration >= 240){
+            lastJumpSpeedSelectIndex = 5
+        }
+        
+        /*默认进入快慢速模式
+         - 当素材总时长∈[120,144]s 时,快慢速处理方式:快速为 6x,慢速为 1.2x,效果是快&快
+         - 当素材总时长∈[70,120)s 时,快慢速处理方式:快速为5x,慢速为 1x,效果是快&正常
+         - 当素材总时长∈[56,70)s 时,快慢速处理方式:快速为3x,慢速为 0.5x,效果是快&慢
+         - 当素材总时长∈[17.5,56)s 时,快慢速处理方式:快速为 2.4x,慢速为 0.4x,效果是快&慢
+         - 当素材总时长∈[10.5,17.5)s 时,快慢速处理方式:快速为 1.8x,慢速为 0.3x,效果是快&慢
+         - 当素材总时长∈(0,10.5)s 时,快慢速处理方式:快速为 1x,慢速为 0.2x,效果是正常&慢
+         
+         */
+        //1.2)生成快慢速的默认值
+        if(selectedTotalDuration >= 120 && selectedTotalDuration <= 144){
+            lastSpeedSelectIndex = 0
+        }else if(selectedTotalDuration >= 70 && selectedTotalDuration < 120){
+            lastSpeedSelectIndex = 1
+        }else if(selectedTotalDuration >= 56 && selectedTotalDuration < 70){
+            lastSpeedSelectIndex = 2
+        }else if(selectedTotalDuration >= 17.5 && selectedTotalDuration < 56){
+            lastSpeedSelectIndex = 3
+        }else if(selectedTotalDuration >= 10.5 && selectedTotalDuration < 17.5){
+            lastSpeedSelectIndex = 4
+        }else if(selectedTotalDuration > 0 && selectedTotalDuration < 10.5){
+            lastSpeedSelectIndex = 5
+        }
+        
+        
+        /*
+          文档规则 https://w42nne6hzg.feishu.cn/docs/doccnQZm1uCfkU4QtJb5fLxYk4d#
+         */
+        //2,根据所选择所有素材时长判断哪些功能不可能用,及进入默认模式
+        //全是图片
+        if(selectedDataCount == selectedImageDataCount){
+            BFLog(message: "全是图片 \(selectedDataCount) \(selectedImageDataCount)")
+            speedStuckBtn.isEnabled = false
+            //默认进入跳跃卡点模式
+            editModelClick(sender: jumpPointBtn)
+            speedSettingView.setSelectItem(index: lastJumpSpeedSelectIndex)
+            
+        }else{
+            
+            //1,根据素材输入确定可用模式及推荐模式
+            //1)0-6s时卡点不能使用, 纯图片时快慢速不可用
+            if(selectedTotalDuration > 0 && selectedTotalDuration < 6){
+                jumpPointBtn.isEnabled = false
+            }
+            //默认进入快慢速模式
+            if(selectedTotalDuration > 0 && selectedTotalDuration <= 144){
+                
+                editModelClick(sender: speedStuckBtn)
+                speedSettingView.setSelectItem(index: lastSpeedSelectIndex)
+     
+            }else{
+                //默认进入卡点模式
+                editModelClick(sender: jumpPointBtn)
+                speedSettingView.setSelectItem(index: lastJumpSpeedSelectIndex)
+        
+            }
+        }
+ 
     }
 }