SwiftAudioPlayer
基于 Swift 的音频播放器,以 AVAudioEngine 为其基础。支持:实时音频操纵,变速(3.5倍、4倍、32倍)、音频音调,以及使用自定义 音频增强 的实时音频操纵。
此播放器是为 播客 设计的。我们最初使用 AVPlayer 播放音频,但想操纵正在流式的音频。我们首先设置了 AVAudioEngine 只是用来播放手机上保存的文件,效果非常好,但 AVAudioEngine 单独不支持像 AVPlayer 那样轻松地进行音频流操作。
因此,使用 AudioToolbox,我们能够流式传输音频并将已下载的数据转换为 AVAudioEngine 可播放的可用数据。关于我们的解决方案概述,请查看我们的 博客文章。
基本功能
- 实时音频操纵,包括最高10倍速度,使用 均衡器和其它操纵
- 使用 AVAudioEngine 流式传输在线音频
- 流式传输广播
- 使用相同API播放本地保存的音频
- 下载音频
- 自动播放队列中的下载和流式音频
- 仅占用 1-2% 的 CPU,以优化您应用程序其余部分的最佳性能
- 您可以将桥接和任何其它 AVAudioEngine 功能安装,以实现像跳过静音这样的酷炫功能
特殊功能
这些是通过此音频引擎支持的社区音频处理功能。您可以实现这些功能的自定义版本,并通过查看 SAPlayerFeatures 了解如何使用库实现这些功能。
- 跳过音频中的静音部分
- 睡眠定时器,在延迟后停止播放音频
- 循环播放流式和已保存的音频
要求
iOS 10.0 及更高版本。
入门
运行示例项目
- 克隆仓库
- CD 到 Example 文件夹,其中包含示例应用程序
- 在终端中运行
pod install
- 构建和运行
安装
SwiftAudioPlayer 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile
pod 'SwiftAudioPlayer'
使用方法
在顶部导入播放器
import SwiftAudioPlayer
重要:对于后台下载的应用,请参阅注意事项。
播放远程音频
let url = URL(string: "https://randomwebsite.com/audio.mp3")!
SAPlayer.shared.startRemoteAudio(withRemoteUrl: url)
SAPlayer.shared.play()
设置锁屏的显示信息
let info = SALockScreenInfo(title: "Random audio", artist: "Foo", artwork: UIImage(), releaseDate: 123456789)
SAPlayer.shared.mediaInfo = info
接收流媒体进度(缓冲进度%)
@IBOutlet weak var bufferProgress: UIProgressView!
override func viewDidLoad() {
super.viewDidLoad()
_ = SAPlayer.Updates.StreamingBuffer.subscribe{ [weak self] buffer in
guard let self = self else { return }
self.bufferProgress.progress = Float(buffer.bufferingProgress)
self.isPlayable = buffer.isReadyForPlaying
}
}
查看更新部分,了解使用详情和其他更新。
对于实时音频操作,使用AVAudioUnit节点。例如,通过UI中的滑块调整混响效果
@IBOutlet weak var reverbSlider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
let node = AVAudioUnitReverb()
SAPlayer.shared.audioModifiers.append(node)
node.wetDryMix = 300
}
@IBAction func reverbSliderChanged(_ sender: Any) {
if let node = SAPlayer.shared.audioModifiers[1] as? AVAudioUnitReverb {
node.wetDryMix = reverbSlider.value
}
}
欲了解更多使用说明,请参阅实时音频操作部分。
更多详细和具体的信息,请查看以下的API文档。
联系信息
问题或疑问
请在GitHub仓库提交任何问题、请求和疑问。
许可证
SwiftAudioPlayer遵循MIT许可证。更多详情请参阅LICENSE文件。
API 详细说明
SAPlayer
通过 SAPlayer.shared
访问播放器及其所有字段和函数。
支持的文件类型
已知的支持文件类型有 .mp3
和 .wav
。
播放音频(基本命令)
要设置播放音频的播放器,可以使用以下任一方式:
startSavedAudio(withSavedUrl url: URL, mediaInfo: SALockScreenInfo?)
播放设备上保存的音频。startRemoteAudio(withRemoteUrl url: URL, bitrate: SAPlayerBitrate, mediaInfo: SALockScreenInfo?)
播放来自远程位置的音频流。
这两者都需要音频位置的URL和一个可选的媒体信息用于显示在锁屏上。对于流媒体音频,您可以设置比特率为 .high
或 .low
。高比特率性能更好,但不适合用于广播流;对于广播流,您应使用低比特率。如果您未设置它,则默认比特率为 .high
。
对于流式远程音频,订阅 SAPlayer.Updates.StreamingBuffer
以获取流进度更新。
可用的基本控制功能
play()
pause()
togglePlayAndPause()
seekTo(seconds: Double)
skipForward()
skipBackwards()
队列音频以自动播放
您可以将远程或本地保存的音频队列排成自动播放。
要排队
SAPlayer.shared.queueSavedAudio(withSavedUrl: C://random_folder/audio.mp3) // or
SAPlayer.shared.queueRemoteAudio(withRemoteUrl: https://randomwebsite.com/audio.mp3)
您还可以从 SAPlayer.shared.audioQueued
直接访问和修改队列。
重要
引擎可以处理速度、音调、效果等各种音频操作。为了实现这一点,在调用初始化方法之前必须最终确定效果节点。有关更多信息,请参阅音频操作文档。
锁屏媒体播放器
更新并设置播放器活动时在锁屏媒体播放器上显示的内容。
用于跳过或后退的间隔时间有skipForwardSeconds
和skipBackwardSeconds
。
mediaInfo
用于在锁屏上显示音频信息。类型为SALockScreenInfo
,包含
title: String
artist: String
artwork: UIImage?
releaseDate: UTC // Int
playbackRateOfAudioChanged(rate: Float)
用于更新锁屏媒体播放器音频播放速度已更改。
SAPlayer.Downloader
使用下载器功能从远程位置保存音频文件,以供将来离线播放。
音频文件会在设备上以自定义命名方案保存,并且可以使用文件的原始远程URL进行恢复。
背景下载的重要一步
为了确保您的应用程序将在后台继续下载音频,请确保将以下内容添加到 AppDelegate.swift
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
SAPlayer.Downloader.setBackgroundCompletionHandler(completionHandler)
}
下载
当从URL流式传输音频时,所有下载将暂停。流式传输完成后将自动恢复。
使用以下代码开始后台下载音频
func downloadAudio(withRemoteUrl url: URL, completion: @escaping (_ savedUrl: URL) -> ())
成功下载后,它将调用您传递的完成处理程序,并在设备上提供已下载文件的存储位置。
订阅 SAPlayer.Updates.AudioDownloading
以获取下载进度更新。
并使用以下代码停止任何活动或防止未来下载相应的远程URL
func cancelDownload(withRemoteUrl url: URL)
默认情况下,允许使用蜂窝数据下载。如果您希望关闭此选项,请设置
SAPlayer.Downloader.allowUsingCellularData = false
您也可以通过 allowUsingCellularData
来检索您为移动数据下载设置的偏好。
管理已下载内容
使用以下操作来管理已下载的音频文件。
检查是否已下载
func isDownloaded(withRemoteUrl url: URL) -> Bool
获取设备上保存的与远程位置对应的音频文件的URL
func getSavedUrl(forRemoteUrl url: URL) -> URL?
如果存在,则删除已下载的音频
func deleteDownloaded(withSavedUrl url: URL)
注意:当您不再需要下载时,应由您负责清除下载
SAPlayer.Updates
接收到有关播放器值更改的更新,例如音频时长、已播放时间、下载进度等。
所有更新订阅功能均采用以下形式
func subscribe(_ closure: @escaping (_ payload: <Payload>) -> ()) -> UInt
closure
:将接收更新的闭包。建议对使用这些函数的类具有弱引用。payload
:更新的值。- 返回:如果您想取消订阅闭包的更新,则返回订阅的id。
有时还有
url
:更新对应的远程URL。在这种情况下,可能会观察多个文件,例如一次性下载多个文件。
退出订阅的形式类似
func unsubscribe(_ id: UInt)
id
:具有此id的闭包将停止接收更新。
ElapsedTime
负载 = Double
当前初始化音频的时间戳/已播放时间的变化。即音频的剪辑指针应指向的位置。
订阅此更新以在音频播放的部分位置变化时更新视图。
Duration
负载 = Double
当前初始化音频的时长变化。特别适用于正在流式传输且可能随更多数据而变化的音频。引擎会尽力猜测音频的时长。猜测会随着从网络上流出的字节数增加而变得更好。
播放状态
有效载荷 = SAPlayingStatus
玩家播放状态的变更。可能是以下4种之一:播放中
、暂停
、缓冲
、结束
(音频播放结束)。
流媒体缓冲
有效载荷 = SAAudioAvailabilityRange
流媒体音频下载进度的变更。包括可用音频范围和音频是否可播放的信息。查看SAAudioAvailabilityRange以获取更多信息。
要查看保存到手机以供以后播放的音频的下载进度,请参阅AudioDownloading。
音频下载
负载 = Double
后台音频下载进度的变更。这不对应于流媒体下载进度,请参阅StreamingBuffer以查看流媒体进度。
音频队列
有效载荷 = URL
即将播放的音频URL通知。此URL可能是远程的或本地保存的。
音频效果
实时音频处理
播放器上的所有音频效果都通过AVAudioUnit节点来完成。这包括添加混响、改变音调和播放速度以及添加失真。效果列表的完整信息请在此处查看。
要使用的效果以节点列表的形式存储在audioModifiers
中。这些节点的顺序是引擎将它们附加到彼此的顺序。
注意:默认情况下,SAPlayer
从多个节点开始,有一个AVAudioUnitTimePitch节点,该节点设置为在改变音频速率的同时不改变音频的音调(用于改变语音的速率)。
重要
在调用initializeSavedAudio(...)
或initializeRemoteAudio(...)
之前,必须先最终确定所有要在播放的音频上使用的节点。在调用给定的音频文件后对节点列表所做的任何更改将不会反映在播放中。
一旦所有节点都添加到audioModifiers
中,且播放器已初始化,对节点所做的任何操作都将实时执行。示例应用展示了如何实时更改播放速度。
let speed = rateSlider.value
if let node = SAPlayer.shared.audioModifiers[0] as? AVAudioUnitTimePitch {
node.rate = speed
SAPlayer.shared.playbackRateOfAudioChanged(rate: speed)
}
注意:如果改变了音频的速率,也应调用playbackRateOfAudioChanged
以更新锁定屏幕的媒体播放器。