| 
					
				 | 
			
			
				@@ -0,0 +1,2073 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//  PQStuckPointEditerController.swift 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//  PQSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//  Created by ak on 2021/4/26. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//  Copyright © 2021 BytesFlow. All rights reserved. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//  功能:卡点音乐编辑界面 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 创建不同玩法的类型 (1:跳跃卡点,2:快慢速,3:仅配乐) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public enum createStickersModel: Int { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    case createStickersModelPoint = 1 // 跳跃卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    case createStickersModelSpeed = 2 // 快慢速 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    case createStickersModelOnlyMusic = 3 // 仅配乐 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import BFCommonKit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import Foundation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import ObjectMapper 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import Photos 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import RealmSwift 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import UIKit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class PQStuckPointEditerController: BFBaseViewController { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 是否导出视频成功 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var isExportVideosSuccess: Bool = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 是否请求卡点数据成功 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var isStuckPointDataSuccess: Bool = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 是否同步音乐成功 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var isSynchroMusicInfoSuccess: Bool = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 当前所有的filter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var filters: Array = Array<ImageProcessingOperation>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 选中所有素材的的总时长 再进入编辑界面时已经不包括图片的时长 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var selectedTotalDuration: Float64 = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 选择的总数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var selectedDataCount: Int = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 选择的图片总数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var selectedImageDataCount: Int = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 选中的素材数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var selectedPhotoData: [PHAsset]? { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        didSet { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if selectedPhotoData != nil, (selectedPhotoData?.count ?? 0) > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                selectedMetarialData = Array<PQEditVisionTrackMaterialsModel>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                selectedPhotoData?.forEach { phAsset in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    let metarialData = PQEditVisionTrackMaterialsModel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.asset = phAsset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.width = Float(phAsset.pixelWidth) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.itemWidth = Float(phAsset.pixelWidth) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.height = Float(phAsset.pixelHeight) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.itemHeight = Float(phAsset.pixelHeight) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if phAsset.mediaType == .image { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        metarialData.type = "image" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } else if phAsset.mediaType == .video { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        metarialData.type = "video" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        metarialData.duration = Float64(phAsset.duration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.canvasFillType = phAsset.canvasFillType ?? "" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.locationPath = phAsset.localPath ?? "" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.selectedIndex = phAsset.selectedIndex ?? 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.originalData = phAsset.originalData 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    metarialData.coverImageUI = phAsset.image 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    selectedMetarialData?.append(metarialData) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var selectedMetarialData: [PQEditVisionTrackMaterialsModel]? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 选中的音乐数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var stuckPointMusicData: PQVoiceModel? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 保存所有段的所有贴纸,音频信息,用于播放器的渲染使用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var projectModel: PQEditProjectModel = PQEditProjectModel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 从草稿箱进入的项目数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var draftProjectModel: PQEditProjectModel? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var mStickers: [PQEditVisionTrackMaterialsModel]? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 播放器的开始和结束时间,1,刚进界面使用推荐的开始结束时间,2,用户修改起结点时修改 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var playeTimeRange: CMTimeRange = CMTimeRange() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 首帧图片 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var firstFrameImage: UIImage? { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        didSet { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if firstFrameImage != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                playerView.layer.contents = firstFrameImage?.cgImage 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // add by ak 是否是再创作模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var isReCreate: Bool = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public var reCreateVideoData: PQReCreateModel? // 再创作数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 最后一个选择的模式 BTN 用于还原选中状态 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var lastEditModelBtn: UIButton? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // add by ak  最大、最小速度 有固定值和自定义,当快慢速下两个值都有效,当跳跃卡点只有maxSpeed有效 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 快慢速模式的 速度设置,快/慢速 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var modelSpeed_maxSpeed: Float = 1.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var modelSpeed_minSpeed: Float = 1.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 跳跃模式的速度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var modelPoint_speed: Float = 1.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 快慢速最后一次选择的速度位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var lastSpeedSelectIndex: Int = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 跳跃卡点最后一次选择的速度位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var lastJumpSpeedSelectIndex: Int = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 循环次数设置最后一次选择的位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var lastCyclesSelectIndex: Int = -1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 当前选择的玩法模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var currentCreateStickersModel: createStickersModel = .createStickersModelSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 最终使用的卡点数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var finallyStuckPoints: Array = Array<Float>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var finallyStuckPointsInt64: Array = Array<Int64>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 最终使用的音频时长 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var finallyUserAudioTime: Float = 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 注意推荐时间位置和后面最近的卡点时间与0.3的关系 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 保存丢卡点处理后的卡点信息推荐开始到最后倒数第二个 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 经过档位处理后的卡点信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var stuckPointsTemp: Array = Array<Float>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var stuckPointsTempInt64: Array = Array<Int64>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 是否点击了下一步去合成 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    var isClickNextBtn: Bool = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 下一步 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var nextBtn: UIButton = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let nextBtn = UIButton(type: .custom) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        nextBtn.frame = CGRect(x: cScreenWidth - 16 - cDefaultMargin * 6, y: cDevice_iPhoneStatusBarHei + (cDevice_iPhoneNavBarHei - cDefaultMargin * 3) / 2, width: cDefaultMargin * 6, height: cDefaultMargin * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        nextBtn.setTitle("合成", for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        nextBtn.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: .medium) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        nextBtn.addTarget(self, action: #selector(nextBtnClick(sender:)), for: .touchUpInside) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        nextBtn.backgroundColor = UIColor.hexColor(hexadecimal: BFConfig.shared.styleColor.rawValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        nextBtn.setTitleColor(UIColor.hexColor(hexadecimal: "#FFFFFF"), for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        nextBtn.uxy_acceptEventInterval = 0.5 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        nextBtn.addCorner(corner: 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return nextBtn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 播放器显示 view 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var playerView: PQGPUImagePlayerView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let playerView = PQGPUImagePlayerView(frame: .zero) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.backgroundColor = BFConfig.shared.styleBackGroundColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.isShowLine = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.showGaussianBlur = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.pause() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.renderViewOnClickHandle = { [weak self] in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.musicEditBGView.pausePlayer() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.playerEmptyView.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return playerView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 节奏选择视图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var sustomSwitchView: PQCustomSwitchView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let sustomSwitchView = PQCustomSwitchView(frame: CGRect(x: 16, y: 0, width: 180, height: 30), titles: ["慢节奏", "适中", "快节奏"], defaultIndex: stuckPointMusicData?.speed ?? 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sustomSwitchView.switchChangeHandle = { [weak self] sender in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 改变速率,.只有快慢速且非只有图片素材时自动+1处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.stuckPointMusicData?.speed = sender.tag 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.musicEditBGView.pausePlayer() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.projectModel.sData?.getBGMSession()?.sectionTimeline?.audioTrack?.audioTrackMaterials.first?.bgmInfo?.rhythmMusicSpeed = sender.tag 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 播放前先暂停 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            self?.playerView.stop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 开始播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.settingPlayerView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 下面都是统计 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if self?.currentCreateStickersModel == .createStickersModelPoint { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_selectMusicVideoRhythm, pageSource: .sp_stuck_previewSyncedUp, extParams: nil, remindmsg: "点击上报:选择节奏") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if self?.currentCreateStickersModel == .createStickersModelSpeed { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_selectSpeedRhythm, pageSource: .sp_stuck_previewSyncedUp, extParams: nil, remindmsg: "点击上报:选择节奏") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if self?.currentCreateStickersModel == .createStickersModelOnlyMusic { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_selectMusicVideoRepeatRhythm, pageSource: .sp_stuck_previewSyncedUp, extParams: nil, remindmsg: "点击上报:选择节奏") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return sustomSwitchView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 裁剪视图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var stuckPointCuttingView: PQStuckPointCuttingView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let stuckPointCuttingView = PQStuckPointCuttingView(frame: CGRect(x: 0, y: optionlineView.frame.minY - 85 - 28, width: view.frame.width, height: 80), duration: CGFloat(Float(stuckPointMusicData?.duration ?? "0") ?? 0), suggestRhythmStartTime: CGFloat(stuckPointMusicData?.suggestRhythmStartTime ?? 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /// 裁剪进度回调 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stuckPointCuttingView.videoDidBeginDrag = { [weak self] in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(message: "开始划动") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.playerView.pause() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /// 播放进度回调 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stuckPointCuttingView.videoProgressDidChanged = { [weak self] progress in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(message: "进度更新返回--progress = \(progress) \(String(describing: self?.playerView.mPlayeTimeRange))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /// 拖缀结束的回调 type - 1-拖动左边裁剪结束 2--拖动右边裁剪结束 3-进度条拖动结束 4-滑动结束 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stuckPointCuttingView.videoDidEndDragging = { [weak self] type, startTime, endTime, progress in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(1, message: "拖拽结束返回--type = \(type),startTime = \(startTime),endTime = \(endTime),progress = \(progress)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.playerView.pause() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.musicEditBGView.pausePlayer() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 修改最新值 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.stuckPointMusicData?.startTime = Float64(startTime) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.stuckPointMusicData?.endTime = Float64(endTime) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 红的指针完成 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if type == 3 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if CMTimeGetSeconds(self?.playerView.mPlayeTimeRange?.end ?? .zero) == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    BFLog(message: "mPlayeTimeRange is error") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let newBeginSconds = (Double(startTime) + (Double(endTime) - Double(startTime)) * Double(progress)) * 600 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: " newBeginSconds is \(newBeginSconds)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let seekTimeRange: CMTimeRange = CMTimeRange(start: CMTime(value: CMTimeValue(Int64(newBeginSconds)), timescale: 600), end: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    CMTime(value: CMTimeValue(Int64(endTime * 600)), timescale: 600)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "修改的开始 \(CMTimeGetSeconds(seekTimeRange.start)) 结束  \(CMTimeGetSeconds(seekTimeRange.end))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 重新设置有效缓存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.playerView.configCache(beginTime: CMTimeGetSeconds(seekTimeRange.start)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.playerView.play(pauseFirstFrame: false, playeTimeRange: seekTimeRange) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 更改素材开始时间及结束时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.projectModel.sData?.getBGMSession()?.sectionTimeline?.audioTrack?.audioTrackMaterials.first?.out = Float64(endTime) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.projectModel.sData?.getBGMSession()?.sectionTimeline?.audioTrack?.audioTrackMaterials.first?.model_in = Float64(startTime) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.projectModel.sData?.getBGMSession()?.sectionTimeline?.audioTrack?.audioTrackMaterials.first?.timelineIn = Float64(startTime) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.projectModel.sData?.getBGMSession()?.sectionTimeline?.audioTrack?.audioTrackMaterials.first?.timelineOut = Float64(endTime) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "调整后总时长: \(endTime - startTime) startTime:\(startTime) endTime:\(endTime)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 初始化音频的开始和结束时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.playeTimeRange = CMTimeRange(start: CMTimeMakeWithSeconds(Float64(startTime), preferredTimescale: BASE_FILTER_TIMESCALE), end: CMTimeMakeWithSeconds(Float64(endTime), preferredTimescale: BASE_FILTER_TIMESCALE)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.dealParameter(model: self?.currentCreateStickersModel ?? .createStickersModelSpeed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (self?.finallyStuckPoints.count ?? 0) < 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    BFLog(message: "finallyStuckPoints data is error!!!!") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                DispatchQueue.global().async { // 并行、异步 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    let beginTime = Date() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.mStickers = self?.createStickers(sections: self?.projectModel.sData?.sections ?? List(), inputSize: CGSize(width: CGFloat(self?.projectModel.sData?.videoMetaData?.videoWidth ?? 0), height: CGFloat(self?.projectModel.sData?.videoMetaData?.videoHeight ?? 0)), model: self?.currentCreateStickersModel ?? .createStickersModelSpeed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    DispatchQueue.main.async { // 串行、异步 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.playerView.mStickers = self?.mStickers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        BFLog(message: "endTime is endTimeendTime \(Date().timeIntervalSince(beginTime))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.playerView.play(pauseFirstFrame: false, playeTimeRange: self!.playeTimeRange) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 更新一下时间条的UI总时间 及数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.stuckPointCuttingView.videoDuration = CGFloat(self?.finallyUserAudioTime ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.stuckPointCuttingView.stuckPointStartTime = CGFloat(CMTimeGetSeconds(self?.playeTimeRange.start ?? .zero)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.stuckPointCuttingView.stuckPointEndTime = CGFloat(CMTimeGetSeconds(self?.playeTimeRange.end ?? .zero)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.stuckPointCuttingView.tatalTimeLabel.text = "\(Float64(CMTimeGetSeconds(self?.playeTimeRange.end ?? .zero) - CMTimeGetSeconds(self?.playeTimeRange.start ?? .zero)).formatDurationToHMS())" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return stuckPointCuttingView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 卡点模式标题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var pointEditRemindLab: UILabel = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let pointEditRemindLab = UILabel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditRemindLab.backgroundColor = .clear 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditRemindLab.textAlignment = .left 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditRemindLab.font = UIFont.boldSystemFont(ofSize: 14) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditRemindLab.textColor = BFConfig.shared.styleTitleColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditRemindLab.text = "卡点模式" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return pointEditRemindLab 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 卡点模式标题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var speedTitleLab: UILabel = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let speedTitleLab = UILabel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedTitleLab.backgroundColor = .clear 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedTitleLab.textAlignment = .left 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedTitleLab.font = UIFont.boldSystemFont(ofSize: 14) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedTitleLab.textColor = BFConfig.shared.styleTitleColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedTitleLab.text = "节奏变化" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return speedTitleLab 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 卡点模式下方操作区背景 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var pointEditBGView: UIView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let pointEditBGView = UIView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.backgroundColor = .clear 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return pointEditBGView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 下方音乐编辑操作区背景 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var musicEditBGView: PQSelecteMusicView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let musicEditBGView = PQSelecteMusicView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.backgroundColor = .clear 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.isUserInteractionEnabled = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.musicSearchBtn.addTarget(self, action: #selector(musicSearchBtnClick(sender:)), for: .touchUpInside) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.didSelectItemHandle = { [weak self] status in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if status == .isSelected { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if self?.playerView.status != .playing { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.playerView.RenderViewOnclick() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.playerView.pause() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.btnClickHandle = { [weak self] _, bgmData in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 使用音乐 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.userstuckPointMusic(musicData: bgmData as? PQVoiceModel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return musicEditBGView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 卡点编辑 btn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var pointEditerBtn: UIButton = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let pointEdterBtn = UIButton(type: .custom) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEdterBtn.setImage(UIImage.moduleImage(named: "pointEditerBtn_n", moduleName: "BFFramework", isAssets: false), for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEdterBtn.setImage(UIImage.moduleImage(named: "pointEditerBtn_h", moduleName: "BFFramework", isAssets: false)?.withRenderingMode(.alwaysTemplate), for: .selected) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEdterBtn.tintColor = UIColor.hexColor(hexadecimal: BFConfig.shared.styleColor.rawValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEdterBtn.addTarget(self, action: #selector(pointEditerBtnClick(sender:)), for: .touchUpInside) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEdterBtn.isSelected = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEdterBtn.adjustsImageWhenHighlighted = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return pointEdterBtn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 音乐编辑 btn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var musicEditerBtn: UIButton = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let musicEditerBtn = UIButton(type: .custom) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditerBtn.setImage(UIImage.moduleImage(named: "musicEditerBtn_n", moduleName: "BFFramework", isAssets: false), for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditerBtn.setImage(UIImage.moduleImage(named: "musicEditerBtn_h", moduleName: "BFFramework", isAssets: false)?.withRenderingMode(.alwaysTemplate), for: .selected) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditerBtn.tintColor = UIColor.hexColor(hexadecimal: BFConfig.shared.styleColor.rawValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditerBtn.addTarget(self, action: #selector(musicEditerBtnClick(sender:)), for: .touchUpInside) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditerBtn.adjustsImageWhenHighlighted = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return musicEditerBtn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 快慢速卡点模式 btn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var speedStuckBtn: UIButton = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let speedStuckBtn = UIButton(type: .custom) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.addTarget(self, action: #selector(editModelClick1(sender:)), for: .touchUpInside) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.setTitle("快慢速卡点", for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: .regular) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.backgroundColor =  BFConfig.shared.pointEditNamalBackgroundColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.setTitleColor(UIColor.hexColor(hexadecimal: BFConfig.shared.styleColor.rawValue), for: .selected) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.setTitleColor(UIColor.hexColor(hexadecimal: "#959595"), for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.addCorner(corner: 5) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.imagePosition(at: .top, space: 8) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.tag = 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.adjustsImageWhenHighlighted = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.setImage(UIImage.moduleImage(named: BFConfig.shared.speedStuckBtnImage_N, moduleName: "BFFramework", isAssets: false), for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.setImage(UIImage.moduleImage(named: BFConfig.shared.speedStuckBtnImage_H, moduleName: "BFFramework", isAssets: false), for: .selected) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return speedStuckBtn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    lazy var speedStuckBtnGif: UIImageView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        let speedStuckBtnGif = UIImageView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        speedStuckBtnGif.kf.setImage(with: URL(fileURLWithPath: currentBundlePath()!.path(forResource: "speedstuck_h", ofType: "gif")!)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        speedStuckBtnGif.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        return speedStuckBtnGif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 跳转卡点模式 btn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var jumpPointBtn: UIButton = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let jumpPointBtn = UIButton(type: .custom) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.setTitle("跳跃卡点", for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: .regular) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.backgroundColor =  BFConfig.shared.pointEditNamalBackgroundColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.setTitleColor(UIColor.hexColor(hexadecimal: BFConfig.shared.styleColor.rawValue), for: .selected) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.setTitleColor(UIColor.hexColor(hexadecimal: "#959595"), for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.imagePosition(at: .top, space: 8) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.addCorner(corner: 5) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.tag = 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.addTarget(self, action: #selector(editModelClick1(sender:)), for: .touchUpInside) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.adjustsImageWhenHighlighted = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.setImage(UIImage.moduleImage(named: BFConfig.shared.jumpPointBtnImage_N, moduleName: "BFFramework", isAssets: false), for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.setImage(UIImage.moduleImage(named: BFConfig.shared.jumpPointBtnImage_H, moduleName: "BFFramework", isAssets: false), for: .selected) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return jumpPointBtn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    lazy var jumpPointBtnGif: UIImageView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        let jumpPointBtnGif = UIImageView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        jumpPointBtnGif.kf.setImage(with: URL(fileURLWithPath: currentBundlePath()!.path(forResource: "jumpPoint_n", ofType: "gif")!)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        jumpPointBtnGif.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        return jumpPointBtnGif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 仅配乐模式 btn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var onlyMusicBtn: UIButton = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let onlyMusicBtn = UIButton(type: .custom) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.setTitle("仅配乐", for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: .regular) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.backgroundColor =  BFConfig.shared.pointEditNamalBackgroundColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.setTitleColor(UIColor.hexColor(hexadecimal: BFConfig.shared.styleColor.rawValue), for: .selected) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.setTitleColor(UIColor.hexColor(hexadecimal: "#959595"), for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.addCorner(corner: 5) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.tag = 3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.addTarget(self, action: #selector(editModelClick1(sender:)), for: .touchUpInside) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.adjustsImageWhenHighlighted = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.setImage(UIImage.moduleImage(named: BFConfig.shared.onlyMusicBtnImage_N, moduleName: "BFFramework", isAssets: false), for: .normal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.setImage(UIImage.moduleImage(named: BFConfig.shared.onlyMusicBtnImage_H, moduleName: "BFFramework", isAssets: false), for: .selected) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return onlyMusicBtn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 操作面板上的分割线 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var optionlineView: UIView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let optionlineView = UIView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        optionlineView.backgroundColor = BFConfig.shared.pointEditNamalBackgroundColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return optionlineView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 固定速度 UI 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var speedSettingView: PQSpeedSettingView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let speedSetView = PQSpeedSettingView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedSetView.backgroundColor = .clear 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedSetView.selectSpeedCallBack = { [weak self] maxSpeed, minSpeed, selectIndex, isSettingPlayer in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(message: "固定maxSpeed is\(maxSpeed) minSpeed \(minSpeed)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.musicEditBGView.pausePlayer() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if maxSpeed == -1.0, minSpeed == -1.0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.customSpeedSettingView.isHidden = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.customSpeedSettingView.viewType = self?.speedSettingView.viewType ?? 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if maxSpeed != 0.0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 更新最后一次选择的位置恢复时使用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if self?.speedSettingView.viewType == 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.lastSpeedSelectIndex = selectIndex 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.modelSpeed_maxSpeed = maxSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.modelSpeed_minSpeed = minSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } else if self?.speedSettingView.viewType == 2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.lastJumpSpeedSelectIndex = selectIndex 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.modelPoint_speed = maxSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.lastCyclesSelectIndex = selectIndex 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    BFLog(message: "设置速度无效") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if isSettingPlayer { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.settingPlayerView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return speedSetView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 自定义速度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var customSpeedSettingView: PQCustomSpeedSettingView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let customSpeedSetView = PQCustomSpeedSettingView(frame: CGRect(x: 0, y: cScreenHeigth - 354, width: cScreenWidth, height: 354)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        customSpeedSetView.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        customSpeedSetView.selectSpeedCallBack = { [weak self, weak customSpeedSetView] maxSpeed, minSpeed, isJumpSpeedModel, isCancle in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if !isCancle { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "自定义速度maxSpeed is\(maxSpeed) minSpeed \(minSpeed) \(isJumpSpeedModel)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.musicEditBGView.pausePlayer() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 自定定义的更新一下最后的选择位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if self?.speedSettingView.viewType == 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.lastSpeedSelectIndex = -1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.modelSpeed_maxSpeed = maxSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.modelSpeed_minSpeed = minSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else if self?.speedSettingView.viewType == 2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.lastJumpSpeedSelectIndex = -1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.modelPoint_speed = maxSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.lastCyclesSelectIndex = Int(maxSpeed - 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.settingPlayerView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 确认后 选中自定义 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.speedSettingView.selectCustom() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 取消后恢复上一次选择的位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if self?.speedSettingView.viewType == 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.speedSettingView.setSelectItem(index: self?.lastSpeedSelectIndex ?? 0, isSettingPlayer: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else if self?.speedSettingView.viewType == 2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.speedSettingView.setSelectItem(index: self?.lastJumpSpeedSelectIndex ?? 0, isSettingPlayer: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.speedSettingView.setSelectItem(index: self?.lastCyclesSelectIndex ?? 0, isSettingPlayer: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                customSpeedSetView?.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return customSpeedSetView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 音乐标题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var musicNameView: UIView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let musicNameView = UIView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameView.addSubview(musicNameLab) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let nameWidth: CGFloat = musicNameLab.frame.width + (25 + cDefaultMargin * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameView.frame = CGRect(x: (view.frame.width - nameWidth) / 2, y: cDevice_iPhoneStatusBarHei + (cDevice_iPhoneNavBarHei - cDefaultMargin * 3) / 2, width: nameWidth, height: cDefaultMargin * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        musicNameView.backgroundColor = UIColor.hexColor(hexadecimal: "#333333") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameView.addCorner(corner: musicNameView.frame.height / 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let musicImageView = UIImageView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicImageView.tintColor = BFConfig.shared.styleTitleColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicImageView.image = UIImage.moduleImage(named: "stuckPoint_reCreate_music", moduleName: "BFFramework", isAssets: false)?.withRenderingMode(.alwaysTemplate) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicImageView.frame = CGRect(x: musicNameView.frame.height / 2 - 5, y: (musicNameView.frame.height - 22) / 2, width: 22, height: 22) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameView.addSubview(musicImageView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameLab.frame.origin.x = musicImageView.frame.maxX + 5 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return musicNameView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 音乐歌曲名称 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var musicNameLab: LMJHorizontalScrollText = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let nameWidth: CGFloat = sizeWithText(text: "\(stuckPointMusicData?.musicName ?? "")", font: UIFont.systemFont(ofSize: 13), size: CGSize(width: view.frame.width - ((cDefaultMargin * 6 + 16 * 2) * 2) - (25 + cDefaultMargin * 3), height: cDefaultMargin * 3)).width 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let musicNameLab = LMJHorizontalScrollText(frame: CGRect(x: 0, y: 0, width: nameWidth < cDefaultMargin * 4 ? cDefaultMargin * 4 : nameWidth, height: cDefaultMargin * 3)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameLab.textColor = BFConfig.shared.styleTitleColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameLab.textFont = UIFont.systemFont(ofSize: 13) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameLab.speed = 0.03 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameLab.moveDirection = LMJTextScrollMoveLeft 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameLab.moveMode = LMJTextScrollContinuous 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if nameWidth < cDefaultMargin * 4 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            musicNameLab.text = " \(stuckPointMusicData?.musicName ?? "") " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            musicNameLab.text = " \(stuckPointMusicData?.musicName ?? "") " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return musicNameLab 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 同步进度显示 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lazy var synchroMarskView: PQStuckPointLoadingView = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var synchroMarskView = PQStuckPointLoadingView(frame: CGRect(x: 0, y: 0, width: cScreenWidth, height: cScreenHeigth)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        synchroMarskView.cancelHandle = { [weak self] _ in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.navigationController?.popViewController(animated: true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return synchroMarskView 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @objc func willEnterForeground() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(message: "进入到前台") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if navigationController?.topViewController == self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if projectModel.sData!.sections.count > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                settingPlayerView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                prepareMeta() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @objc func enterBackground() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(message: "进入到后台") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 取消导出 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if navigationController?.topViewController == self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            playerView.pause() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    override func backBtnClick() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        super.backBtnClick() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        playerView.pause() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 点击上报:返回按钮 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_back, pageSource: .sp_stuck_previewSyncedUp, extParams: nil, remindmsg: "卡点视频数据上报-(点击上报:返回按钮)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 使用选择音乐 调用情况:1,操作面板直接选择 ,2 搜索界面点击使用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func userstuckPointMusic(musicData: PQVoiceModel?) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 1,音乐面板点击了使用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stuckPointMusicData = musicData 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 2,同步最新音乐数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        synchroMusicInfoData(resetSelectIndex: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 3,更新音乐标题UI 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let nameWidth: CGFloat = sizeWithText(text: "\(stuckPointMusicData?.musicName ?? "")", font: UIFont.systemFont(ofSize: 13), size: CGSize(width: view.frame.width - ((cDefaultMargin * 6 + 16 * 2) * 2) - (25 + cDefaultMargin * 3), height: cDefaultMargin * 3)).width 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if nameWidth < cDefaultMargin * 4 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            musicNameLab.text = " \(stuckPointMusicData?.musicName ?? "") " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            musicNameLab.text = " \(stuckPointMusicData?.musicName ?? "") " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 更新一下节奏的 UI 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sustomSwitchView.selectOneBtn(Index: stuckPointMusicData?.speed ?? 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 点击搜索音乐 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @objc func musicSearchBtnClick(sender _: UIButton) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let searchVC = PQEditMusicSearchController() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        searchVC.btnClickHandle = { [weak self] _, bgmData in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 使用音乐 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(message: "搜索音乐点击了使用") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.musicEditBGView.insertSearchMusic(model: bgmData as! PQVoiceModel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self?.userstuckPointMusic(musicData: bgmData as? PQVoiceModel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let navigationController: UINavigationController = UINavigationController(rootViewController: searchVC) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        navigationController.modalPresentationStyle = .fullScreen 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        present(navigationController, animated: true, completion: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 卡点编辑 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @objc func pointEditerBtnClick(sender: UIButton) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if sender.isSelected { return } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sender.isSelected = !sender.isSelected 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditerBtn.isSelected = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.isHidden = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_videoTab, pageSource: .sp_shanyinApp_main, extParams: nil, remindmsg: "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 音乐编辑 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @objc func musicEditerBtnClick(sender: UIButton) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if sender.isSelected { return } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sender.isSelected = !sender.isSelected 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditerBtn.isSelected = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.showData() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_musicTab, pageSource: .sp_shanyinApp_main, extParams: nil, remindmsg: "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @objc func editModelClick1(sender: UIButton) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        editModelClick(sender: sender) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 三种模式修改 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @objc func editModelClick(sender: UIButton, reportLog: Bool = true) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        if sender.isSelected { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            BFLog(message: "已经是选中状态") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            return  “” 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.pausePlayer() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sharedImageProcessingContext.framebufferCache.purgeAllUnassignedFramebuffers() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if sender == jumpPointBtn, selectedTotalDuration < 6, selectedDataCount != selectedImageDataCount, reCreateVideoData == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            cShowHUB(superView: view, msg: "素材时长需要大于6秒才\n可选择“跳跃卡点”模式") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lastEditModelBtn?.isSelected = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //设置取消选中的背景色 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lastEditModelBtn?.backgroundColor = BFConfig.shared.pointEditNamalBackgroundColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sender.isSelected = !sender.isSelected 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lastEditModelBtn = sender 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //设置选中的背景色 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let styleColor = UIColor.hexColor(hexadecimal: BFConfig.shared.styleColor.rawValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lastEditModelBtn?.backgroundColor = UIColor(red: styleColor.rgbaf[0], green: styleColor.rgbaf[1], blue: styleColor.rgbaf[2], alpha: 0.15) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(message: "sender tag is \(sender.tag)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 2素材全是图片的时候三个模式都显示循环设置 UI 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if selectedDataCount == selectedImageDataCount { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speedSettingView.viewType = 3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            customSpeedSettingView.viewType = speedSettingView.viewType 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speedSettingView.snp.remakeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                make.left.equalToSuperview().offset(16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                make.right.equalToSuperview() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                make.top.equalTo(onlyMusicBtn.snp.bottom).offset(10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                make.height.equalTo(30) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speedSettingView.isHidden = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speedTitleLab.isHidden = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sustomSwitchView.isHidden = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if lastCyclesSelectIndex != -1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                speedSettingView.setSelectItem(index: lastCyclesSelectIndex, isSettingPlayer: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 1 ui 调整 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if sender.tag == 1 || sender.tag == 2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                speedSettingView.viewType = sender.tag 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                customSpeedSettingView.viewType = speedSettingView.viewType 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                speedSettingView.snp.remakeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    make.left.equalToSuperview().offset(16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    make.right.equalToSuperview() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    make.top.equalTo(onlyMusicBtn.snp.bottom).offset(10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    make.height.equalTo(sender.tag == 1 ? 44 : 30) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                speedSettingView.isHidden = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                speedTitleLab.isHidden = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                sustomSwitchView.isHidden = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if sender.tag == 1 { // 快慢速 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    speedSettingView.setSelectItem(index: lastSpeedSelectIndex, isSettingPlayer: false, setDisable: (selectedTotalDuration < 6 && selectedDataCount != selectedImageDataCount) ? true : false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else if sender.tag == 2 { // 跳跃卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    speedSettingView.setSelectItem(index: lastJumpSpeedSelectIndex, isSettingPlayer: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                speedTitleLab.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                speedSettingView.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                sustomSwitchView.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 3 设置 btn 不同显示状态 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var speedStuckBtnGifName = "" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var jumpPointBtnGifName = "" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if sender.tag == 1 { // 快慢速 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speedStuckBtnGifName = "speedstuck_h_pq" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            jumpPointBtnGifName = "jumpPoint_n_pq" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            currentCreateStickersModel = .createStickersModelSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if reportLog { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_selectPatternSpeed, pageSource: .sp_shanyinApp_main, extParams: nil, remindmsg: "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if sender.tag == 2 { // 跳跃卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speedStuckBtnGifName = "speedstuck_n_pq" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            jumpPointBtnGifName = "jumpPoint_h_pq" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            currentCreateStickersModel = .createStickersModelPoint 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if reportLog { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_selectPatternMusicVideo, pageSource: .sp_shanyinApp_main, extParams: nil, remindmsg: "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if sender.tag == 3 { // 仅音乐 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speedStuckBtnGifName = "speedstuck_n_pq" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            jumpPointBtnGifName = "jumpPoint_n_pq" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            currentCreateStickersModel = .createStickersModelOnlyMusic 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if reportLog { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_selectPatternBgm, pageSource: .sp_shanyinApp_main, extParams: nil, remindmsg: "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        settingPlayerView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    override func viewWillAppear(_ animated: Bool) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        super.viewWillAppear(animated) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lineView?.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        DispatchQueue.main.async { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            UIApplication.shared.isIdleTimerDisabled = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameLab.move() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQNotification.addObserver(self, selector: #selector(enterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQNotification.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 从分享返回后从重初始化播放器 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if isClickNextBtn { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            isClickNextBtn = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            settingPlayerView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    override func viewWillDisappear(_ animated: Bool) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        super.viewWillDisappear(animated) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        DispatchQueue.main.async { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            UIApplication.shared.isIdleTimerDisabled = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameLab.stop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.stop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.pausePlayer() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQNotification.removeObserver(self) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        synchroMarskView.removeMarskView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    override func viewDidLoad() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        super.viewDidLoad() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        leftButton(image: nil, tintColor: BFConfig.shared.styleTitleColor) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        navHeadImageView?.addSubview(nextBtn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        navHeadImageView?.addSubview(musicNameView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 添加子视图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        addSubViews() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        prepareMeta() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 曝光上报:预览页面曝光上报 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQEventTrackViewModel.baseReportUpload(businessType: .bt_windowView, objectType: .ot_view_previewSyncedUp, pageSource: .sp_stuck_previewSyncedUp, extParams: nil, remindmsg: "卡点视频数据上报-(曝光上报:预览页面曝光上报)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 从选择的素材中 第一个素材设置封面 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if selectedPhotoData != nil, selectedPhotoData!.count > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let photo = selectedPhotoData!.first! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let option = PHImageRequestOptions() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            option.isNetworkAccessAllowed = true // 允许下载iCloud的图片 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            option.resizeMode = .none 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            option.deliveryMode = .highQualityFormat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            PHImageManager.default().requestImage(for: photo, targetSize: CGSize(width: 1920, height: 1920), contentMode: .aspectFill, options: option) { [weak self] image, _ in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // image就是图片 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if image != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.firstFrameImage = image 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    override func viewDidLayoutSubviews() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        super.viewDidLayoutSubviews() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.resetCanvasFrame(frame: coculationPlayViewRect()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func prepareMeta() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 导出相册视频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        exportPhotoData() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 同步音乐数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        synchroMusicInfoData() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 插入选择的音乐信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.firstInsertVoiceModel = stuckPointMusicData! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 添加子视图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Returns: <#description#> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func addSubViews() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (stuckPointMusicData?.rhythmSdata.count ?? 0) <= 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        view.addSubview(playerView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        view.addSubview(pointEditBGView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        view.addSubview(musicEditBGView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        view.addSubview(optionlineView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        view.addSubview(pointEditerBtn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        view.addSubview(musicEditerBtn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        view.addSubview(customSpeedSettingView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.addSubview(pointEditRemindLab) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.addSubview(speedTitleLab) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.addSubview(speedStuckBtn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.addSubview(jumpPointBtn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.addSubview(onlyMusicBtn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.addSubview(speedSettingView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.addSubview(sustomSwitchView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 音乐 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.addSubview(stuckPointCuttingView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditerBtn.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.equalToSuperview().offset(100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.bottom.equalToSuperview().offset(-(14 + cAKSafeAreaHeight)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(24) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.width.equalTo(24) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditerBtn.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.right.equalToSuperview().offset(-100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.top.equalTo(pointEditerBtn.snp.top) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(24) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.width.equalTo(24) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditBGView.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.right.equalTo(view) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.bottom.equalTo(pointEditerBtn.snp.top).offset(-7) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(290) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicEditBGView.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.right.equalToSuperview() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.bottom.equalTo(pointEditerBtn.snp.top).offset(-7) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(290) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        optionlineView.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.right.equalToSuperview() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.bottom.equalTo(pointEditBGView.snp.bottom).offset(-1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stuckPointCuttingView.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.right.equalToSuperview() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.bottom.equalTo(musicEditBGView.snp.bottom).offset(-1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(85) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pointEditRemindLab.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.equalToSuperview().offset(16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.top.equalToSuperview().offset(16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(20) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.width.equalTo(80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.equalToSuperview().offset(16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.top.equalTo(pointEditRemindLab.snp.bottom).offset(8) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.width.equalTo(80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.equalTo(speedStuckBtn.snp.right).offset(10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.top.equalTo(speedStuckBtn.snp.top) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.width.equalTo(80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.equalTo(jumpPointBtn.snp.right).offset(10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.top.equalTo(speedStuckBtn.snp.top) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.width.equalTo(64) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 重新设置三个模式 btn 图片和title的位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.titleEdgeInsets = UIEdgeInsets(top: 0, left: -(speedStuckBtn.imageView?.frame.size.width ?? 0), bottom: -(speedStuckBtn.imageView?.frame.size.height ?? 0), right: 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedStuckBtn.imageEdgeInsets = UIEdgeInsets(top: -(speedStuckBtn.titleLabel?.intrinsicContentSize.height ?? 0), left: 0, bottom: 0, right: -(speedStuckBtn.titleLabel?.intrinsicContentSize.width ?? 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.titleEdgeInsets = UIEdgeInsets(top: 0, left: -(jumpPointBtn.imageView?.frame.size.width ?? 0), bottom: -(jumpPointBtn.imageView?.frame.size.height ?? 0), right: 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        jumpPointBtn.imageEdgeInsets = UIEdgeInsets(top: -(jumpPointBtn.titleLabel?.intrinsicContentSize.height ?? 0), left: 0, bottom: 0, right: -(jumpPointBtn.titleLabel?.intrinsicContentSize.width ?? 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.titleEdgeInsets = UIEdgeInsets(top: 0, left: -(onlyMusicBtn.imageView?.frame.size.width ?? 0), bottom: -(onlyMusicBtn.imageView?.frame.size.height ?? 0), right: 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        onlyMusicBtn.imageEdgeInsets = UIEdgeInsets(top: -(onlyMusicBtn.titleLabel?.intrinsicContentSize.height ?? 0), left: 0, bottom: 0, right: -(onlyMusicBtn.titleLabel?.intrinsicContentSize.width ?? 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedSettingView.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.equalToSuperview().offset(16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.right.equalToSuperview() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.top.equalTo(onlyMusicBtn.snp.bottom).offset(10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(44) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        speedTitleLab.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.equalToSuperview().offset(16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.top.equalToSuperview().offset(190) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(20) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.width.equalTo(80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sustomSwitchView.snp.makeConstraints { make in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.left.equalToSuperview().offset(16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.top.equalTo(speedTitleLab.snp.bottom).offset(8) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.height.equalTo(30) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            make.width.equalTo(180) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @objc func nextBtnClick(sender _: UIButton) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(message: "去发布") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        isClickNextBtn = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.pause() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 使用深 copy 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let json = projectModel.toJSONString(prettyPrint: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if json == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(message: "数据转换有问题 跳转") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let tempModel: PQEditProjectModel? = Mapper<PQEditProjectModel>().map(JSONString: json!) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let materialVC: PQStuckPointMaterialController? = navigationController?.viewControllers.first(where: { (vc) -> Bool in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            vc is PQStuckPointMaterialController 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }) as? PQStuckPointMaterialController 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if materialVC != nil, materialVC?.isToPublicHandle != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            materialVC?.isToPublicHandle!(isReCreate, selectedTotalDuration, selectedDataCount, selectedImageDataCount, mStickers, stuckPointMusicData, tempModel, currentCreateStickersModel, modelSpeed_maxSpeed, modelSpeed_minSpeed, Float(finallyStuckPoints.last ?? 0) - Float(finallyStuckPoints.first ?? 0), getClipAudioRange(), playeTimeRange) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if finallyStuckPoints.count == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                cShowHUB(superView: nil, msg: "无卡点信息,返回重新选择音乐") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let videoExporter = PQStuckPointPublicController() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.rhythmMode = currentCreateStickersModel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.syncedUpVideoSpeedMin = modelSpeed_maxSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.syncedUpVideoSpeedMax = modelSpeed_minSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.isReCreate = isReCreate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.selectedTotalDuration = selectedTotalDuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.selectedDataCount = selectedDataCount 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.selectedImageDataCount = selectedImageDataCount 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.finallyUserAudioTime = Float(finallyStuckPoints.last ?? 0) - Float(finallyStuckPoints.first ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.clipAudioRange = getClipAudioRange() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.playeTimeRange = playeTimeRange 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.mStickers = mStickers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.audioMixModel = stuckPointMusicData 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.coverImage = selectedMetarialData?.first?.coverImageUI ?? UIImage.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoExporter.editProjectModel = tempModel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            navigationController?.pushViewController(videoExporter, animated: true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 点击上报:去合成 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_commit, pageSource: .sp_stuck_previewSyncedUp, extParams: ["musicName": stuckPointMusicData?.musicName ?? "", "musicId": stuckPointMusicData?.musicId ?? "", "rhythmNumber": stuckPointMusicData?.speed ?? 2, "duration": ((stuckPointMusicData?.endTime ?? 0) - (stuckPointMusicData?.startTime ?? 0)) * 1000], remindmsg: "点击上报:去合成") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        super.touchesBegan(touches, with: event) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if touches.first?.view != customSpeedSettingView { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if !customSpeedSettingView.isHidden { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                customSpeedSettingView.isHidden = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // MARK: - 播放器相关操作 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// seek 播放器 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Parameter playeTimeRange: 开始和结束时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func seekPlayer(playeTimeRange: CMTimeRange) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.setEnableSeek(isSeek: true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.play(pauseFirstFrame: false, playeTimeRange: playeTimeRange) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 通过传入的    selectedPhotoData 、 stuckPointMusicData 创建 projectModel 模型 后面都使用 projectModel 参数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func createPorjectData() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 1,添加选择的视觉素材 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if projectModel.sData?.sections.count == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let section: PQEditSectionModel = PQEditSectionModel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            selectedMetarialData?.forEach { model in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                let json = model.toJSONString(prettyPrint: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                if json == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                    BFLog(message: "数据转换有问题 跳转") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                    return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                let tempModel: PQEditVisionTrackMaterialsModel = Mapper<PQEditVisionTrackMaterialsModel>().map(JSONString: json!)! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                section.sectionTimeline?.visionTrack?.visionTrackMaterials.append(model) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            projectModel.sData?.sections.append(section) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 2,添加背景音乐 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        projectModel.sData?.addBGM(audioMix: stuckPointMusicData!) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 计算拼接音乐的开始和结束点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func getClipAudioRange() -> CMTimeRange { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 设置音乐的拼接范围,开始:推荐的卡点  结束:点到的倒数第二位 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if stuckPointMusicData!.rhythmSdata.count > 0, stuckPointMusicData?.rhythmSdata[0].pointTimes.count ?? 0 > 2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            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)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return clipAudioRange 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return CMTimeRange(start: CMTime(value: 0, timescale: 1), duration: CMTime(value: 1, timescale: 1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 设置播放器 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func coculationPlayViewRect() -> CGRect { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let playerShowHeight = pointEditBGView.frame.minY - (navHeadImageView?.frame.maxY ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var showRect: CGRect = CGRect(x: (cScreenWidth - playerShowHeight) / 2, y: 0, width: playerShowHeight, height: playerShowHeight) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if firstFrameImage != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let w = firstFrameImage!.size.width 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let h = firstFrameImage!.size.height 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let ratioMaterial: Float = Float(w / max(h, 1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ratioMaterial > 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 横屏 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let tempPlayerHeight = min(cScreenWidth * CGFloat(h / w), playerShowHeight) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect = CGRect(x: (cScreenWidth - tempPlayerHeight * CGFloat(ratioMaterial)) / 2, y: (playerShowHeight - tempPlayerHeight) / 2, width: tempPlayerHeight * CGFloat(ratioMaterial), height: tempPlayerHeight) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 竖屏 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let playerViewWidth = (CGFloat(w) / CGFloat(h)) * playerShowHeight 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect = CGRect(x: (cScreenWidth - playerViewWidth) / 2, y: 0, width: playerViewWidth, height: playerShowHeight) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if showRect.size.width == showRect.size.height { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if cScreenWidth > playerShowHeight { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect.origin.x = (cScreenWidth - playerShowHeight) / 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect.size.width = playerShowHeight 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect.size.height = playerShowHeight 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect.origin.x = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect.size.width = cScreenWidth 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect.size.height = cScreenWidth 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if showRect.size.width != 0, showRect.size.height != 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if Int(showRect.height) % 2 != 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect.size.height = showRect.size.height + 1.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if Int(showRect.width) % 2 != 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                showRect.size.width = showRect.size.width + 1.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        showRect.origin.y = (playerShowHeight - showRect.size.height) / 2.0 + (navHeadImageView?.frame.maxY ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return showRect 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func settingPlayerView() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stuckPointCuttingView.resetDefaultsColor() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        synchroMarskView.show() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 1,设置播放器的显示区域 和画布大小 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //  - 按第一个素材尺寸自适应 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playerView.pause() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var firstModel: PQEditVisionTrackMaterialsModel? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for part in projectModel.sData!.sections { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if part.sectionTimeline?.visionTrack?.getEnableVisionTrackMaterials().count ?? 0 > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                firstModel = part.sectionTimeline?.visionTrack?.getEnableVisionTrackMaterials().first 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var videoSize: CGSize = CGSize(width: Int(firstModel?.width ?? 0), height: Int(firstModel?.height ?? 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var minSlider = min(videoSize.width, videoSize.height) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var maxSlider = max(videoSize.width, videoSize.height) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let ration = 1080 / minSlider 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        minSlider = minSlider * ration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        maxSlider = maxSlider * ration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if videoSize.width > videoSize.height { // 宽屏 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoSize = CGSize(width: maxSlider, height: minSlider) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoSize = CGSize(width: minSlider, height: maxSlider) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if videoSize.width.isNaN || videoSize.height.isNaN { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(1, message: "宽高无效NaN") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let maxValue = max(videoSize.width, videoSize.height) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if maxValue > 1920 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let maxRation = 1920 / maxValue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoSize = CGSize(width: videoSize.width * CGFloat(maxRation), height: videoSize.height * CGFloat(maxRation)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(message: "最长边已经超过 1920 要等比缩小 缩放后\(videoSize)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (Int(videoSize.width) % 2) != 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoSize.width = videoSize.width - 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (Int(videoSize.height) % 2) != 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoSize.height = videoSize.height - 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        projectModel.sData?.videoMetaData?.videoWidth = Int(videoSize.width) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        projectModel.sData?.videoMetaData?.videoHeight = Int(videoSize.height) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let beginTime = Date() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        dealParameter(model: currentCreateStickersModel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 更新裁剪时间条的的ui数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stuckPointCuttingView.videoDuration = max(CGFloat(finallyUserAudioTime), CGFloat(finallyStuckPoints.last!)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let counn = (stuckPointMusicData?.rhythmSdata[0].pointTimes.count)! - 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let suggestRhythmStartTime = CGFloat(stuckPointMusicData?.suggestRhythmStartTime ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let suggestRhythmEndTime = max(suggestRhythmStartTime, CGFloat(stuckPointMusicData?.rhythmSdata[0].pointTimes[max(counn, 0)] ?? 0) / CGFloat(BASE_FILTER_TIMESCALE)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stuckPointCuttingView.updateEndTime( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            startTime: CGFloat(CMTimeGetSeconds(playeTimeRange.start)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            endTime: CGFloat(CMTimeGetSeconds(playeTimeRange.end)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            suggestRhythmStartTime: suggestRhythmStartTime, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            suggestRhythmEndTime: suggestRhythmEndTime 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 2,创建滤镜 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        DispatchQueue.global().async { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.mStickers = self.createStickers(sections: self.projectModel.sData?.sections ?? List(), inputSize: CGSize(width: CGFloat(self.projectModel.sData?.videoMetaData?.videoWidth ?? 0), height: CGFloat(self.projectModel.sData?.videoMetaData?.videoHeight ?? 0)), model: self.currentCreateStickersModel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            DispatchQueue.main.async { // 串行、异步 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.playerView.mStickers = self.mStickers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "createStickers tiskskskskme  \(Date().timeIntervalSince(beginTime))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 3,设置音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let audioPath = self.stuckPointMusicData?.localPath ?? "" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "初始化音频播放器的音频地址为:\(audioPath)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.playerView.stop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 这里的测试这个音乐播放有问题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //        self.playerView.updateAsset(URL(fileURLWithPath: "63930549652d74e477141e3b79c8d29a9ef8af81625053214516.mp3", relativeTo:Bundle.main.resourceURL!), videoComposition: nil, audioMixModel: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.playerView.updateAsset(URL(fileURLWithPath: documensDirectory + audioPath), videoComposition: nil, audioMixModel: nil, originMusicDuration: self.finallyUserAudioTime, clipAudioRange: self.getClipAudioRange(), isUsedAVPlayer: true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 4, 设置播放器的输出画布大小 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.playerView.movie?.mShowVidoSize = CGSize(width: CGFloat(self.projectModel.sData?.videoMetaData?.videoWidth ?? 0), height: CGFloat(self.projectModel.sData?.videoMetaData?.videoHeight ?? 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 传给movie 音频的原始卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let fir = Int64(self.stuckPointsTemp.first ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let endd = Int64(self.stuckPointsTemp.last ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.playerView.movie?.orginStuckRange = CMTimeRange(start: CMTime(value: Int64(fir) * Int64(BASE_FILTER_TIMESCALE), timescale: BASE_FILTER_TIMESCALE), end: CMTime(value: Int64(endd) * Int64(BASE_FILTER_TIMESCALE), timescale: BASE_FILTER_TIMESCALE)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 5,开始播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.playerView.isLoop = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.playerView.showProgressLab = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 初始化音频的开始和结束时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "播放的器 开始\(String(describing: CMTimeGetSeconds(self.playeTimeRange.start))) 结束 \(String(describing: CMTimeGetSeconds(self.playeTimeRange.end)))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let end3: TimeInterval = Date().timeIntervalSince1970 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.playerView.play(pauseFirstFrame: false, playeTimeRange: CMTimeRange(start: self.playeTimeRange.start, end: self.playeTimeRange.end)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.stuckPointCuttingView.updateProgress(progress: 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.synchroMarskView.removeMarskView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let end4: TimeInterval = Date().timeIntervalSince1970 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: " playerView.play tiskskskskme  \(end4 - end3)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 6,进度回调 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.playerView.progress = { [weak self] currentTime, tatolTime, percent in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if percent == 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.stuckPointCuttingView.resetDefaultsColor(clearData: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        sharedImageProcessingContext.framebufferCache.purgeAllUnassignedFramebuffers() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if CMTimeGetSeconds(self?.playeTimeRange.duration ?? .zero) <= 0.0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        BFLog(message: "时长错误!!!!") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 更新进度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    let progress = (currentTime - CMTimeGetSeconds(self?.playeTimeRange.start ?? .zero)) / CMTimeGetSeconds(self?.playeTimeRange.duration ?? .zero) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    BFLog(message: "\(currentTime) \(tatolTime) 显示播放器进度为: \(progress)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.stuckPointCuttingView.updateProgress(progress: CGFloat(progress)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deinit { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        musicNameLab.stop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        playerView.pause() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 取消所有的导出 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQSingletoMemoryUtil.shared.allExportSession.forEach { _, exportSession in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            exportSession.cancelExport() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.synchroMarskView.removeMarskView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sharedImageProcessingContext.framebufferCache.purgeAllUnassignedFramebuffers() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(1, message: "卡点视频预览界面release") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// MARK: - 视频渲染相关逻辑方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+extension PQStuckPointEditerController { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 分割视频 这里只设置视频类型的 in 和 out 并不设置显示的开始和结束时间   mp4 ,png ,png ,mp4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Parameter section: 当前段 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Parameter stuckPoints: 用户选择的,或推荐的卡点数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Returns: 返回分割后的所有 stickers 和卡点数是一致的 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func clipVideoMerage(section: PQEditSectionModel, stuckPoints: [Float]) -> [PQEditVisionTrackMaterialsModel] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var stickers: Array = Array<PQEditVisionTrackMaterialsModel>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 第二种情况:有视频要进行分割 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         1, 确定每个视频素材需要切的段数p 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         2, 将所有视频时长相加,得到总视频素材时长L = l1 + l2 + ... + ln 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         3, 视频素材a1需要切分的个数clipNum = max (round (kongduan * a1 / L) , 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 要补的空位数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let kongduan: Int = Int(stuckPoints.count - 1) - selectedImageDataCount 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 所有视频总时长 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var videoTotalDuration: Float64 = 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for video in section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials(type: "video") { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // MARK: SanW-2021.11.15-不再导出到沙盒,直接使用本地相册地址 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: video.locationPath), options: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: documensDirectory + video.locationPath), options: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            videoTotalDuration = videoTotalDuration + Float64(CMTimeGetSeconds(asset.duration)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if videoTotalDuration == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(message: "视频总时长出现错误!!!!这里应该有视频素材的") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return stickers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for sticker in section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if sticker.type == StickerType.VIDEO.rawValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // MARK: SanW-2021.11.15-不再导出到沙盒,直接使用本地相册地址 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: sticker.locationPath), options: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: documensDirectory + sticker.locationPath), options: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 要分割的段落 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let clipNum = Int(max(round(Double(kongduan) * CMTimeGetSeconds(asset.duration) / videoTotalDuration), 1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                sticker.duration = CMTimeGetSeconds(asset.duration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "单个视频\(sticker.locationPath)时长::\(CMTimeGetSeconds(asset.duration)) ,clipNum is:\(clipNum)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                for clipindex in 0 ..< clipNum { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // deep copy sticker model 防止只有一个对象 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    let deepCopySticker: PQEditVisionTrackMaterialsModel? = sticker.copy() as? PQEditVisionTrackMaterialsModel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 设置循环模式和适配模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    deepCopySticker?.generateDefaultValues() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    deepCopySticker?.model_in = clipindex == 0 ? 0 : CMTimeGetSeconds(asset.duration) / Double(clipNum) * Double(clipindex) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    deepCopySticker?.out = (deepCopySticker?.model_in ?? 0) + CMTimeGetSeconds(asset.duration) / Double(clipNum) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (deepCopySticker?.model_in ?? 0) >= CMTimeGetSeconds(asset.duration) || (deepCopySticker?.out ?? 0) >= CMTimeGetSeconds(asset.duration) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        deepCopySticker?.model_in = CMTimeGetSeconds(asset.duration) - CMTimeGetSeconds(asset.duration) / Double(clipNum) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        deepCopySticker?.out = CMTimeGetSeconds(asset.duration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    BFLog(message: " crilp is in \(deepCopySticker?.model_in ?? 0) out \(deepCopySticker?.out ?? 0) 总时长\(CMTimeGetSeconds(asset.duration))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if deepCopySticker != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        stickers.append(deepCopySticker!) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if sticker.type == StickerType.IMAGE.rawValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                sticker.generateDefaultValues() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                stickers.append(sticker) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        kongduan = clipNumTep 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return stickers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 更新 playeTimeRange & finallyUserAudioTime 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func updateTimeInfomation() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 四,背景音乐时长处理)计算最后使用的音频时长, 如果不用拼接音频时长度是卡点的倒数第二位时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        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(Float64(finallyStuckPoints.first ?? 0) * Float64(BASE_FILTER_TIMESCALE)), timescale: BASE_FILTER_TIMESCALE), end: CMTime(value: CMTimeValue(Float64(finallyStuckPoints.last ?? 0) * Float64(BASE_FILTER_TIMESCALE)), timescale: BASE_FILTER_TIMESCALE)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (index, usePoint) in finallyStuckPoints.enumerated() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(message: "测试人员最后使用的卡点信息 \(index) : \(usePoint)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(message: "计算后给播放器使用的开始:\(CMTimeGetSeconds(playeTimeRange.start)) 结束时间\(CMTimeGetSeconds(playeTimeRange.end)) 播放总时长:\(CMTimeGetSeconds(playeTimeRange.end) - CMTimeGetSeconds(playeTimeRange.start))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 创建sticker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Parameters: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ///   - sections: 项目所有段落数据信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ///   - inputSize: 画布大小 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Returns: filters 数据 播放器可直接使用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func createStickers(sections: List<PQEditSectionModel>, inputSize _: CGSize = .zero, model: createStickersModel = .createStickersModelPoint) -> [PQEditVisionTrackMaterialsModel] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 推荐卡点数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let beginDecoderTime: TimeInterval = Date().timeIntervalSince1970 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 保存滤镜对象数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var stickers: Array = Array<PQEditVisionTrackMaterialsModel>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for section in sections { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if section.sectionType == "normal" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 第一种情况:全是图片,三种模式都进行图片回环播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials(type: "video").count == 0, section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials(type: "image").count > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    for (index, _) in finallyStuckPoints.enumerated() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        let sticker: PQEditVisionTrackMaterialsModel = section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials()[index % section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials().count] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        BFLog(message: "stickerlocationPath sticker : \(sticker.locationPath)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        let deepCopySticker: PQEditVisionTrackMaterialsModel? = sticker.copy() as? PQEditVisionTrackMaterialsModel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if deepCopySticker!.type == StickerType.IMAGE.rawValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if index + 1 < finallyStuckPoints.count { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                deepCopySticker!.timelineIn = Float64(String(format: "%.6f", finallyStuckPoints[index])) ?? 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                deepCopySticker!.timelineOut = Float64(String(format: "%.6f", finallyStuckPoints[index + 1])) ?? 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                if deepCopySticker != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    deepCopySticker?.generateDefaultValues() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    stickers.append(deepCopySticker!) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    BFLog(1, message: "测试人员index is 纯图片 timelineOut:\(deepCopySticker!.timelineIn) timelineOut :\(deepCopySticker!.timelineOut)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { // 第二种情况:视频 + 图片情况、视频要分段+图片按卡点时长创建 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if model == .createStickersModelPoint { // 跳跃卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 第二种情况:有视频要进行分割 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        let clipFilters = clipVideoMerage(section: section, stuckPoints: finallyStuckPoints) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 数据不一致时要对数据进行二次处理,不是最好方案 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if clipFilters.count > finallyStuckPoints.count - 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            clipPoint(clipNum: clipFilters.count - finallyStuckPoints.count, oldPoints: finallyStuckPoints) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } else if clipFilters.count < finallyStuckPoints.count - 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            while clipFilters.count < finallyStuckPoints.count - 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                finallyStuckPoints.removeLast() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 更新最终使用值 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        updateTimeInfomation() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // stikcer段数比clipFilters 数 大于 1才是正确的 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        BFLog(message: "stikcer count is\(clipFilters.count) finallyStuckPoints count is\(finallyStuckPoints.count)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        for (index, point) in finallyStuckPoints.enumerated() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            BFLog(message: "aaaaaindexindeindexxindexindexindex \(index) \(point)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if index + 1 < finallyStuckPoints.count, index < clipFilters.count { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                BFLog(message: "bbbbbindexindeindexxindexindexindex \(index) \(point)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                let sticker: PQEditVisionTrackMaterialsModel = clipFilters[index] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                if sticker.type == StickerType.IMAGE.rawValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    BFLog(message: "当前是image filter !!!!!") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                sticker.timelineIn = Float64(String(format: "%.6f", finallyStuckPoints[index])) ?? 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                sticker.timelineOut = Float64(String(format: "%.6f", finallyStuckPoints[index + 1])) ?? 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // 卡点的时间 >  in out 值 这里就会出现鬼畜效果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                let timelineInterval = sticker.timelineOut - sticker.timelineIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                let inOutInterval = sticker.out - sticker.model_in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                if timelineInterval > inOutInterval { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    BFLog(message: "实际要显示卡点时长\(timelineInterval) 素材裁剪时长:\(inOutInterval)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    sticker.out = sticker.model_in + timelineInterval 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    // 下面只是 LOG 方便查问题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    let stickerInOut = sticker.out - sticker.model_in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    let stickerTimelineInOut = sticker.timelineOut - sticker.timelineIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    if stickerInOut != stickerTimelineInOut { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        BFLog(message: "sticker.timelineIn \(sticker.timelineIn) stickerTimelineInOut is\(stickerTimelineInOut) stickerInOut is\(stickerInOut) 相差\(stickerTimelineInOut - stickerInOut)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // out > 素材的总时长in out 进行前移操作 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                let offsetAssetDuration = sticker.out - sticker.duration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                if offsetAssetDuration > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    sticker.model_in = sticker.model_in - offsetAssetDuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    sticker.out = sticker.out - offsetAssetDuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                print("跳跃卡点测试人员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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } else if model == .createStickersModelOnlyMusic || model == .createStickersModelSpeed { // 仅音乐 和 快慢速卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        BFLog(message: "stuckPoints count is \(finallyStuckPoints.count)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        for sticker in section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if sticker.type == StickerType.VIDEO.rawValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // MARK: SanW-2021.11.15-不再导出到沙盒,直接使用本地相册地址 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: sticker.locationPath), options: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: documensDirectory + sticker.locationPath), options: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                BFLog(message: "单个视频\(sticker.locationPath)时长::\(CMTimeGetSeconds(asset.duration)) ,clipNum is:\(sticker.clipCount)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                var lastOutTime: Float64 = 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                for _ in 1 ... sticker.clipCount { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    // deep copy sticker model 防止只有一个对象 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    let deepCopyStickerDecoderTime: TimeInterval = Date().timeIntervalSince1970 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    let deepCopySticker: PQEditVisionTrackMaterialsModel? = sticker.copy() as? PQEditVisionTrackMaterialsModel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    BFLog(message: "生成stickers 总时长为 aaa\(Date().timeIntervalSince1970 - deepCopyStickerDecoderTime)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    // 设置循环模式和适配模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    deepCopySticker?.generateDefaultValues() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    deepCopySticker?.materialDurationFit?.fitType = adapterMode.staticFrame.rawValue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    // 当前分段的速度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    var tempSpeed: Float = 1.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    if model == .createStickersModelSpeed { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        tempSpeed = (stickers.count % 2) == 0 ? modelSpeed_maxSpeed : modelSpeed_minSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    if stickers.count + 1 < finallyStuckPoints.count { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        deepCopySticker?.speedRate = tempSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        // 定义临时使用的变量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        // 素材显示的开始时间和结束时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        let tempTimelineIn: Float64 = Float64(String(format: "%.6f", finallyStuckPoints[stickers.count])) ?? 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        let timelineOut: Float64 = Float64(String(format: "%.6f", finallyStuckPoints[stickers.count + 1])) ?? 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        // 素材分割的开始时间和结束时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        let tempModel_In = lastOutTime 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        var tempOut = lastOutTime + Float64(tempSpeed) * (timelineOut - tempTimelineIn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        // 处理最后一点视频素材不够卡点时长 e.g. 0.3 卡点时长0.5 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        if tempOut > CMTimeGetSeconds(asset.duration) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            // 最后一点素材时长 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            let lastAssetDuration = CMTimeGetSeconds(asset.duration) - lastOutTime 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            let pointDuration = timelineOut - tempTimelineIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            // 要适应到卡点内要使用的C速度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            let needSpeed = lastAssetDuration / pointDuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            // 当前卡点段为快速 快速都用 C 速处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            BFLog(message: "最后一点视频素材不够卡点时长要做变速C处理 差\(tempOut - CMTimeGetSeconds(asset.duration)) \(needSpeed)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            deepCopySticker?.speedRate = Float(needSpeed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            tempOut = CMTimeGetSeconds(asset.duration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            if needSpeed == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                BFLog(message: "needSpeed is 0 出现在时长和卡点正好相等") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        deepCopySticker?.model_in = tempModel_In 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        deepCopySticker?.out = tempOut 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        deepCopySticker?.timelineIn = tempTimelineIn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        deepCopySticker?.timelineOut = timelineOut 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        lastOutTime = deepCopySticker?.out ?? 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    BFLog(message: "测试人员创建 sticker  crilp is in 视频 \(String(format: "%.6f", deepCopySticker?.model_in ?? 0))  out  \(String(format: "%.6f", deepCopySticker?.out ?? 0)) ,分段素材时长:\(String(format: "%.6f", (deepCopySticker?.out ?? 0) - (deepCopySticker?.model_in ?? 0))) ,分段显示时长:\(String(format: "%.6f", (deepCopySticker?.timelineOut ?? 0) - (deepCopySticker?.timelineIn ?? 0))), 视频素材原时长\(CMTimeGetSeconds(asset.duration)) clipNum \(sticker.clipCount) timelineIN: \(String(format: "%.6f", deepCopySticker?.timelineIn ?? 0)) timelineOUT:\(String(format: "%.6f", deepCopySticker?.timelineOut ?? 0)) speedRate:\(deepCopySticker?.speedRate ?? 0.0)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    if deepCopySticker != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        if deepCopySticker?.timelineIn == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            BFLog(message: "timelineIn data is error!!!") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        stickers.append(deepCopySticker!) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } else if sticker.type == StickerType.IMAGE.rawValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                if stickers.count + 1 >= finallyStuckPoints.count { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    BFLog(message: "数据出现错误!!!查正") // 155.318253 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                sticker.generateDefaultValues() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                sticker.timelineIn = Float64(String(format: "%.6f", finallyStuckPoints[stickers.count])) ?? 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                sticker.timelineOut = Float64(String(format: "%.6f", finallyStuckPoints[stickers.count + 1])) ?? 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                stickers.append(sticker) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                BFLog(message: "测试人员创建 sticker  crilp is in 图片 \(String(format: "%.6f", sticker.model_in))  out  \(String(format: "%.6f", sticker.out)) ,分段素材时长:\(String(format: "%.6f", sticker.out - sticker.model_in)) ,分段显示时长:\(String(format: "%.6f", sticker.timelineOut - sticker.timelineIn)),   timelineIN: \(String(format: "%.6f", sticker.timelineIn)) timelineOUT:\(String(format: "%.6f", sticker.timelineOut)) speedRate:\(sticker.speedRate)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(message: "生成stickers 总时长为:\(Date().timeIntervalSince1970 - beginDecoderTime)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return stickers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 根据档位取最后使用的卡点数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Parameter seed: 档位速度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Returns: 最后使用的卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func getUsedStuckPoint(seed: Int) -> [Float] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if !(stuckPointMusicData!.rhythmSdata.count > 0 && stuckPointMusicData!.rhythmSdata[0].pointTimes.count > 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 推荐卡点数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var stuckPoints: Array = Array<Float>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var pointsTemp = Array<Float>.init() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 最后一个卡点时间(原推荐卡点的倒数第二位时间) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let lastPoint = stuckPointMusicData!.rhythmSdata[0].pointTimes[stuckPointMusicData!.rhythmSdata[0].pointTimes.count - 2] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (index, dunshu) in stuckPointMusicData!.rhythmSdata[0].pointTimes.enumerated() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if dunshu >= Int64((stuckPointMusicData?.startTime ?? 0) * Float64(BASE_FILTER_TIMESCALE)), dunshu < lastPoint { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let savePointStr = String(format: "%.6f", Float(dunshu) / Float(BASE_FILTER_TIMESCALE)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "原所有卡点数:\(index) \(savePointStr)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                pointsTemp.append(Float(savePointStr) ?? 0.0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         一,快慢速模式下取卡点 2 3 4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         二,跳跃卡点模式下根据不同速度 取卡点 1,2,3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         快节奏为选中区域的所有点位,即0,1,2,3,4 5 6 7 8 9 10 …… 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         适中为每两个点位取一个,即0,2,4,6…… 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         慢节奏为每三个点位取一个,即0,3,6,9…… 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 不丢 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if seed == 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            stuckPoints = pointsTemp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 根据档位要丢 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for (index, point) in pointsTemp.enumerated() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if index % seed == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    stuckPoints.append(point) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        for point in stuckPoints { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            BFLog(message: "没有 start end 计算后的卡点数\(point)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 若音乐起点至第一个卡点点位之间时长t0<0.3时,此段时长与下一个点位时长合并,故第一段卡点部分时长为t0+d 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        while (stuckPoints.first ?? 0.0) - Float(stuckPointMusicData?.startTime ?? 0) < 0.3 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if stuckPoints.first != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                stuckPoints.removeFirst() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        stuckPoints.insert(Float(stuckPointMusicData?.startTime ?? 0), at: 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        for point in stuckPoints { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            BFLog(message: "有 start end 计算后的卡点数\(point)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(message: "处理节奏后 stuckPoints count is \(stuckPoints.count) seed \(seed), start time:\(stuckPoints.first ?? 0.0),end time:\(stuckPoints.last ?? 0.0) 总时长为:\((stuckPoints.last ?? 0.0) - (stuckPoints.first ?? 0.0))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return stuckPoints 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func clipPoint(clipNum: Int, oldPoints: [Float]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(message: "拼接卡点数:\(clipNum)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if clipNum < 0 || oldPoints.count < 2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BFLog(message: "clipNum is error!!!! \(clipNum)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 如果是第一次拼接先补第0位 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if finallyStuckPoints.count == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            finallyStuckPoints.append(stuckPointsTemp.first ?? 0.0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for i in finallyStuckPoints.count ... clipNum + finallyStuckPoints.count { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (i % (oldPoints.count - 1)) != 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let value = String(format: "%.6f", finallyStuckPoints[i - 1] + oldPoints[((i - 1) % (oldPoints.count - 1)) + 1] - oldPoints[((i - 2) % (oldPoints.count - 1)) + 1]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                finallyStuckPoints.append(Float(value) ?? 0.0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let value = String(format: "%.6f", finallyStuckPoints[i - 1] + oldPoints[1] - oldPoints[0]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                finallyStuckPoints.append(Float(value) ?? 0.0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 根据不同模式model,    maxSpeed ,minSpeed,      self?.stuckPointMusicData?.speed 档位,生成音乐时长和最终使用的卡点信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func dealParameter(model: createStickersModel) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 清空上一次使用的卡点数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        finallyStuckPoints.removeAll() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 已经取到的视频素材总长度,用于和原视频素材时长做对比,不够多加一个点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var useAssestDuration: Float = 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        switch model { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case .createStickersModelPoint: // 跳跃卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            stuckPointsTemp = getUsedStuckPoint(seed: stuckPointMusicData?.speed ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 要拼接的段数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var clipNum: Int = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var i: Int = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // L/(n+1)  L -原视觉素材总时长  n-抛留倍数  lastJumpSpeedSelectIndex 是位置 对应的值要+1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 根据公式计划出的总时长 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let jumpTime = Float(selectedTotalDuration) / Float(modelPoint_speed + 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 只有图片素材时会为0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if jumpTime > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                while useAssestDuration < Float(jumpTime) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 回环从头取\ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if i + 1 >= stuckPointsTemp.count { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        i = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 快速段 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    let LA = (stuckPointsTemp[i + 1] - stuckPointsTemp[i]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    useAssestDuration = useAssestDuration + Float(LA) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    i = i + 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    clipNum = clipNum + 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 拼接要使用的卡点信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                clipPoint(clipNum: clipNum, oldPoints: stuckPointsTemp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case .createStickersModelSpeed, .createStickersModelOnlyMusic: // 快慢速 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 快慢速  (2:快节奏,3:适中,4:慢节奏) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var tempMaxSpeed: Float = 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var tempMinSpeed: Float = 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if model == .createStickersModelSpeed { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 改变速率,.只有快慢速且非只有图片素材时自动+1处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if model == .createStickersModelSpeed, selectedDataCount != selectedImageDataCount { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    stuckPointsTemp = getUsedStuckPoint(seed: (stuckPointMusicData?.speed ?? 0) + 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    stuckPointsTemp = getUsedStuckPoint(seed: stuckPointMusicData?.speed ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                tempMaxSpeed = modelSpeed_maxSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                tempMinSpeed = modelSpeed_minSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                stuckPointsTemp = getUsedStuckPoint(seed: stuckPointMusicData?.speed ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             - 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快速为:\(tempMaxSpeed) By慢速为:\(tempMinSpeed) 档位 N为:\(stuckPointMusicData?.speed ?? 0)  使用的卡点总数:\(stuckPointsTemp.count)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 使用新方法取使用的卡点数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for section in projectModel.sData?.sections ?? List() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if section.sectionType == "normal" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    for sticker in section.sectionTimeline!.visionTrack!.getEnableVisionTrackMaterials() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if sticker.type == StickerType.VIDEO.rawValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // MARK: SanW-2021.11.15-不再导出到沙盒,直接使用本地相册地址 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: sticker.locationPath), options: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                            let asset: AVURLAsset = AVURLAsset(url: URL(fileURLWithPath: documensDirectory + sticker.locationPath), options: nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            let assetDuration = Float(CMTimeGetSeconds(asset.duration)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            BFLog(message: "输入素材时长 \(assetDuration)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if finallyStuckPoints.count == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                finallyStuckPoints.append(stuckPointsTemp[0]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            var j = finallyStuckPoints.count 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 添加卡点的段数 用于判断当前卡点是快/慢速 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            var pointCount: Int = 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 已经取到的视频素材总长度,用于和原视频素材时长做对比,不够多加一个卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            var useAssestDurationTemp: Float = 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            while useAssestDurationTemp < assetDuration { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // 当前段的应该使用的速度 A/B 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                let useSpeed = (pointCount % 2 != 0) ? tempMaxSpeed : tempMinSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // 计算卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // 要添加的卡点数值 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                var sub: Float = 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                if stuckPointsTemp.count > 2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    if ((j - 1) % (stuckPointsTemp.count - 1)) != 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        sub = stuckPointsTemp[((j - 1) % (stuckPointsTemp.count - 1)) + 1] - stuckPointsTemp[(j - 1) % (stuckPointsTemp.count - 1)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        sub = stuckPointsTemp[1] - stuckPointsTemp[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    finallyStuckPoints.append(finallyStuckPoints[j - 1] + sub) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    j += 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                useAssestDurationTemp += sub * useSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                if useAssestDurationTemp > assetDuration { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    useAssestDurationTemp -= sub * useSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                pointCount += 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                BFLog(2, message: "finallyStuckPoints last ;\((finallyStuckPoints.last ?? 0.0) - (finallyStuckPoints.first ?? 0.0)), tmp:\(useAssestDurationTemp)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 2拼接要使用的卡点信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            sticker.clipCount = pointCount 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if stuckPointsTemp.count < 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // todo 和产品沟通提示 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                BFLog(message: "卡点数据有错误!!!") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            BFLog(message: "finallyStuckPoints\(finallyStuckPoints)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 3,多补一个卡点 做 C级 速处理,要根据条件不满足 要删除最后一位, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if useAssestDurationTemp < assetDuration { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 // 下一个卡的的速度性质快、慢,e.g. sticker.clipCount = 5时 tempSpeed 应该是慢速。下面计算正确。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 var tempSpeed: Float = 1.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 if model == .createStickersModelSpeed { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                     tempSpeed = (sticker.clipCount) % 2 != 0 ? modelSpeed_maxSpeed : modelSpeed_minSpeed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 // 最后一点素材时长 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 let lastAssetDuration = Float(CMTimeGetSeconds(asset.duration)) - useAssestDurationTemp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 let lastPointIndex = (sticker.clipCount % stuckPointsTemp.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 // 两个卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 let a: Float = stuckPointsTemp[lastPointIndex] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 var b: Float = 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 if lastPointIndex + 1 < stuckPointsTemp.count { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                     b = stuckPointsTemp[lastPointIndex + 1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                     let pointDuration = b - a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                     // 要适应到卡点内要使用的C速度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                     let needSpeed = lastAssetDuration / pointDuration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                     // 当前卡点段为快速 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                     if tempSpeed >= 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 //                                        if needSpeed < 0.4 * tempSpeed { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 //                                            BFLog(message: "条件不满足不用补位 删除多加的一位") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 //                                            finallyStuckPoints.removeLast() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 //                                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                     } else { // 当前卡点段为慢速 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                         if needSpeed >= 0.4 * tempSpeed && needSpeed >= 0.2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                             // 查找使用的最后一个卡点在原数组中的位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                             BFLog(message: "条件不满足不用补位 删除多加的一位") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                             finallyStuckPoints.removeLast() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // 出现在第一个卡点X 倍速 > 原素材 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                finallyStuckPoints.removeLast() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 拼接图片所使用的时长.选择一组图片 按图片数量计算卡点的总时长 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if selectedImageDataCount > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            clipPoint(clipNum: selectedImageDataCount - 1, oldPoints: stuckPointsTemp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 全是图片时数组里放着的一定都是图片的使用的卡点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 定义一次循环的总时长 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var oneSelectImageDuration: Float = 0.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if selectedDataCount == selectedImageDataCount { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            oneSelectImageDuration = (finallyStuckPoints.last ?? 0) - (finallyStuckPoints.first ?? 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 3)素材全是图片处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if selectedDataCount == selectedImageDataCount { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // lastCyclesSelectIndex != -1 已经设置过循环次数 应该是手动设置的值 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if lastCyclesSelectIndex != -1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 纯图片时 已经默认添加一次循环 所以要用lastCyclesSelectIndex - 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if lastCyclesSelectIndex != 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    clipPoint(clipNum: selectedImageDataCount * lastCyclesSelectIndex - 1, oldPoints: stuckPointsTemp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if oneSelectImageDuration < 10 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    lastCyclesSelectIndex = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    while oneSelectImageDuration < 10 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 不够10S 时 一次加图片数量的卡点数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        clipPoint(clipNum: selectedImageDataCount - 1, oldPoints: stuckPointsTemp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        oneSelectImageDuration = Float((finallyStuckPoints.last ?? 0) - (finallyStuckPoints.first ?? 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        lastCyclesSelectIndex = lastCyclesSelectIndex + 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    speedSettingView.setSelectItem(index: lastCyclesSelectIndex, isSettingPlayer: false, enableInsert: true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    lastCyclesSelectIndex = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if finallyStuckPoints.count < 2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            cShowHUB(superView: nil, msg: "视频资源导入失败,请重新选择!!") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            exportResourceFailed() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 设置速度选择的位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if speedSettingView.viewType == 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speedSettingView.setSelectItem(index: lastSpeedSelectIndex, isSettingPlayer: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if speedSettingView.viewType == 2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            speedSettingView.setSelectItem(index: lastJumpSpeedSelectIndex, isSettingPlayer: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if speedSettingView.viewType == 3 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if lastCyclesSelectIndex != -1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                speedSettingView.setSelectItem(index: lastCyclesSelectIndex, isSettingPlayer: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                speedSettingView.setSelectItem(index: 0, isSettingPlayer: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        updateTimeInfomation() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// MARK: - 同步/下载素材相关 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/// 同步/下载素材相关 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+extension PQStuckPointEditerController { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 同步音乐相关数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Returns: <#description#> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func synchroMusicInfoData(resetSelectIndex: Bool = true) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (stuckPointMusicData?.rhythmSdata.count ?? 0) <= 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            synchroMarskView.show() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            PQStuckPointViewModel.stuckPointMusicDetailData(musicId: stuckPointMusicData?.musicId ?? "", originType: stuckPointMusicData?.originType ?? 1) { [weak self] newMusicData, _ in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if newMusicData != nil, (newMusicData?.rhythmSdata.count ?? 0) > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.isStuckPointDataSuccess = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.stuckPointMusicData?.rhythmSdata = newMusicData?.rhythmSdata ?? [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.stuckPointMusicData?.startTime = newMusicData?.startTime ?? 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.stuckPointMusicData?.endTime = newMusicData?.endTime ?? 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if newMusicData?.speed != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.stuckPointMusicData?.speed = newMusicData?.speed ?? 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if self?.stuckPointMusicData?.localPath == nil || (self?.stuckPointMusicData?.localPath?.count ?? 0) > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        PQDownloadManager.downLoadFile(url: self?.stuckPointMusicData?.musicPath ?? "") { [weak self] filePath, error in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if error == nil, filePath != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                self?.isSynchroMusicInfoSuccess = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                self?.stuckPointMusicData?.localPath = filePath?.replacingOccurrences(of: documensDirectory, with: "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // 处理所有数据完成 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                self?.dealWithDataSuccess(resetSelectIndex: resetSelectIndex) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            self?.synchroMarskView.removeMarskView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.isSynchroMusicInfoSuccess = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 处理所有数据完成 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.dealWithDataSuccess(resetSelectIndex: resetSelectIndex) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 添加子视图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.addSubViews() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.synchroMarskView.removeMarskView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    cShowHUB(superView: nil, msg: "音乐信息加载失败,请重新选择音乐") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.navigationController?.popViewController(animated: true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if stuckPointMusicData?.localPath == nil || (stuckPointMusicData?.localPath?.count ?? 0) > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            synchroMarskView.show() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            isStuckPointDataSuccess = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            PQDownloadManager.downLoadFile(url: stuckPointMusicData?.musicPath ?? "") { [weak self] filePath, error in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if error == nil, filePath != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.isSynchroMusicInfoSuccess = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.stuckPointMusicData?.localPath = filePath?.replacingOccurrences(of: documensDirectory, with: "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 处理所有数据完成 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.dealWithDataSuccess(resetSelectIndex: resetSelectIndex) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.synchroMarskView.removeMarskView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    cShowHUB(superView: nil, msg: "音乐信息加载失败,请重新选择音乐") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                    BFUploadRemindView.showUploadRemindView(title: nil, attributedTitle: NSAttributedString(string: "加载音乐失败,请重新选择音乐"), summary: "", confirmTitle: nil) { [weak self] _, _ in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        self?.navigationController?.popViewController(animated: true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            isStuckPointDataSuccess = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 处理所有数据完成 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            dealWithDataSuccess(resetSelectIndex: resetSelectIndex) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 导出相册数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Returns: <#description#> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func exportPhotoData() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 取消所有的导出 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        PQSingletoMemoryUtil.shared.allExportSession.forEach { _, exportSession in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            exportSession.cancelExport() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var isHaveVideo: Bool = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        var failedExprot: Bool = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if selectedMetarialData != nil, (selectedMetarialData?.count ?? 0) > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if synchroMarskView.superview == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                UIApplication.shared.keyWindow?.addSubview(synchroMarskView) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let dispatchGroup = DispatchGroup() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for photo in selectedMetarialData! { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if photo.asset != nil, photo.asset?.mediaType == .video { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if !isHaveVideo { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        isHaveVideo = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    dispatchGroup.enter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    PQPHAssetVideoParaseUtil.parasToAVAsset(phAsset: photo.asset!) { avAsset, _, _, _ in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if avAsset is AVURLAsset { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 创建目录 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            let fileName = (avAsset as! AVURLAsset).url.absoluteString 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            BFLog(message: "video  fileName is\(fileName)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            let tempPhoto = self.selectedMetarialData?.first(where: { material in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                material.asset == photo.asset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// MARK: SanW-2021.11.15-不在导出到沙盒,直接用本地地址 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            tempPhoto?.locationPath = fileName.replacingOccurrences(of: "file://", with: "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            dispatchGroup.leave() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                            if fileName.count > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                createDirectory(path: photoLibraryDirectory) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                let outFilePath = photoLibraryDirectory + fileName.md5 + ".mp4" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                // 文件存在先删除老文件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                if FileManager.default.fileExists(atPath: outFilePath) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                    do { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                        try FileManager.default.removeItem(at: NSURL.fileURL(withPath: outFilePath)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                    } catch { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                        BFLog(message: "导出相册视频-error == \(error)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                let curr = Date() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                let assetResources = PHAssetResource.assetResources(for: photo.asset!) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                if let rsc = assetResources.first(where: { res in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                    res.type == .video  || res.type == .pairedVideo 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                }) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                    PHAssetResourceManager.default().writeData(for: rsc, toFile: URL(fileURLWithPath: outFilePath), options: nil) { error in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                        if error == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                            BFLog(message: "导出视频相exportAsynchronously \(String(describing: outFilePath)) \(Date().timeIntervalSince(curr))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                            tempPhoto?.locationPath = outFilePath.replacingOccurrences(of: documensDirectory, with: "") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                        }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                            failedExprot = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                            BFLog(message: "导出视频相exportAsynchro faile") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                        dispatchGroup.leave() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                }else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                    BFLog(message: "导出视频相exportAsynchro faile") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                    dispatchGroup.leave() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            dispatchGroup.notify(queue: DispatchQueue.main) { [weak self] in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if failedExprot { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    cShowHUB(superView: nil, msg: "视频导入失败,请返回重试") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.exportResourceFailed() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self?.isExportVideosSuccess = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "所有相册视频导出成功") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 处理所有数据完成 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if isHaveVideo { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self?.dealWithDataSuccess() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 只有图片 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if !isHaveVideo { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                isExportVideosSuccess = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "所有相册视频导出成功") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dealWithDataSuccess() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func exportResourceFailed() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        DispatchQueue.main.async { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.synchroMarskView.removeMarskView() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.navigationController?.popViewController(animated: true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// 处理所有数据完成 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// - Returns: <#description#> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// resetSelectIndex : 是否重置用户选择的速度设置,在编辑界面切换音乐时不重置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    func dealWithDataSuccess(resetSelectIndex: Bool = true) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(message: "三组参数:\(isSynchroMusicInfoSuccess)  \(isStuckPointDataSuccess) \(isExportVideosSuccess)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if !isSynchroMusicInfoSuccess || !isStuckPointDataSuccess || !isExportVideosSuccess { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        createPorjectData() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BFLog(1, message: "界面编辑界面时参数 选择素材时长:\(selectedTotalDuration) 选择素材总数:\(selectedDataCount) 选择图片总数\(selectedImageDataCount) 再创建类型:\(String(describing: reCreateVideoData?.rhythmMode))") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if resetSelectIndex { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 1 生成默认参数值 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             - 当素材总时长∈[0-6)s 时,提示推荐仅配乐模式 or 快慢速模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             - 当素材总时长∈[6-80)s 时,卡点抛留倍数为1x 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             - 当素材总时长∈[80,120)s 时,卡点抛留倍数为2x 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             - 当素材总时长∈[120,160)s 时,卡点抛留倍数为3x 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             - 当素材总时长∈[160,200)s 时,卡点抛留倍数为4x 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             - 当素材总时长∈[200,240)s 时,卡点抛留倍数为5x 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             - 当素材总时长∈[240,∞)s 时,卡点抛留倍数为5x 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 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) || selectedTotalDuration >= 240 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lastJumpSpeedSelectIndex = 4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            /* 默认进入快慢速模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             - 当素材总时长∈[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 || selectedTotalDuration > 144 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lastSpeedSelectIndex = 5 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if selectedTotalDuration >= 70, selectedTotalDuration < 120 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lastSpeedSelectIndex = 4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if selectedTotalDuration >= 56, selectedTotalDuration < 70 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lastSpeedSelectIndex = 3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if selectedTotalDuration >= 17.5, selectedTotalDuration < 56 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lastSpeedSelectIndex = 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if selectedTotalDuration >= 10.5, selectedTotalDuration < 17.5 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lastSpeedSelectIndex = 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if selectedTotalDuration > 0, selectedTotalDuration < 10.5 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lastSpeedSelectIndex = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 如果是再创作进来的按原视频的模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if reCreateVideoData != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "是再创作进来的 \(reCreateVideoData!.rhythmMode)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                switch reCreateVideoData!.rhythmMode { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                case 1: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    editModelClick(sender: jumpPointBtn, reportLog: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                case 2: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    editModelClick(sender: speedStuckBtn, reportLog: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                case 3: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    editModelClick(sender: onlyMusicBtn, reportLog: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                default: break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             // 跳跃卡点不可用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             if selectedTotalDuration < 6 && selectedDataCount != selectedImageDataCount { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let styleColor = UIColor.hexColor(hexadecimal: BFConfig.shared.styleColor.rawValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                jumpPointBtn.setTitleColor(UIColor.init(red: styleColor.rgbaf[0], green: styleColor.rgbaf[1], blue: styleColor.rgbaf[2], alpha: 0.3), for: .selected) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let pointEditNamalBackgroundColor = BFConfig.shared.pointEditNamalBackgroundColor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                jumpPointBtn.backgroundColor = UIColor.init(red: pointEditNamalBackgroundColor.rgbaf[0], green: pointEditNamalBackgroundColor.rgbaf[1], blue: pointEditNamalBackgroundColor.rgbaf[2], alpha: 0.3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             文档规则 https://w42nne6hzg.feishu.cn/docs/doccnQZm1uCfkU4QtJb5fLxYk4d# 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 2,根据所选择所有素材时长进入默认模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 全是图片 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if selectedDataCount == selectedImageDataCount { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BFLog(message: "全是图片 \(selectedDataCount) \(selectedImageDataCount)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 默认进入跳跃卡点模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                editModelClick(sender: jumpPointBtn, reportLog: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 默认进入快慢速模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if selectedTotalDuration > 0, selectedTotalDuration <= 144 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    editModelClick(sender: speedStuckBtn, reportLog: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 默认进入跳跃卡点模式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    editModelClick(sender: jumpPointBtn, reportLog: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            editModelClick(sender: lastEditModelBtn ?? jumpPointBtn, reportLog: false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |