本文是Intermediate iOS 11 Programming with Swift 4系列 的 第 十 篇.
10.1
iOS SDK提供了多种框架,可以让你在应用中使用声音。你可以用来播放和录制音频文件的框架之一是AV Foundation框架。在这一章,我将带你通过基本的框架,并向你展示如何管理音频回放和录音.
AV Foundation为开发者提供了必要的api来处理iOS上的音频。在这个demo中,我们主要使用框架的这两个类:
AVAudioPlayer - 把它想象成一个播放声音文件的音频播放器。通过使用播放器,您可以在iOS中播放任何持续时间和音频格式的声音
AVAudioRecorder - 一个用来记录音频的录音机。
Demo
为了了解如何使用API,我们将构建一个简单的音频应用程序,允许用户录制和播放音频。我们的主要关注点是演示AVFoundation框架,这样应用程序的用户界面就会非常简单。
首先,使用 Single View Application 模板创建一个应用程序,并将其命名为RecordPro. 您可以自己设计一个类似于图10.1的用户界面。然而,要让您免于设置用户界面和自定义类,您可以从这里下载模板! 界面很简单, 只有3个按钮: 录音, 暂停, 和播放.
它也有一个计时器来显示录制期间经过的时间。这些按钮已经连接到RecordProController类中相应的动作方法,而RecordProController类是UIViewController的一个子类.
10.1 demo在我们进入到实现之前,让我给你一个更好的关于演示应用程序如何工作的想法:
* 当用户点击录制按钮时,应用程序启动计时器并开始录制音频。然后,记录按钮被暂停按钮取代。如果用户点击暂停按钮,应用程序将暂停录制,直到用户再次点击按钮。在编码方面,它调用记录操 作方法
* 当用户点击停止按钮时,应用程序会停止录制。我已经把按钮和RecordProController中的stop动作方法连接起来了。
* 要播放录音,用户可以点击播放按钮,这是与播放方法相关联的。
AVAudioRecorder
AVAudioRecorder类的AV Foundation框架允许您的应用程序提供音频录制功能。在iOS中,录制的音频来自iOS设备的内置麦克风或耳机麦克风。这些设备包括iPhone、iPad或iPod touch。
首先,让我们看看如何使用AVAudioRecorder类来记录音频。与SDK中的大多数api一样,AVAudioRecorder使用了delegate模式。您可以为音频记录器实现delegate对象,以响应音频中断并完成录制。AVAudioRecorder对象的委托必须采用AVAudioRecorderDelegate协议.
可以写个Extension:
extension RecorderProController: AVAudioRecorderDelegate {
}
记得导入AV Foundation 框架 !
声明 AVAudioRecorder 和 AVAudioPlayer的实例变量
var audioRecorder: AVAudioRecorder ?
var audioPlayer: AVAudioPlayer?
让我们先关注AVAudioRecorder。稍后我们将使用audioPlayer变量。AVAudioRecorder类提供了一种在应用程序中记录声音的简单方法。
* 指定一个声音文件URL
* 设置一个音频会话
* 配置录音机的初始状态
我们将创建一个名为configure()的私有方法来进行设置。将代码插入RecordProController类中
直接上代码:
private func configure() {
// Disable Stop/Play button when application launches
stopButton.isEnabled = false
playButton.isEnabled = false
// Get the document directory. If fails, just skip the rest of the code
guard let directoryURL = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first else {
let alertMessage = UIAlertController(title: "Error", message: "Failed to get the document directory for recording the “audio. Please try again later.", preferredStyle: .alert)
alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertMessage, animated: true, completion: nil)
return
}
// Set the default audio file
let audioFileURL = directoryURL.appendingPathComponent("MyAudioMemo.m4a")
// Setup audio session
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, with: AVAudioSessionCategoryOptions.defaultToSpeaker)
// Define the recorder setting
let recorderSetting: [String: Any] = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
“ AVSampleRateKey: 44100.0,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
// Initiate and prepare the recorder
audioRecorder = try AVAudioRecorder(url: audioFileURL, settings: recorderSetting)
audioRecorder.delegate = self
audioRecorder.isMeteringEnabled = true
audioRecorder.prepareToRecord()
} catch {
print(error)
}
}
接下来看一看 录音按钮的 实现
当用户点击录制按钮时,应用程序将开始录制。录制按钮将被更改为暂停按钮。如果用户点击暂停按钮,应用程序将暂停音频录制,直到再次点击按钮。当用户点击“停止”按钮时,录音就会停止
代码如下 :
@IBAction func record(sender: UIButton) {
// Stop the audio player before recording
if let player = audioPlayer, player.isPlaying {
player.stop()
}
if !audioRecorder.isRecording {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
// Start recording
audioRecorder.record()
// Change to the Pause image
recordButton.setImage(UIImage(named: "Pause"), for: UIControlState.normal)
} catch {
print(error)
}
} else {
// Pause recording
audioRecorder.pause()
// Change to the Record image
recordButton.setImage(UIImage(named: "Record"), for: UIControlState.normal)
}
stopButton.isEnabled = true
playButton.isEnabled = false
}
当然别忘 在 info.plist 里面 加入访问权限
访问权限暂停按钮的实现
当用户点击停止按钮时,会调用停止动作方法。这个方法很简单。我们首先重置按钮的状态,然后调用AVAudioRecorder对象的stop方法来停止录制。最后,我们关闭音频会话
代码如下 :
@IBAction func stop(sender: UIButton) {
recordButton.setImage(UIImage(named: "Record"), for: UIControlState.normal)
recordButton.isEnabled = true
stopButton.isEnabled = false
playButton.isEnabled = true
// Stop the audio recorder
audioRecorder?.stop()
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(false)
} catch {
print(error)
}
}
实现 AVAudioRecorderDelegate 协议
你可以使用AVAudioRecorderDelegate协议来处理音频中断(比如,录音期间的电话)以及完成录音。在本例中,RecordProController是委托。AVAudioRecorderDelegate协议中定义的方法是可选的。为了演示目的,我们将只实现audioRecorderDidFinishRecording(_:successful:)方法来处理记录的完成.
代码如下 :
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
if flag {
let alertMessage = UIAlertController(title: "Finish Recording", message: "Successfully recorded the audio!", preferredStyle: .alert)
alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertMessage, animated: true, completion: nil)
}
}
实现 AVAudioPlayerDelegate 协议
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
playButton.isSelected = false
let alertMessage = UIAlertController(title: "Finish Playing", message: "Finish playing the recording!", preferredStyle: .alert)
alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertMessage, animated: true, completion: nil)
}
最后实现 定时器
private var timer: Timer?
private var elapsedTimeInSecond: Int = 0
func startTimer() {
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (timer) in
self.elapsedTimeInSecond += 1
self.updateTimeLabel()
})
}
func pauseTimer() {
timer?.invalidate()
}
func resetTimer() {
timer?.invalidate()
elapsedTimeInSecond = 0
updateTimeLabel()
}
func updateTimeLabel() {
let seconds = elapsedTimeInSecond % 60
let minutes = (elapsedTimeInSecond / 60) % 60
timeLabel.text = String(format: "%02d:%02d", minutes, seconds)
}
demo 截图
网友评论