Wave
Overview
一個(gè)簡單的音頻播放器的實(shí)現(xiàn),可實(shí)現(xiàn)自定義緩存国觉,可以播放各類音頻流。
使用方式
- 創(chuàng)建一個(gè)音頻播放器
let player = StreamAudioPlayer()
- 將音頻數(shù)據(jù)傳遞給播放器
player.response(with: data)
/// 當(dāng)解析完音頻頭部信息针饥,播放器會(huì)自動(dòng)進(jìn)行播放筷凤。
- 自定義屬性
設(shè)置最少播放幀
player?.leastPlayPackets = 100
- 設(shè)置代理
player.delegate = self
func streamAudioPlayer(_ player: StreamAudioPlayer, parsedProgress progress: Progress) {
DispatchQueue.main.async {
/// 這里可以顯示解析進(jìn)度(基本上就是網(wǎng)絡(luò)請(qǐng)求的進(jìn)度)蹂风。
}
}
func streamAudioPlayerCompletedParsedAudioInfo(_ player: StreamAudioPlayer) {
DispatchQueue.main.async {
/// 音頻信息頭解析完成
}
}
func streamAudioPlayer(_ player: StreamAudioPlayer, didCompletedPlayFromTime time: TimeInterval) {
DispatchQueue.main.async {
/// 這里可以取消顯示indicator.
/// 成功從某一個(gè)點(diǎn)開始播放.
self.player?.play()
}
}
func streamAudioPlayer(_ player: StreamAudioPlayer, didCompletedPlayAudio isEnd: Bool) {
DispatchQueue.main.async {
if isEnd {
/// 下一首音頻
} else {
/// 顯示indicator任内,表示音頻數(shù)據(jù)還沒有過來.
}
}
}
- 基本控制
player?.play()
player?.pause()
player?.stop()
/// 如果返回的true趋距,表示已經(jīng)有數(shù)據(jù)并成功seek到該點(diǎn)的位置,false表示時(shí)間超出范圍或者就是音頻數(shù)據(jù)還沒有被解析,這個(gè)時(shí)候使用delegate來監(jiān)聽狼渊。
player?.seek(toTime: 1024)
建議不要持續(xù)使用
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就是我的畢業(yè)設(shè)計(jì): Music
喜歡的朋友就給個(gè)star吧