fix
无故事王国
2024-06-06 6f7f02d5c8880ff670b2c694fe61f5af5a6e3e36
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//
//  VoicePlayer.swift
//  DolphinEnglishLearnStudent
//
//  Created by 无故事王国 on 2024/6/4.
//
 
import Foundation
import AVFAudio
 
 
/// 音频播放器
class VoicePlayer:NSObject{
                /// 缓存地址
                private let voiceCacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("voices")
                private static var _sharedInstance: VoicePlayer?
                private var player:AVAudioPlayer?
 
                //是否正在播放
                var isPlaying:Bool{return player?.isPlaying ?? false}
                //播放完成回调
                private var playComplete:(()->Void)?
 
 
                /// 单例
                /// - Returns: <#description#>
                class func share() -> VoicePlayer {
                                guard let instance = _sharedInstance else {
                                                _sharedInstance = VoicePlayer()
                                                try? FileManager.default.createDirectory(at: _sharedInstance!.voiceCacheDirectory, withIntermediateDirectories: true)
                                                return _sharedInstance!
                                }
                                return instance
                }
 
                private override init() {} // 私有化init方法
 
                ///销毁单例对象
                class func destroy() {
                                _sharedInstance = nil
                }
 
                /// 播放语音
                /// - Parameter url: Https的语音地址
                func playerAt(url:String?){
                                guard let u = url else {return}
                                if player?.isPlaying ?? false{
                                                VoicePlayer.share().playComplete?() //先通知完成播放
                                                player?.stop()
                                }
 
                                //文件存在:直接播放缓存路径的语音
                                let fileURL = voiceCacheDirectory.appendingPathComponent(URL(fileURLWithPath: u).lastPathComponent).droppedScheme()
                                if FileManager.default.fileExists(atPath: fileURL!.absoluteString){
                                                player = try? AVAudioPlayer(contentsOf: fileURL!)
                                                player?.delegate = self
                                                player?.play()
                                }else{
                                                //文件不存在:执行下载
                                                let downloadTask = URLSession.shared.downloadTask(with: URL(string: u)!) { tempLocalUrl, response, error in
                                                                if let tempLocalUrl = tempLocalUrl, error == nil {
                                                                                do {
                                                                                                let finalCacheUrl = self.voiceCacheDirectory.appendingPathComponent(URL(fileURLWithPath: u).lastPathComponent)
                                                                                                try FileManager.default.moveItem(at: tempLocalUrl, to: finalCacheUrl)
                                                                                                self.player = try? AVAudioPlayer(contentsOf: finalCacheUrl)
                                                                                                self.player?.delegate = self
                                                                                                self.player?.play()
                                                                                } catch {
                                                                                                print("视频缓存失败:catch")
                                                                                }
                                                                } else {
                                                                                print("视频缓存失败:\(error?.localizedDescription ?? "")")
                                                                }
                                                }
                                                downloadTask.resume()
                                }
                }
 
                func playerEnd(){
                                player?.stop()
                                playComplete?()
 
                }
 
                func playEnd(course:@escaping ()->Void){
                                self.playComplete = course
                }
}
 
extension VoicePlayer:AVAudioPlayerDelegate{
                func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
                                VoicePlayer.share().playComplete?()
                }
 
                func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: (any Error)?) {
                                print("播放错误")
                }
}