本文演示如何使用第三方的
StreamingKit库,来实现网络流音频的播放。
一、StreamingKit介绍和配置
1,基本介绍
(1)
StreamingKit是一个适用于
iOS和
Mac OSX的音频播放流媒体库。
StreamingKit提供了一个简洁的面向对象
API,用于在
CoreAudio框架下进行音频的解压和播放(采用硬件或软件编解码器)处理。
(2)
StreamingKit的主要机制是对从播放器输入的数据源进行解耦,从而使高级定制的数据源可以进行诸如基于流媒体的渐进式下载、编码解码、自动恢复、动态缓冲之类的处理。
StreamingKit是唯一支持不同格式音频文件无缝播放的音频播放流媒体库。
(3)
Github主页:
https://github.com/tumtumtum/StreamingKit
2,主要特点
- 免费开源
- 简洁的API
- 可读性很强的源代码
- 精心使用多线程提供了一个快速响应的API,既能防止线程阻塞,又能保证缓冲流畅
- 缓冲并无缝播放所有不同格式的音频文件
- 容易实现的音频数据源(支持本地、HTTP、AutoRecovering HTTP作为数据源)
- 容易kuo扩展数据源以支持自动缓冲、编码等
- 低耗电和低cpu使用率(cpu使用率0%,流式处理时使用率为1%)
- 优化线性数据源,仅随机访问数据源需要搜索
- StreamingKit0.2.0使用AudioUnit API而不是速度较慢的音频队列API,允许对原始PCM数据进行实时截取以获得并行测量、EQ等特征
- 电能计量
- 内置的均衡器(iOS5.0及以上版本、OSX10.9及以上版本)支持音频播放的同时动态改变、启用、禁用均衡器
- 提供了iOS和Mac OSX应用实例
3,安装配置
(1)将源码包下载下来后,将其中的
StreamingKit/StreamingKit文件夹复制到项目中来。
1
|
|
二、制作一个网络音频播放器
1,效果图
(1)程序运行后自动开始播放音乐(整个队列一个有
3首歌曲,默认先播放第一首)
(2)点击“
上一曲”“
下一曲”按钮可以切换当前播放歌曲。
(3)歌曲播放过程中进度条会随之变化,进度条右侧会显示出当前歌曲播放时间。
(4)进度条可以拖动,拖动结束后自动播放该时间点的音乐。
(5)点击“
暂停”按钮可以交替切换播放器暂停、继续状态。
(6)点击“
结束”按钮,结束整个播放器的音乐播放。
(2)为了让播放器能在后台持续播放,我们需要将 Targets-> Capabilities-> BackgroundModes设为 ON,同时勾选“ Audio,AirPlay,and Picture in Picture”。
1
(3)主视图代码( ViewController.swift)
13
源码下载:
hangge_1667.zip
2,实现步骤
1
2
3
4
5
|
<key>
NSAppTransportSecurity
</key>
<dict>
NSAllowsArbitraryLoads
</key>
<
true
/>
</dict>
|
(2)为了让播放器能在后台持续播放,我们需要将 Targets-> Capabilities-> BackgroundModes设为 ON,同时勾选“ Audio,AirPlay,and Picture in Picture”。
import
UIKit
import
AVFoundation
@UIApplicationMain
class
AppDelegate
:
UIResponder
,
UIApplicationDelegate
{
var
window:
UIWindow
?
func
application(_ application:
UIApplication
launchOptions: [
UIApplicationLaunchOptionsKey
Any
]?) ->
Bool
{
do {
try session.setActive(
)
try session.setCategory(
AVAudioSessionCategoryPlayback
)
} catch {
print
(error)
}
return
true
}
applicationWillResignActive(_ application:
) {
}
applicationDidEnterBackground(_ application:
UIApplication
) {
}
applicationWillEnterForeground(_ application:
) {
}
applicationDidBecomeActive(_ application:
) {
}
applicationWillTerminate(_ application:
) {
}
}
|
(3)主视图代码( ViewController.swift)
UIKit
ViewController
UIViewController
{
@IBOutlet
weak
titleLabel:
UILabel
!
//暂停按钮
pauseBtn:
UIButton
!
//可拖动的进度条
playbackSlider:
UiSlider
!
//当前播放时间标签
playTime:
UILabel
!
//更新进度条定时器
timer:
Timer
!
//音频播放器
//播放列表
"歌曲2"
"http://mxd.766.com/sdo/music/data/3/m12.mp3"
"歌曲3"
"http://mxd.766.com/sdo/music/data/3/m13.mp3"
)!)]
//当前播放音乐索引
currentIndex:
Int
= -1
//是否循环播放
loop:
Bool
=
false
//当前播放状态
state:
STKAudioPlayerState
= []
override
viewDidLoad() {
super
.viewDidLoad()
playbackSlider!.minimumValue = 0
playbackSlider!.isContinuous =
false
//重置播放器
resetAudioPlayer()
//开始播放歌曲列表
playWithQueue(queue: queue)
//设置一个定时器,每三秒钟滚动一次
timer =
.scheduledTimer(timeInterval: 0.1,target:
self
selector: #selector(tick),userInfo:
nil
)
}
//重置播放器
resetAudioPlayer() {
options =
STKAudioPlayerOptions
()
options.flushQueueOnSeek =
true
options.enableVolumeMixer =
true
audioPlayer =
(options: options)
audioPlayer.meteringEnabled =
true
audioPlayer.volume = 1
audioPlayer.delegate =
self
}
//开始播放歌曲列表(默认从第一首歌曲开始播放)
playWithQueue(queue: [
],index:
Int
= 0) {
guard index >= 0 && index < queue.count
else
{
return
}
.queue = queue
audioPlayer.clearQueue()
url = queue[index].url
audioPlayer.play(url)
i
in
1 ..< queue.count {
audioPlayer.queue(queue[
((index + i) % queue.count)].url)
}
currentIndex = index
loop =
false
}
//停止播放
stop() {
audioPlayer.stop()
queue = []
currentIndex = -1
}
//单独播放某个歌曲
play(file:
) {
audioPlayer.play(file.url)
}
//下一曲
next() {
guard queue.count > 0
{
return
}
currentIndex = (currentIndex + 1) % queue.count
playWithQueue(queue: queue,index: currentIndex)
}
//上一曲
prev() {
currentIndex =
max
(0,currentIndex - 1)
}
//下一曲按钮点击
@IBAction
nextBtnTapped(_ sender:
) {
next()
}
//上一曲按钮点击
prevBtnTapped(_ sender:
) {
prev()
}
//暂停继续按钮点击
pauseBtnTapped(_ sender:
) {
//在暂停和继续两个状态间切换
if
.state == .paused {
audioPlayer.resume()
}
{
audioPlayer.pause()
}
}
//结束按钮点击
stopBtnTapped(_ sender:
) {
stop()
}
//定时器响应,更新进度条和时间
tick() {
if
state == .playing {
//更新进度条进度值
.playbackSlider!.value =
Float
(audioPlayer.progress)
//一个小算法,来实现00:00这种格式的播放时间
all:
=
(audioPlayer.progress)
m:
=all % 60
f:
(all/60)
time:
String
=
""
f<10{
time=
"0\(f):"
{
"\(f)"
}
m<10{
time+=
"0\(m)"
{
"\(m)"
}
//更新播放时间
.playTime!.text=time
}
}
//拖动进度条改变值时触发
playbackSliderValueChanged(_ sender:
) {
//播放器定位到对应的位置
//如果当前时暂停状态,则继续播放
state == .paused
{
audioPlayer.resume()
}
}
didReceiveMemoryWarning() {
.didReceiveMemoryWarning()
}
}
extension
STKAudioPlayerDelegate
{
//开始播放歌曲
index = (queue.index { $0.url == queueItemId
as
!
}) {
currentIndex = index
}
}
//缓冲完毕
didFinishBufferingSourceWithQueueItemId queueItemId:
) {
updateNowPlayingInfoCenter()
}
//播放状态变化
stateChanged state:
prevIoUsState:
) {
.state = state
state != .stopped && state != .error && state != .disposed {
}
updateNowPlayingInfoCenter()
}
//播放结束
didFinishPlayingQueueItemId queueItemId:
with stopReason:
STKAudioPlayerStopReason
andProgress progress:
Double
) {
index = (queue.index {
$0.url == audioPlayer.currentlyPlayingQueueItemId()
URL
}) {
currentIndex = index
}
//自动播放下一曲
stopReason == .eof {
next()
else
stopReason == .error {
stop()
resetAudioPlayer()
}
}
//发生错误
unexpectedError errorCode:
STKAudioPlayerErrorCode
) {
(
"Error when playing music \(errorCode)"
)
resetAudioPlayer()
}
//更新当前播放信息
updateNowPlayingInfoCenter() {
currentIndex >= 0 {
music = queue[currentIndex]
//更新标题
titleLabel.text =
"当前播放:\(music.name)"
//更新暂停按钮名字
pauseBtnTitle =
.state == .playing ?
"暂停"
:
"继续"
pauseBtn.setTitle(pauseBtnTitle,
: .normal)
//设置进度条相关属性
playbackSlider!.maximumValue =
Float
(audioPlayer.duration)
{
//停止播放
"播放停止!"
//更新进度条和时间标签
playbackSlider.value = 0
playTime.text =
"--:--"
}
}
}
//歌曲类
@H_403_2100@{
name:
String
URL
//类构造函数
init
(name:
){
.name = name
.url = url
}
}
|
原文出自: www.hangge.com 转载请保留原文链接: http://www.hangge.com/blog/cache/detail_1667.html