自动播放 Swift 中的音频文件
Auto play audio files in Swift
我正在制作一个非常简单的应用程序,用户可以在其中 select 一些他想播放的音频文件。
然后,他按下播放按钮,它会一个接一个地播放所有 selected 的文件。
为此,我创建了一个数组来存储用户想要播放的文件的名称。然后,由播放按钮触发的函数将对数组进行迭代,查找名称并播放文件。
是这样的:
//declaring the audioplayer
var audioPlayer = AVAudioPlayer()
//declaring the array
var selectedMusic = [String]()
该界面有 6 个按钮,每个按钮都链接到特定的音乐。用户可以通过点击按钮立即触发音乐,或者通过长按进行 selection 连续播放。让我们假设用户得到了一个 selection 并且数组看起来像这样:
selectedMusic = ["Song 1", "Song 5", "Song 3", "Song 2"]
我播放歌曲的功能是:
for selection in selectedMusic {
if selection == "Song 1" {
guard let alertSound = Bundle.main.url(forResource: "Song 1", withExtension: "mp3") else {return}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
audioPlayer = try AVAudioPlayer(contentsOf: alertSound)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch let error {
print(error.localizedDescription)
}
} else if selection == "Song 2" {
guard let alertSound = Bundle.main.url(forResource: "Song 2", withExtension: "mp3") else {return}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
audioPlayer = try AVAudioPlayer(contentsOf: alertSound)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch let error {
print(error.localizedDescription)
}
等等,直到第 5 首歌。
我想要的是以特定顺序(1 到 5)播放 selected 歌曲,而不是用户选择的顺序(这很重要)。
然而,这个函数没有给出预期的结果,它只是播放 selection 的最后一个项目。
那么,我应该如何完成这项工作?阵列不是这里的最佳选择吗?
正如我提到的,歌曲按时间顺序播放是强制性的。
任何帮助将不胜感激:)
谢谢!
首先,您正在使用 for 并重复其中的代码。理论上您可以这样做
audioUrls.forEach { (url) in
guard let alertSound = Bundle.main.url(forResource: url, withExtension: "mp3") else {return}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
audioPlayer = try AVAudioPlayer(contentsOf: alertSound)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch let error {
print(error.localizedDescription)
}
}
其次,您没有跟踪音频,因此您的程序不知道曲目已播放完毕,并且您正在用新对象覆盖播放器。
例如,在下面的代码中,我正在跟踪我的音频播放器并使用当前时间更新标签。
func keepTrackOfAudio() {
audioPlayer?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)
//track progress
let interval = CMTime(value: 1, timescale: 2)
audioPlayer?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main , using: { (progressTime) in
let seconds = CMTimeGetSeconds(progressTime)
let secondsString = String(format: "%02d", Int(seconds.truncatingRemainder(dividingBy: 60)))
let minutesString = String(format: "%02d", Int(seconds / 60))
self.audioCurrentTimeLabel.text = "\(minutesString):\(secondsString)"
//lets move the slider thumb
if let duration = self.audioPlayer?.currentItem?.duration {
let durationSeconds = CMTimeGetSeconds(duration)
self.audioSlider.value = Float(seconds / durationSeconds)
}
})
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if let duration = audioPlayer?.currentItem?.duration {
let seconds = CMTimeGetSeconds(duration)
let secondsText = String(format: "%02d", Int(seconds) % 60)
let minutesText = String(format: "%02d", Int(seconds) / 60)
audioLengthLabel.text = "\(minutesText):\(secondsText)"
}
}
}
你的作业是计算音频何时结束,然后才播放下一首曲目。
我正在制作一个非常简单的应用程序,用户可以在其中 select 一些他想播放的音频文件。 然后,他按下播放按钮,它会一个接一个地播放所有 selected 的文件。
为此,我创建了一个数组来存储用户想要播放的文件的名称。然后,由播放按钮触发的函数将对数组进行迭代,查找名称并播放文件。
是这样的:
//declaring the audioplayer
var audioPlayer = AVAudioPlayer()
//declaring the array
var selectedMusic = [String]()
该界面有 6 个按钮,每个按钮都链接到特定的音乐。用户可以通过点击按钮立即触发音乐,或者通过长按进行 selection 连续播放。让我们假设用户得到了一个 selection 并且数组看起来像这样:
selectedMusic = ["Song 1", "Song 5", "Song 3", "Song 2"]
我播放歌曲的功能是:
for selection in selectedMusic {
if selection == "Song 1" {
guard let alertSound = Bundle.main.url(forResource: "Song 1", withExtension: "mp3") else {return}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
audioPlayer = try AVAudioPlayer(contentsOf: alertSound)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch let error {
print(error.localizedDescription)
}
} else if selection == "Song 2" {
guard let alertSound = Bundle.main.url(forResource: "Song 2", withExtension: "mp3") else {return}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
audioPlayer = try AVAudioPlayer(contentsOf: alertSound)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch let error {
print(error.localizedDescription)
}
等等,直到第 5 首歌。
我想要的是以特定顺序(1 到 5)播放 selected 歌曲,而不是用户选择的顺序(这很重要)。
然而,这个函数没有给出预期的结果,它只是播放 selection 的最后一个项目。
那么,我应该如何完成这项工作?阵列不是这里的最佳选择吗? 正如我提到的,歌曲按时间顺序播放是强制性的。
任何帮助将不胜感激:) 谢谢!
首先,您正在使用 for 并重复其中的代码。理论上您可以这样做
audioUrls.forEach { (url) in
guard let alertSound = Bundle.main.url(forResource: url, withExtension: "mp3") else {return}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
audioPlayer = try AVAudioPlayer(contentsOf: alertSound)
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch let error {
print(error.localizedDescription)
}
}
其次,您没有跟踪音频,因此您的程序不知道曲目已播放完毕,并且您正在用新对象覆盖播放器。
例如,在下面的代码中,我正在跟踪我的音频播放器并使用当前时间更新标签。
func keepTrackOfAudio() {
audioPlayer?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)
//track progress
let interval = CMTime(value: 1, timescale: 2)
audioPlayer?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main , using: { (progressTime) in
let seconds = CMTimeGetSeconds(progressTime)
let secondsString = String(format: "%02d", Int(seconds.truncatingRemainder(dividingBy: 60)))
let minutesString = String(format: "%02d", Int(seconds / 60))
self.audioCurrentTimeLabel.text = "\(minutesString):\(secondsString)"
//lets move the slider thumb
if let duration = self.audioPlayer?.currentItem?.duration {
let durationSeconds = CMTimeGetSeconds(duration)
self.audioSlider.value = Float(seconds / durationSeconds)
}
})
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if let duration = audioPlayer?.currentItem?.duration {
let seconds = CMTimeGetSeconds(duration)
let secondsText = String(format: "%02d", Int(seconds) % 60)
let minutesText = String(format: "%02d", Int(seconds) / 60)
audioLengthLabel.text = "\(minutesText):\(secondsText)"
}
}
}
你的作业是计算音频何时结束,然后才播放下一首曲目。