123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- //
- // PQVoiceModel.swift
- // PQSpeed
- //
- // Created by ak on 2020/8/18.
- // Copyright © 2020 BytesFlow. All rights reserved.
- //
- import Foundation
- enum voiceStatue: Int {
- case isLoading = 0 // 加载中
- case isPlaying = 1 // 播放中
- case isNormal = 2 // 正常状态
- case isSelected = 3 // 选中状态,有红框 字红色 ,别的都没有
- }
- class PQVoiceModel: NSObject, NSCopying {
- public var name: String = ""
- // 对应接口的 KEY
- public var voice: String = ""
- public var cateId: Int = 0
- // 性别
- public var gender: Int = 0
- public var avatarUrl: String = ""
- public var channel: String = "aliyun" // aliyun , azure
- // 是否为精品
- public var qualityFlag: Int = 0
- // 微软语音设置
- // public var azureStyleConfig: [PQAzureStyleModel] = Array()
- // 声音文件沙盒位置 是 URI
- public var wavFilePath: String!
- // 是否收藏
- public var isFavorite: Bool = false
- // 是否在加载状态 是否在播放状态f
- public var voiceStatue: voiceStatue = .isNormal
- // 收藏 ID
- public var favoriteId: Int = 0
- public var speedRate: Float = 1.0
- public var pitchRate: Float = 0
- public var azureStyle: String = "general"
- var isSelected: Bool = false // 是否被选中
- var isPlaying: Bool = false // 是否在播放
- var itemWidth: CGFloat = 0 // 元素宽度
- var materialUrl: String? // 播放地址
- var localPath: String? // 本地存储地址
- var duration: String? // 时长
- var currentTime: Float64? // 当前已播放时长
- var uniqueId: Int = 0 // 背景音乐ID
- var materialId: String? // 保存发音人后素材IDmaterialUrl
- var volume: Int = 0 // 0-100 素材音量
- var startTime: Float64 = 0 // 开始时间
- var endTime: Float64 = 0 // 结束时间
- var createTimestamp: Int64 = 0 // 创建时间
- var voiceType: String = VOICETYPT.PRODUCE.rawValue // 音乐类型
- var accompanimentPath: String? // 伴奏地址
- var musicId: String? // 音乐ID
- var musicLabels: String? // 标签
- var musicName: String? // 歌名
- var musicPath: String? // 音乐地址
- var musicSinger: String? // 歌手
- var originType: Int = 1 // 音乐来源: 1上传, 2爬取
- var sortNum: Int = 0 // 排序值
- var vodAccompanimentMediaId: String? // 伴奏vod mediaId
- var vodMusicMediaId: String? // 音乐vod mediaId
- // add by ak json 结构化数据传值使用
- var wavfileDuration: Float64 = 0
- var selectVoiceType: Int = 1 // 选择的声音类型,1:原声 ,2:背景声
- // 卡点视频-分类信息
- var tagsInfo: PQStuckPointMusicTagsModel?
- // 卡点视频-卡点时间数据
- var rhythmSdata: [PQStuckPointTimesModel] = Array<PQStuckPointTimesModel>.init()
- // 卡点视频-默认卡点速度(1:快节奏,2:适中,3:慢节奏) ,
- var speed: Int = 2
- // 卡点视频-卡点音乐入点
- var rhythmMusicIn: Float64 = 0
- // 卡点视频-卡点音乐出点
- var rhythmMusicOut: Float64 = 0
- // 卡点视频-源项目ID(从那个项目做同款)
- var originProjectId: String?
- func copy(with _: NSZone? = nil) -> Any {
- let voice = PQVoiceModel()
- voice.name = name
- voice.channel = channel
- voice.azureStyle = azureStyle
- voice.voice = self.voice
- voice.cateId = cateId
- voice.gender = gender
- voice.duration = duration
- voice.avatarUrl = avatarUrl
- voice.wavFilePath = wavFilePath
- voice.isFavorite = isFavorite
- voice.isSelected = isSelected
- voice.voiceStatue = voiceStatue
- voice.speedRate = speedRate
- voice.pitchRate = pitchRate
- voice.qualityFlag = qualityFlag
- // voice.azureStyleConfig = azureStyleConfig
- // ui 使用
- voice.isSelected = isSelected
- voice.isPlaying = isPlaying
- voice.itemWidth = itemWidth
- voice.materialUrl = materialUrl
- voice.localPath = localPath
- voice.duration = duration
- voice.currentTime = currentTime
- voice.uniqueId = uniqueId
- voice.volume = volume
- voice.startTime = startTime
- voice.endTime = endTime
- voice.createTimestamp = createTimestamp
- voice.voiceType = voiceType
- voice.accompanimentPath = accompanimentPath
- voice.musicId = musicId
- voice.musicLabels = musicLabels
- voice.musicName = musicName
- voice.musicPath = musicPath
- voice.musicSinger = musicSinger
- voice.originType = originType
- voice.sortNum = sortNum
- voice.vodAccompanimentMediaId = vodAccompanimentMediaId
- voice.vodMusicMediaId = vodMusicMediaId
- return voice
- }
- override init() {
- super.init()
- }
- init(jsonDict: [String: Any]) {
- super.init()
- if jsonDict.keys.contains("name"), "\(jsonDict["name"] ?? "")" != "<null>" {
- name = "\(jsonDict["name"] ?? "")"
- }
- if jsonDict.keys.contains("cateName"), "\(jsonDict["cateName"] ?? "")" != "<null>" {
- name = "\(jsonDict["cateName"] ?? "")"
- }
- if jsonDict.keys.contains("coverUrl") {
- avatarUrl = "\(jsonDict["coverUrl"] ?? "")"
- }
- if jsonDict.keys.contains("avatarUrl") {
- avatarUrl = "\(jsonDict["avatarUrl"] ?? "")"
- }
- if jsonDict.keys.contains("coverImgPath") {
- avatarUrl = "\(jsonDict["coverImgPath"] ?? "")"
- }
- if jsonDict.keys.contains("bgmId") {
- uniqueId = Int("\(jsonDict["bgmId"] ?? "0")") ?? 0
- }
- if jsonDict.keys.contains("gender") {
- gender = Int("\(jsonDict["gender"] ?? "0")") ?? 0
- }
- if jsonDict.keys.contains("id") {
- uniqueId = Int("\(jsonDict["id"] ?? "0")") ?? 0
- }
- if jsonDict.keys.contains("cateId") {
- cateId = Int("\(jsonDict["cateId"] ?? "0")") ?? 0
- }
- if jsonDict.keys.contains("cid") {
- cateId = Int("\(jsonDict["cid"] ?? "0")") ?? 0
- }
- if jsonDict.keys.contains("createTimestamp") {
- createTimestamp = Int64("\(jsonDict["createTimestamp"] ?? "0")") ?? 0
- }
- if name.count > 0 {
- itemWidth = sizeWithText(text: name, font: UIFont.systemFont(ofSize: 14, weight: .semibold), size: CGSize(width: cDefaultMargin * 10, height: cDefaultMargin * 4)).width + cDefaultMargin * 3
- }
- if jsonDict.keys.contains("favoriteStatus") {
- isFavorite = "\(jsonDict["favoriteStatus"] ?? "0")" == "1"
- }
- if jsonDict.keys.contains("materialUrl") {
- materialUrl = "\(jsonDict["materialUrl"] ?? "")"
- }
- if jsonDict.keys.contains("duration") {
- duration = "\(jsonDict["duration"] ?? "")"
- if (Float64("\(duration ?? "0")") ?? 0) < 1_000_000 {
- duration = "\(Float64("\(duration ?? "0")") ?? 0)"
- } else {
- duration = "\((Float64("\(duration ?? "0")") ?? 0) / 1_000_000)"
- }
- }
- if jsonDict.keys.contains("accompanimentPath") {
- accompanimentPath = "\(jsonDict["accompanimentPath"] ?? "")"
- }
- if jsonDict.keys.contains("musicId") {
- musicId = "\(jsonDict["musicId"] ?? "")"
- }
- if jsonDict.keys.contains("musicLabels") {
- musicLabels = "\(jsonDict["musicLabels"] ?? "")"
- }
- if jsonDict.keys.contains("musicName") {
- musicName = "\(jsonDict["musicName"] ?? "")"
- }
- if jsonDict.keys.contains("musicPath") {
- musicPath = "\(jsonDict["musicPath"] ?? "")"
- }
- if jsonDict.keys.contains("coverMusicPath") {
- musicPath = "\(jsonDict["coverMusicPath"] ?? "")"
- }
- if jsonDict.keys.contains("musicSinger"), "\(jsonDict["musicSinger"] ?? "")" != "<null>" {
- musicSinger = "\(jsonDict["musicSinger"] ?? "")"
- }
- if jsonDict.keys.contains("author"), "\(jsonDict["author"] ?? "")" != "<null>" {
- musicSinger = "\(jsonDict["author"] ?? "")"
- }
- if jsonDict.keys.contains("originType") {
- originType = Int("\(jsonDict["originType"] ?? "0")") ?? 0
- }
- if jsonDict.keys.contains("sortNum") {
- sortNum = Int("\(jsonDict["sortNum"] ?? "0")") ?? 0
- }
- if jsonDict.keys.contains("vodAccompanimentMediaId") {
- vodAccompanimentMediaId = "\(jsonDict["vodAccompanimentMediaId"] ?? "")"
- }
- if jsonDict.keys.contains("vodMusicMediaId") {
- vodAccompanimentMediaId = "\(jsonDict["vodMusicMediaId"] ?? "")"
- }
- if jsonDict.keys.contains("musicTagInfos") {
- let musicTagInfos = jsonDict["musicTagInfos"] as? [String: Any]
- if musicTagInfos != nil, (musicTagInfos?.keys.count ?? 0) > 0 {
- tagsInfo = PQStuckPointMusicTagsModel(jsonDict: musicTagInfos!)
- }
- }
- if jsonDict.keys.contains("rhythmSdata"), "\(jsonDict["rhythmSdata"] ?? "")".count > 0, "\(jsonDict["rhythmSdata"] ?? "")" != "<null>" {
- let tempArr = jsonStringToArray(jsonString: "\(jsonDict["rhythmSdata"] ?? "")")
- if tempArr != nil, (tempArr?.count ?? 0) > 0 {
- tempArr?.forEach { sdata in
- let tempTimesModel: PQStuckPointTimesModel = PQStuckPointTimesModel(jsonDict: (sdata as? [String: Any]) ?? [:])
- rhythmSdata.append(tempTimesModel)
- }
- }
- }
- if jsonDict.keys.contains("suggestRhythmStart") {
- startTime = (Float64("\(jsonDict["suggestRhythmStart"] ?? "0")") ?? 0) / 1_000_000
- }
- if jsonDict.keys.contains("suggestRhythmEnd") {
- endTime = (Float64("\(jsonDict["suggestRhythmEnd"] ?? "0")") ?? 0) / 1_000_000
- }
- if jsonDict.keys.contains("speed"), "\(jsonDict["speed"] ?? "")" != "<null>" {
- speed = Int("\(jsonDict["speed"] ?? "2")") ?? 2
- }
- if jsonDict.keys.contains("rhythmMusicIn") {
- rhythmMusicIn = (Float64("\(jsonDict["rhythmMusicIn"] ?? "0")") ?? 0) / 1_000_000
- }
- if jsonDict.keys.contains("rhythmMusicOut") {
- rhythmMusicOut = (Float64("\(jsonDict["rhythmMusicOut"] ?? "0")") ?? 0) / 1_000_000
- }
- if jsonDict.keys.contains("originProjectId"), "\(jsonDict["originProjectId"] ?? "")" != "<null>" {
- originProjectId = "\(jsonDict["originProjectId"] ?? "")"
- }
- if jsonDict.keys.contains("projectId"), "\(jsonDict["projectId"] ?? "")" != "<null>" {
- originProjectId = "\(jsonDict["projectId"] ?? "")"
- }
- }
- /// 计算卡点时长 策略1 :
- /// - Parameters:
- /// - videoCount: 视频个数
- /// - imageCount: 图片个数
- /// - Returns: <#description#>
- func stuckPointCuttingTime(videoCount: Int, imageCount: Int, totalDuration: Float64) -> Float64 {
- if totalDuration <= 0 {
- return 0
- }
- // 默认比例
- let rate: Float64 = 1.5
- // 音乐最大时长
- let MaxM: Float64 = 40
- // 音乐最小时长
- let MinM: Float64 = 10
- // 视频个数
- // var V1: Float64 = Float64(videoCount)
- // 图片个数
- let V2: Float64 = Float64(imageCount)
- // 视频总时长
- let V1T: Float64 = totalDuration - V2
- // 推荐音乐时长
- var M: Float64 = endTime - startTime
- // 音频段数
- // let MC: Float64 = Float64(rhythmSdata.first?.pointTimes.count ?? 1)
- // 档位时长平均值
- // let MST: Float64 = (Float64(duration ?? "0") ?? 0) / MC
- // 从推荐点位开始speed*V2 的点位个数的时长/V2
- let startS: Float64 = Float64(Double(rhythmSdata.first?.pointTimes.first ?? 0) / 1_000_000.0)
- var endS: Float64 = Float64(Double(rhythmSdata.first?.pointTimes.last ?? 0) / 1_000_000.0)
- if V2 > 0, speed > 0, Float64(rhythmSdata.first?.pointTimes.count ?? 0) > (V2 * Float64(speed) + 2) {
- endS = Float64(Double(rhythmSdata.first?.pointTimes[Int(V2 * Float64(speed) + 2)] ?? 0) / 1_000_000.0)
- }
- let MST: Float64 = V2 <= 0 ? 0 : (endS - startS) / V2
- if (V2 * MST + V1T / 2) >= MaxM {
- M = MaxM
- } else if (V2 * MST + V1T / 2) >= MinM && MaxM > (V2 * MST + V1T / 2) {
- M = V2 * MST + V1T / 2
- } else if (V2 * MST + V1T / 2) <= MinM && (V2 * MST + V1T) * rate >= MinM {
- M = (V2 * MST + V1T) * rate
- } else if (V2 * MST + V1T) * rate < MinM {
- M = MinM
- }
- // 限制卡点时长最大值不能超过duration
- if (M + startTime) > endTime {
- M = endTime - startTime
- }else if (M + startTime) > (Float64(duration ?? "0") ?? 0) {
- M = (Float64(duration ?? "0") ?? 0) - startTime
- }
- BFLog(message: "计算当前裁剪时长:\(M),开始时间:\(startTime),结束时间:\(endTime),总时长:\(Float64(duration ?? "0") ?? 0)")
- return M
- }
- }
|