Wave
Overview
一个简单的音频播放器的实现,可实现自定义缓存,可以播放各类音频流。
使用方式
- 创建一个音频播放器
let player = StreamAudioPlayer()
- 将音频数据传递给播放器
player.response(with: data)
/// 当解析完音频头部信息,播放器会自动进行播放。
- 自定义属性
设置最少播放帧
player?.leastPlayPackets = 100
- 设置代理
player.delegate = self
func streamAudioPlayer(_ player: StreamAudioPlayer, parsedProgress progress: Progress) {
DispatchQueue.main.async {
/// 这里可以显示解析进度(基本上就是网络请求的进度)。
}
}
func streamAudioPlayerCompletedParsedAudioInfo(_ player: StreamAudioPlayer) {
DispatchQueue.main.async {
/// 音频信息头解析完成
}
}
func streamAudioPlayer(_ player: StreamAudioPlayer, didCompletedPlayFromTime time: TimeInterval) {
DispatchQueue.main.async {
/// 这里可以取消显示indicator.
/// 成功从某一个点开始播放.
self.player?.play()
}
}
func streamAudioPlayer(_ player: StreamAudioPlayer, didCompletedPlayAudio isEnd: Bool) {
DispatchQueue.main.async {
if isEnd {
/// 下一首音频
} else {
/// 显示indicator,表示音频数据还没有过来.
}
}
}
- 基本控制
player?.play()
player?.pause()
player?.stop()
/// 如果返回的true,表示已经有数据并成功seek到该点的位置,false表示时间超出范围或者就是音频数据还没有被解析,这个时候使用delegate来监听。
player?.seek(toTime: 1024)
建议不要持续使用
UISlider
的valueChanged
来seek
,下面给出最佳的方案:
/// Add valueChanged target to timeSliderValueChange
timeSlider.addTarget(self, action: #selector(timeSliderValueChange(_:)), for: .valueChanged)
/// Add touchUpInside and touchUpOutside target to timeSliderSeek
timeSlider.addTarget(self, action: #selector(timeSliderSeek(_:)), for: .touchUpInside)
timeSlider.addTarget(self, action: #selector(timeSliderSeek(_:)), for: .touchUpOutside)
@objc fileprivate func timeSliderValueChange(_ sender: MusicPlayerSlider) {
}
@objc fileprivate func timeSliderSeek(_ sender: MusicPlayerSlider) {
if player?.seek(toTime: TimeInterval(sender.value)) == true {
player?.play()
} else {
/// 显示缓存提示
}
}
流程图
GitHub: Wave
Demo
最好的Demo就是我的毕业设计: Music
喜欢的朋友就给个star吧