123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- //
- // TSAudioPlayer.swift
- // Girly
- //
- // Created by 100Years on 2025/1/9.
- //
- import AVFoundation
- class TSAudioPlayer: NSObject {
- private var player: AVPlayer?
- private var timeObserverToken: Any?
- var isLooping: Bool = false
-
- override init() {
- super.init()
- }
-
- var isPlaying: Bool {
- // return player?.rate != 0 && player?.error == nil
-
- if let player = player {
- if #available(iOS 10.0, *) {
- return player.timeControlStatus == .playing
- } else {
- return player.rate > 0
- }
- }
- return false
- }
-
- var duration: Double {
- if let currentItem = player?.currentItem {
- return CMTimeGetSeconds(currentItem.asset.duration)
- }
- return 0.0
- }
-
- var volume: Float {
- get {
- return player?.volume ?? 0.0
- }
- set {
- player?.volume = max(0.0, min(newValue, 1.0))
- }
- }
-
- var currentTime: Double {
- if let currentItem = player?.currentItem {
- return CMTimeGetSeconds(currentItem.currentTime())
- }
- return 0.0
- }
-
- var playerUsable: Bool {
- return player != nil
- }
-
- var currentTimeChanged: ((Double,Double) -> Void)?
- var audioPlayerDidFinishHandle: ((Bool) -> Void)?
-
- /// 初始化播放器
- /// - Parameter url: 音频文件的 URL
- init?(url: URL) {
- super.init()
-
- let playerItem = AVPlayerItem(url: url)
- player = AVPlayer(playerItem: playerItem)
-
- // 监听播放完成事件
- NotificationCenter.default.addObserver(
- self,
- selector: #selector(playerDidFinishPlaying),
- name: .AVPlayerItemDidPlayToEndTime,
- object: playerItem
- )
-
- // 设置音频会话
- do {
- let audioSession = AVAudioSession.sharedInstance()
- try audioSession.setCategory(.playback)
- try audioSession.setActive(true)
- } catch {
- print("TSAudioPlayer 音频会话设置失败: \(error.localizedDescription)")
- return nil
- }
- }
-
- deinit {
- stop()
- }
-
- /// 开始播放音频
- func play() {
- guard let player = player else { return }
-
- let outputVolume = AVAudioSession.sharedInstance().outputVolume
- print("TSAudioPlayer outputVolume: \(outputVolume)")
-
- if outputVolume == 0.0 {
- print("Please turn up the volume".localized)
- }
-
- player.play()
-
- // 监听播放进度
- addTimeObserver()
- }
-
- /// 暂停播放音频
- func pause() {
- player?.pause()
- }
-
- /// 停止并销毁播放器
- func stop() {
- player?.pause()
- player?.replaceCurrentItem(with: nil)
- player = nil
- removeTimeObserver()
- }
-
- /// 设置是否重复播放
- /// - Parameter loop: 是否循环播放
- func setLoop(_ loop: Bool) {
- isLooping = loop
- }
-
- /// 跳转到指定时间
- /// - Parameter time: 目标时间(秒)
- func seek(to time: Double) {
- if let player = player {
- let targetTime = CMTimeMakeWithSeconds(time, preferredTimescale: 600)
- player.seek(to: targetTime)
- }
- }
-
- /// 监听播放完成
- @objc private func playerDidFinishPlaying() {
- if isLooping {
- seek(to: 0.0)
- play()
- }
- audioPlayerDidFinishHandle?(true)
- }
-
- /// 添加时间观察者
- private func addTimeObserver() {
- let interval = CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
- timeObserverToken = player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
- guard let self = self else { return }
- let currentTime = CMTimeGetSeconds(time)
- self.currentTimeChanged?(currentTime,duration)
- }
- }
-
- /// 移除时间观察者
- private func removeTimeObserver() {
- if let token = timeObserverToken {
- player?.removeTimeObserver(token)
- timeObserverToken = nil
- }
- }
- }
- //class TSAudioPlayer : NSObject, AVAudioPlayerDelegate{
- // private var audioPlayer: AVAudioPlayer?
- // var isLooping: Bool = false
- //
- // override init() {
- // super.init()
- // }
- //
- // var isPlaying:Bool{
- // if let audioPlayer = audioPlayer {
- // return audioPlayer.isPlaying
- // }
- // return false
- // }
- //
- // var duration:Double{
- // if let audioPlayer = audioPlayer {
- // return audioPlayer.duration
- // }
- // return 0.0
- // }
- //
- // var volume:Float{
- // if let audioPlayer = audioPlayer {
- // return audioPlayer.volume
- // }
- // return 0
- // }
- //
- // var currentTime:Double{
- // if let audioPlayer = audioPlayer {
- // return audioPlayer.currentTime
- // }
- // return 0.0
- // }
- //
- // //播放器是否可用
- // var playerUsable:Bool {
- // if audioPlayer != nil {
- // return true
- // }
- // return false
- // }
- //
- // var timer:GCDTimer = GCDTimer()
- //
- // var currentTimeChanged:((Double)->Void)?
- //
- // /// 初始化播放器
- // /// - Parameter url: 音频文件的 URL
- // init?(url: URL) {
- // super.init()
- // do {
- // audioPlayer = try AVAudioPlayer(contentsOf: url)
- // audioPlayer?.prepareToPlay()
- // audioPlayer?.delegate = self
- // let audioSession = AVAudioSession.sharedInstance()
- // try audioSession.setCategory(.playback) // 设置类别为 playback
- // try audioSession.setActive(true) // 激活音频会话
- //
- // } catch {
- // dePrint("TSAudioPlayer 音频文件加载失败: \(error.localizedDescription)")
- // return nil
- // }
- // }
- //
- // /// 开始播放音频
- // func play() {
- // guard let audioPlayer = audioPlayer else { return }
- // let outputVolume = AVAudioSession.sharedInstance().outputVolume
- // dePrint("TSAudioPlayer outputVolume\(outputVolume)")
- //
- // if outputVolume == 0.0 {
- // TSToastShared.showToast(text: "Please turn up the volume".localized)
- // }
- //
- // audioPlayer.numberOfLoops = isLooping ? -1 : 0
- // audioPlayer.play()
- //
- // timer.start(interval: 0.5, repeats: true) { [weak self] in
- // guard let self = self else { return }
- //
- // let currentTime = audioPlayer.currentTime
- // dePrint("TSAudioPlayer Current playback time: \(currentTime) seconds")
- // currentTimeChanged?(currentTime)
- // }
- // }
- //
- // /// 暂停播放音频
- // func pause() {
- // audioPlayer?.pause()
- // }
- //
- // /// 停止并销毁播放器
- // func stop() {
- // audioPlayer?.stop()
- // audioPlayer = nil
- // timer.stop()
- // }
- //
- // /// 设置是否重复播放
- // /// - Parameter loop: 是否循环播放
- // func setLoop(_ loop: Bool) {
- // isLooping = loop
- // audioPlayer?.numberOfLoops = loop ? -1 : 0
- // }
- //
- // /// 设置音量
- // /// - Parameter volume: 音量大小 (0.0 静音, 1.0 最大)
- // func setVolume(_ volume: Float) {
- // audioPlayer?.volume = max(0.0, min(volume, 1.0))
- // }
- //
- // deinit {
- // stop()
- // }
- //
- // var audioPlayerDidFinishHandle:((Bool)->Void)?
- // // 实现 AVAudioPlayerDelegate 方法
- // func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
- // if flag {
- // print("TSAudioPlayer 音频播放完成")
- //
- // } else {
- // print("TSAudioPlayer 音频播放中断")
- // }
- // audioPlayerDidFinishHandle?(flag)
- // }
- //}
|