Swift - 制作一个在线流媒体音乐播放器(使用StreamingKit库)
一、StreamingKit介绍和配置
1,基本介绍
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
|
#import "STKAudioPlayer.h" |
二、制作一个网络音频播放器
1,效果图

2,实现步骤
|
1
2
3
4
5
|
<key>NSAppTransportSecurity</key><dict> <key>NSAllowsArbitraryLoads</key> <true/></dict> |
(2)为了让播放器能在后台持续播放,我们需要将 Targets -> Capabilities -> BackgroundModes 设为 ON,同时勾选“Audio, AirPlay, and Picture in Picture”。

|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
import UIKitimport AVFoundation@UIApplicationMainclass AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // 注册后台播放 let session = AVAudioSession.sharedInstance() do { try session.setActive(true) try session.setCategory(AVAudioSessionCategoryPlayback) } catch { print(error) } return true } func applicationWillResignActive(_ application: UIApplication) { } func applicationDidEnterBackground(_ application: UIApplication) { } func applicationWillEnterForeground(_ application: UIApplication) { } func applicationDidBecomeActive(_ application: UIApplication) { } func applicationWillTerminate(_ application: UIApplication) { }} |
(3)主视图代码(ViewController.swift)
import UIKitclass ViewController: UIViewController { //显示歌曲标题 @IBOutlet weak var titleLabel: UILabel! //暂停按钮 @IBOutlet weak var pauseBtn: UIButton! //可拖动的进度条 @IBOutlet weak var playbackSlider: UISlider! //当前播放时间标签 @IBOutlet weak var playTime: UILabel! //更新进度条定时器 var timer:Timer! //音频播放器 var audioPlayer: STKAudioPlayer! //播放列表 var queue = [Music(name: "歌曲1", Music(name: "歌曲2", Music(name: "歌曲3", //当前播放音乐索引 var currentIndex:Int = -1 //是否循环播放 var loop:Bool = false //当前播放状态 var state:STKAudioPlayerState = [] override func viewDidLoad() { super.viewDidLoad() //设置进度条相关属性 playbackSlider!.minimumValue = 0 playbackSlider!.isContinuous = false //重置播放器 resetAudioPlayer() //开始播放歌曲列表 playWithQueue(queue: queue) //设置一个定时器,每三秒钟滚动一次 timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(tick), userInfo: nil, repeats: true) } //重置播放器 func resetAudioPlayer() { var options = STKAudioPlayerOptions() options.flushQueueOnSeek = true options.enableVolumeMixer = true audioPlayer = STKAudioPlayer(options: options) audioPlayer.meteringEnabled = true audioPlayer.volume = 1 audioPlayer.delegate = self } //开始播放歌曲列表(默认从第一首歌曲开始播放) func playWithQueue(queue: [Music], index: Int = 0) { guard index >= 0 && index < queue.count else { return } self.queue = queue audioPlayer.clearQueue() let url = queue[index].url audioPlayer.play(url) for i in 1 ..< queue.count { audioPlayer.queue(queue[Int((index + i) % queue.count)].url) } currentIndex = index loop = false } //停止播放 func stop() { audioPlayer.stop() queue = [] currentIndex = -1 } //单独播放某个歌曲 func play(file: Music) { audioPlayer.play(file.url) } //下一曲 func next() { guard queue.count > 0 else { return } currentIndex = (currentIndex + 1) % queue.count playWithQueue(queue: queue, index: currentIndex) } //上一曲 func prev() { currentIndex = max(0, currentIndex - 1) playWithQueue(queue: queue, index: currentIndex) } //下一曲按钮点击 @IBAction func nextBtnTapped(_ sender: Any) { next() } //上一曲按钮点击 @IBAction func prevBtnTapped(_ sender: Any) { prev() } //暂停继续按钮点击 @IBAction func pauseBtnTapped(_ sender: Any) { //在暂停和继续两个状态间切换 if self.state == .paused { audioPlayer.resume() }else{ audioPlayer.pause() } } //结束按钮点击 @IBAction func stopBtnTapped(_ sender: Any) { stop() } //定时器响应,更新进度条和时间 func tick() { if state == .playing { //更新进度条进度值 self.playbackSlider!.value = Float(audioPlayer.progress) //一个小算法,来实现00:00这种格式的播放时间 let all:Int=Int(audioPlayer.progress) let m:Int=all % 60 let f:Int=Int(all/60) var time:String="" if f<10{ time="0\(f):" }else { time="\(f)" } if m<10{ time+="0\(m)" }else { time+="\(m)" } //更新播放时间 self.playTime!.text=time } } //拖动进度条改变值时触发 @IBAction func playbackSliderValueChanged(_ sender: Any) { //播放器定位到对应的位置 audioPlayer.seek(toTime: Double(playbackSlider.value)) //如果当前时暂停状态,则继续播放 if state == .paused { audioPlayer.resume() } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }}//Audio Player相关代理方法extension ViewController: STKAudioPlayerDelegate { //开始播放歌曲 func audioPlayer(_ audioPlayer: STKAudioPlayer, didStartPlayingQueueItemId queueItemId: NSObject) { if let index = (queue.index { $0.url == queueItemId as! URL }) { currentIndex = index } } //缓冲完毕 func audioPlayer(_ audioPlayer: STKAudioPlayer, didFinishBufferingSourceWithQueueItemId queueItemId: NSObject) { updateNowPlayingInfoCenter() } //播放状态变化 func audioPlayer(_ audioPlayer: STKAudioPlayer, stateChanged state: STKAudioPlayerState, previousState: STKAudioPlayerState) { self.state = state if state != .stopped && state != .error && state != .disposed { } updateNowPlayingInfoCenter() } //播放结束 func audioPlayer(_ audioPlayer: STKAudioPlayer, didFinishPlayingQueueItemId queueItemId: NSObject, with stopReason: STKAudioPlayerStopReason, andProgress progress: Double, andDuration duration: Double) { if let index = (queue.index { $0.url == audioPlayer.currentlyPlayingQueueItemId() as! URL }) { currentIndex = index } //自动播放下一曲 if stopReason == .eof { next() } else if stopReason == .error { stop() resetAudioPlayer() } } //发生错误 func audioPlayer(_ audioPlayer: STKAudioPlayer, unexpectedError errorCode: STKAudioPlayerErrorCode) { print("Error when playing music \(errorCode)") resetAudioPlayer() playWithQueue(queue: queue, index: currentIndex) } //更新当前播放信息 func updateNowPlayingInfoCenter() { if currentIndex >= 0 { let music = queue[currentIndex] //更新标题 titleLabel.text = "当前播放:\(music.name)" //更新暂停按钮名字 let pauseBtnTitle = self.state == .playing ? "暂停" : "继续" pauseBtn.setTitle(pauseBtnTitle, for: .normal) //设置进度条相关属性 playbackSlider!.maximumValue = Float(audioPlayer.duration) }else{ //停止播放 titleLabel.text = "播放停止!" //更新进度条和时间标签 playbackSlider.value = 0 playTime.text = "--:--" } }}//歌曲类class Music { var name:String var url:URL //类构造函数 init(name:String, url:URL){ self.name = name self.url = url }} |
源码下载:
hangge_1667.zip
原文出自:www.hangge.com 转载请保留原文链接:http://www.hangge.com/blog/cache/detail_1667.html
Swift - 制作一个在线流媒体音乐播放器(使用StreamingKit库)的更多相关文章
- Hide-Music-Player 一个完整的音乐播放器《IT蓝豹》
Hide-Music-Player 一个完整的音乐播放器 Hide-Music-Player 一个完整的音乐播放器,本例子主要包括几个点 (1)摇一摇进入播放器 (2)下拉展开新视图(扫描音乐) (3 ...
- vue——一个页面实现音乐播放器
请忽略下面这段文字年关将至,时间好歹又多出了些许.却不敢过度消遣.岁月未曾饶过我,我亦不想饶过岁月.且将它塞得膨胀,让这一年看似加更充实.不曾料想我一个爱些风花雪月.研墨行歌之人,却做起了碼农这一行当 ...
- 如何用vue打造一个移动端音乐播放器
写在前面 没错,这就是慕课网上的那个vue音乐播放器,后台是某音乐播放器的线上接口扒取,虽然这类项目写的人很多,但不得不说这还是个少有的适合vue提升的好项目,做这个项目除了想写一个比较大并且功能复杂 ...
- 用pyqt5做一个简易的音乐播放器
需求 要求可以读取音频文档,有播放和暂停的功能 附上代码(1)UI界面 # -*- coding: utf-8 -*- # Form implementation generated from rea ...
- JS写一个漂亮的音乐播放器
先放上效果图: 正如图中所展示的播放器那样,我们用HTML+CSS+JS将这个效果实现出来. HTML页面布局 <div class="music"> <div ...
- 使用余弦定理制作磁盘形状h5音乐播放器
目录 [1]功能实现 [2]效果展示 [3]原理说明 旋转原理 余弦定理 [4]代码实现 HTML CSS JS [5]源码查看 功能实现 [1]歌曲播放进度转换成视觉的旋转角度 [2]点击磁盘任意位 ...
- Ubuntu 下一个可用的音乐播放器
参考:http://www.pairsdoll.com/install-audacious-music-palyer-in-ubuntu.html/ 方法:打开terminal,sudo apt-ge ...
- Simple2D-16(音乐播放器)ImGui 库介绍
什么是 ImGui IMGUI (Immediate Mode Graphical User interface),下载地址. ImGui 是一种比较新颖的 GUI 实现模式,适用于显示区域实时刷新的 ...
- HTML+纯JS制作音乐播放器
该篇文章会教你通过JavaScript制作一个简单的音乐播放器.包括播放.暂停.上一曲和下一曲. 阅读本文章你需要对HTML.CSS和Javascript有基本的了解. 话不多说,先上图. emmm. ...
随机推荐
- 基本的Mysql语句
操作文件夹(库) 增 create database db1 charset utf8; 查 # 查看当前创建的数据库 show create database db1; # 查看所有的数据库 sho ...
- selenium对浏览器属性操作的方法
最大化 方法一 //指明ChromeDriver路径 System.setProperty(Src_url_string.Chrome_Driver, Src_url_string.Driver_ad ...
- C++关键字简述
ID 范畴 关键字 说明 1 数据类型 bool 基本类型—-布尔类型 2 数据类型 char 基本类型—-字符类型 3 数据类型 wchar_t 基本类型—-宽字符类型 4 数据类型 double ...
- EditPlus修改主题方法
在“EditPlus.exe”或"EditPlus64.exe"所在的目录下找到"editplus_u.ini"文件(如果不存在就新建一个),修改这个文件即可更 ...
- hdu1507 最大匹配
题目大意: 在 n*m在矩阵中,有一些点被标记为黑色,问可以多少对相邻的没有重复的白色块. 思路: 看上去与二分匹配毫无关系.但是没有其他好的解法,转化为二分匹配是正解.二分匹配的条件是{X,Y|E} ...
- 时间&物质&效率
由于我的家庭是地道的农民家庭,在上学的时候,父母很辛苦的供我读初中,高中,大学. 现在我想说的是,用时间来换取效率是我求学时最大的遗憾. 举一个例子吧:每次回家坐火车,火车很费时间,假如我不缺钱,完全 ...
- 用python(2.7)自定义实现SQL的集合操作
有的时候需要在不同的数据库实例之间做集合操作,这就无法直接使用SQL语句的join,left join了.相同类型的数据库之间虽然也有类似于DBLINK和FEDERATED之类的东西,但一来这些东西不 ...
- Linux 安装MySQL5.7.18
https://dev.mysql.com/downloads/mysql/Linux-Generic md5sum mysql-5.7.18-linux-glibc2.5-x86_64.tar.gz ...
- 团体程序设计天梯赛-练习集-L1-027. 出租
L1-027. 出租 下面是新浪微博上曾经很火的一张图: 一时间网上一片求救声,急问这个怎么破.其实这段代码很简单,index数组就是arr数组的下标,index[0]=2 对应 arr[2]=1,i ...
- 解读:20大5G关键技术
解读:20大5G关键技术 5G网络技术主要分为三类:核心网.回传和前传网络.无线接入网. 核心网 核心网关键技术主要包括:网络功能虚拟化(NFV).软件定义网络(SDN).网络切片和多接入边缘计算(M ...