2023年7月25日发(作者:)
Swift-AVPlayer⽹络⾳频播放import UIKitimport Foundationclass PublicFunction: NSObject { //MARK:播放时长 static func convertTime(totalSeconds:Int) -> (String) { let seconds:Int = totalSeconds % 60 let minutes:Int = (totalSeconds / 60) % 60 let time:String = "(String(format: "%02d", minutes)):(String(format: "%02d", seconds))" return time }import UIKitimport AVFoundationclass NetAudioPlayerTool: NSObject { //正在播放回调 //currentTime 播放时间 //currentProgress 播放进度 typealias OnPlayingBlock = (_ currentTime:Float64,_ currentProgress:Float) -> () //准备播放回调 //totalDuration ⾳频总时长 typealias PrepareToPlayBlock = (_ totalDuration:Float) -> () //正在缓冲回调 //bufferDuration 已缓冲的时长 typealias OnBufferingBlock = (_ bufferDuration:Float) -> () //播放完成回调 //flag YES播放完成, NO播放失败 typealias CompletePlayingBlock = (_ flag:Bool) -> () //缓存⾃动暂停回调, ⽤于更改播放按钮的样式 //bufferDuration isPlaying 是否正在播放, 如果没有播放表⽰正在缓冲 typealias IsPlayingBlock = (_ isPlaying:Float) -> ()
var playingBlock:OnPlayingBlock? var prepareToPlayBlock:PrepareToPlayBlock? var bufferingBlock:OnBufferingBlock? var completePlayBlock:CompletePlayingBlock? var isPlayingBlock:IsPlayingBlock?
var palyerItem:AVPlayerItem? //播放器 var player:AVPlayer = AVPlayer() //播放路径 var audioPath:String = "" //⾳量⼤⼩ var volume:Float = 1.0 // 只有当播放器状态为`ReadyToPlay`,才可以执⾏拖拽操作,否则crash. var canDraggingFlag:Bool = false
//之前播放的进度 var timeOffset:Float64 = 0
//播放时间 var currentTime:Float64 = 0 //⾳频总时长 var totalDuration:Float64 = 0
override init() { () erverForPlayer() }
//MARK:如果在播放⾳频前有录⾳操作,需要重新设置⾳频会话,否则声⾳极⼩. func setPlaybackSession() { let session = Instance() do { do { try ive(true) try egory(ck) } catch { print(error) } }
//MARK:创建播放器 func createAudioPlayer() { //创建媒体资源管理对象 let Url = URL(string: ath) Item = (url: Url!) //创建ACplayer:负责视频播放 = (playerItem: Item) = 1.0 = //与播放缓存相关的观测属性 erverForPlayItem() }
//MARK:开始播放 func playAudio() { () }
//MARK:暂停播放 func pauseAudio() { () }
//MARK:停⽌播放 func stopAudio() { yPlayer() }
//MARK:改变播放进度 func changeAudio(currentTime:Float64) { if currentTime>0 { let time:CMTime = CMTimeMakeWithSeconds(currentTime, preferredTimescale: 1 * Int32(NSEC_PER_SEC)) (to: time, toleranceBefore: , toleranceAfter:) () } }
//MARK:Notification //播放完毕 func addObserverForPlayer() { erver(self, selector: #selector(audioPlayCompletion), name: erItemDidPlayToEndTime, object: nil) }
//MARK:Observer //观察 加载状态 加载进度 func addObserverForPlayItem() { tItem?.addObserver(self, forKeyPath: "status", options: .new, context: nil) tItem?.addObserver(self, forKeyPath: "loadedTimeRanges", options: .new, context: nil) tItem?.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil) tItem?.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil) }
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { let playerItem:AVPlayerItem = object as! AVPlayerItem
if keyPath == "status" { switch Item?.status { case .readyToPlay ://准备播放 ggingFlag = true uration = CMTimeGetSeconds(on) eToPlayBlock?(Float(uration))
if fset>0 { let time:CMTime = CMTimeMakeWithSeconds(fset, preferredTimescale: 1 * Int32(NSEC_PER_SEC)) (to: time, toleranceBefore: , toleranceAfter:) (to: time, toleranceBefore: , toleranceAfter:) } PlayProgress()//播放进度
//dio() break case .failed: tePlayBlock?(false) break case .unknown: break default : break } } else if keyPath == "loadedTimeRanges"{//获取最新缓存的区间 let bufferInterval:TimeInterval = edDuration() ingBlock?(Float(bufferInterval)) } else if keyPath == "playbackBufferEmpty"{//正在缓存视频请稍等
} else if keyPath == "playbackLikelyToKeepUp"{//缓存好了继续播放
} }
//播放进度 func updatePlayProgress() { iodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 1), queue: ) { (time) in //当前正在播放的时间 tTime = CMTimeGetSeconds(time) gBlock?(tTime,Float(tTime)) } }
//MARK:播放完毕 @objc func audioPlayCompletion() { if tItem?.status == oPlay { (to: ) { finished in tePlayBlock?(true) } } }
//MARK:计算缓冲进度 func bufferedDuration() -> (TimeInterval) { let loadTimeArray = Item!.loadedTimeRanges //获取最新缓存的区间 let newTimeRange : CMTimeRange = as! CMTimeRange let startSeconds = CMTimeGetSeconds(); let durationSeconds = CMTimeGetSeconds(on); let totalBuffer = startSeconds + durationSeconds;//缓冲总长度 //print("当前缓冲时间:(totalBuffer)") return totalBuffer }
//MARK:释放 播放器 func destroyPlayer() { () tTime = 0.0 tItem?.cancelPendingSeeks() tItem?.Loading() eCurrentItem(with: nil) }
//MARK:移除通知 func removeObserverFromPlayer() { tItem?.removeObserver(self, forKeyPath: "status") tItem?.removeObserver(self, forKeyPath: "loadedTimeRanges") tItem?.removeObserver(self, forKeyPath: "playbackBufferEmpty") tItem?.removeObserver(self, forKeyPath: "playbackLikelyToKeepUp")
Observer(self, name: erItemDidPlayToEndTime, object: nil) }}let netPlayer = NetAudioPlayerTool()//线上⾳频 播放时间var currentTime:Float = 0//线上⾳频 ⾳频总时长var totalDuration:Float = 0//MARK:创建线上播放器func createOnlineAudioPlayer() { ath = "/2/f8e446476833e4c950f58d07762c4827/KGTX/CLTX001/84ea49794a9cc96fa0d27.m AudioPlayer()}//MARK:Player Blockfunc addNetPlayerBlock() { //⽹络⾳频 准备播放时更新UI eToPlayBlock = { (totalDuration) in print("⾳频总时长:(tTime(totalSeconds: Int(totalDuration)))") uration = totalDuration }
//⽹络⾳频 缓冲时更新UI ingBlock = { [weak self] (bufferInterval) in print("当前缓冲时间:(tTime(totalSeconds: Int(bufferInterval)))") print("当前缓冲进度:(Float(bufferInterval / self!.totalDuration))") }
//⽹络⾳频 播放时更新UI gBlock = { (currentTime,currentProgress) in print("当前播放时长---(tTime(totalSeconds: Int(currentTime)))") print("当前播放进度:(currentProgress)") }
//⽹络⾳频 播放完成更新UI tePlayBlock = { (isSuccess) in print("播放完毕") }}//开始播放dio()//暂停播放udio()//拖动修改进度Audio(currentTime: Float64())
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1690228136a317952.html
评论列表(0条)