115 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Swift
		
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Swift
		
	
	
	
| //
 | ||
| //  IMHelperUtil.swift
 | ||
| //  Crush
 | ||
| //
 | ||
| //  Created by Leon on 2025/8/31.
 | ||
| //
 | ||
| 
 | ||
| import Foundation
 | ||
| 
 | ||
| // MARK: - IMHelperUtil
 | ||
| class IMHelperUtil{
 | ||
|     static func getAIIdByConversationId(_ conversationId: String?) -> Int?{
 | ||
|         guard let imConversationId = conversationId else{return nil}
 | ||
|         
 | ||
|         let stings = imConversationId.components(separatedBy: "|")
 | ||
|         guard let last = stings.last else{return nil}
 | ||
|         // let accountId = last
 | ||
|         let strings2 = last.components(separatedBy:"@")
 | ||
|         if let userIdStr = strings2.first {
 | ||
|             if let userid = Int(userIdStr) {
 | ||
|                 return userid
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         return nil
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| // MARK: - IMAudioHelper
 | ||
| class IMAudioHelper{
 | ||
|     /// 提取用于语音的文本(去除括号内容和 emoji)
 | ||
|     func extractTextForVoice(_ text: String) -> String {
 | ||
|         var result = text
 | ||
| 
 | ||
|         // 去除括号内容(中英文括号)
 | ||
|         let bracketPattern = #"\(.*?\)|(.*?)"#
 | ||
|         if let regex = try? NSRegularExpression(pattern: bracketPattern, options: []) {
 | ||
|             result = regex.stringByReplacingMatches(in: result, options: [], range: NSRange(location: 0, length: result.utf16.count), withTemplate: "")
 | ||
|         }
 | ||
| 
 | ||
|         // 去除 emoji
 | ||
|         // 使用 unicode 范围匹配 emoji
 | ||
|         let emojiPattern = "[\\p{Emoji}]"
 | ||
|         if let regex = try? NSRegularExpression(pattern: emojiPattern, options: []) {
 | ||
|             result = regex.stringByReplacingMatches(in: result, options: [], range: NSRange(location: 0, length: result.utf16.count), withTemplate: "")
 | ||
|         }
 | ||
| 
 | ||
|         return result.trimmingCharacters(in: .whitespacesAndNewlines)
 | ||
|     }
 | ||
| 
 | ||
|     /// 计算文本的预估音频时长
 | ||
|     /// - Parameters:
 | ||
|     ///   - text: 文本内容
 | ||
|     ///   - speechRate: 语速设置 (-50 到 50,默认为 0)
 | ||
|     ///   - baseWordsPerMinute: 基础语速(每分钟字数),默认为 200
 | ||
|     /// - Returns: 预估的音频时长(秒,TimeInterval)
 | ||
|     func calculateAudioDuration(
 | ||
|         text: String,
 | ||
|         speechRate: Int = 0,
 | ||
|         baseWordsPerMinute: Double = 200.0
 | ||
|     ) -> TimeInterval {
 | ||
|         guard !text.isEmpty else { return 0 }
 | ||
| 
 | ||
|         let voiceText = extractTextForVoice(text)
 | ||
|         guard !voiceText.isEmpty else { return 0 }
 | ||
| 
 | ||
|         // 中文字符数
 | ||
|         let chineseRegex = try! NSRegularExpression(pattern: "[\\u4e00-\\u9fff]")
 | ||
|         let chineseCharCount = chineseRegex.numberOfMatches(in: voiceText, range: NSRange(location: 0, length: voiceText.utf16.count))
 | ||
| 
 | ||
|         // 英文单词数(先去掉中文,再按单词匹配)
 | ||
|         let textWithoutChinese = chineseRegex.stringByReplacingMatches(in: voiceText, range: NSRange(location: 0, length: voiceText.utf16.count), withTemplate: " ")
 | ||
|         let wordRegex = try! NSRegularExpression(pattern: "\\b\\w+\\b")
 | ||
|         let englishWordCount = wordRegex.numberOfMatches(in: textWithoutChinese, range: NSRange(location: 0, length: textWithoutChinese.utf16.count))
 | ||
| 
 | ||
|         let totalWordCount = chineseCharCount + englishWordCount
 | ||
|         if totalWordCount == 0 { return 0 }
 | ||
| 
 | ||
|         // 根据语速调整基础语速
 | ||
|         let speedMultiplier = 1.0 + (Double(speechRate) / 100.0) // -50 → 0.5, 50 → 1.5
 | ||
|         let adjustedWordsPerMinute = baseWordsPerMinute * speedMultiplier
 | ||
| 
 | ||
|         // 计算时长(分钟 → 秒)
 | ||
|         let durationInMinutes = Double(totalWordCount) / adjustedWordsPerMinute
 | ||
|         let durationInSeconds = durationInMinutes * 60.0
 | ||
| 
 | ||
|         return max(0.5, durationInSeconds)
 | ||
|     }
 | ||
| 
 | ||
| //    /// 格式化音频时长显示
 | ||
| //    /// - Parameter durationInSeconds: 时长(秒)
 | ||
| //    /// - Returns: 格式化的时长字符串,如 "2''" 或 "1'23''"
 | ||
| //    func formatAudioDuration(_ durationInSeconds: Double) -> String {
 | ||
| //        if durationInSeconds < 1 {
 | ||
| //            return "1''"
 | ||
| //        }
 | ||
| //
 | ||
| //        let totalSeconds = Int(round(durationInSeconds))
 | ||
| //
 | ||
| //        if totalSeconds < 60 {
 | ||
| //            return "\(totalSeconds)''"
 | ||
| //        }
 | ||
| //
 | ||
| //        let minutes = totalSeconds / 60
 | ||
| //        let seconds = totalSeconds % 60
 | ||
| //
 | ||
| //        if seconds == 0 {
 | ||
| //            return "\(minutes)'"
 | ||
| //        }
 | ||
| //
 | ||
| //        return String(format: "%d'%02d''", minutes, seconds)
 | ||
| //    }
 | ||
| 
 | ||
| }
 |