Intermediate iOS 11 Programming with Swift(十): 音頻錄制和回放

本文是Intermediate iOS 11 Programming with Swift 4系列?的 第 十 篇.

10.1

iOS SDK提供了多種框架,可以讓你在應(yīng)用中使用聲音。你可以用來播放和錄制音頻文件的框架之一是AV Foundation框架。在這一章,我將帶你通過基本的框架,并向你展示如何管理音頻回放和錄音.

AV Foundation為開發(fā)者提供了必要的api來處理iOS上的音頻。在這個demo中,我們主要使用框架的這兩個類:

AVAudioPlayer - 把它想象成一個播放聲音文件的音頻播放器。通過使用播放器,您可以在iOS中播放任何持續(xù)時間和音頻格式的聲音

AVAudioRecorder - 一個用來記錄音頻的錄音機(jī)。


Demo

為了了解如何使用API,我們將構(gòu)建一個簡單的音頻應(yīng)用程序,允許用戶錄制和播放音頻。我們的主要關(guān)注點(diǎn)是演示AVFoundation框架,這樣應(yīng)用程序的用戶界面就會非常簡單。

首先,使用 Single View Application 模板創(chuàng)建一個應(yīng)用程序,并將其命名為RecordPro. 您可以自己設(shè)計一個類似于圖10.1的用戶界面。然而,要讓您免于設(shè)置用戶界面和自定義類,您可以從這里下載模板!? 界面很簡單, 只有3個按鈕: 錄音, 暫停, 和播放.?

它也有一個計時器來顯示錄制期間經(jīng)過的時間。這些按鈕已經(jīng)連接到RecordProController類中相應(yīng)的動作方法,而RecordProController類是UIViewController的一個子類.?

10.1 demo

在我們進(jìn)入到實現(xiàn)之前,讓我給你一個更好的關(guān)于演示應(yīng)用程序如何工作的想法:

?

* 當(dāng)用戶點(diǎn)擊錄制按鈕時,應(yīng)用程序啟動計時器并開始錄制音頻。然后,記錄按鈕被暫停按鈕取代。如果用戶點(diǎn)擊暫停按鈕,應(yīng)用程序?qū)和d浿疲钡接脩粼俅吸c(diǎn)擊按鈕。在編碼方面,它調(diào)用記錄操 作方法

* 當(dāng)用戶點(diǎn)擊停止按鈕時,應(yīng)用程序會停止錄制。我已經(jīng)把按鈕和RecordProController中的stop動作方法連接起來了。

* 要播放錄音,用戶可以點(diǎn)擊播放按鈕,這是與播放方法相關(guān)聯(lián)的。


AVAudioRecorder

AVAudioRecorder類的AV Foundation框架允許您的應(yīng)用程序提供音頻錄制功能。在iOS中,錄制的音頻來自iOS設(shè)備的內(nèi)置麥克風(fēng)或耳機(jī)麥克風(fēng)。這些設(shè)備包括iPhone、iPad或iPod touch。

首先,讓我們看看如何使用AVAudioRecorder類來記錄音頻。與SDK中的大多數(shù)api一樣,AVAudioRecorder使用了delegate模式。您可以為音頻記錄器實現(xiàn)delegate對象,以響應(yīng)音頻中斷并完成錄制。AVAudioRecorder對象的委托必須采用AVAudioRecorderDelegate協(xié)議.?

可以寫個Extension:

extension RecorderProController:?AVAudioRecorderDelegate {?

}?

記得導(dǎo)入AV Foundation 框架 !? ?

聲明 AVAudioRecorder 和 AVAudioPlayer的實例變量

var audioRecorder:??AVAudioRecorder ?

var audioPlayer: AVAudioPlayer?

讓我們先關(guān)注AVAudioRecorder。稍后我們將使用audioPlayer變量。AVAudioRecorder類提供了一種在應(yīng)用程序中記錄聲音的簡單方法。

?* 指定一個聲音文件URL

?* 設(shè)置一個音頻會話

?* 配置錄音機(jī)的初始狀態(tài)

我們將創(chuàng)建一個名為configure()的私有方法來進(jìn)行設(shè)置。將代碼插入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)

? ? }

}

接下來看一看 錄音按鈕的 實現(xiàn)

當(dāng)用戶點(diǎn)擊錄制按鈕時,應(yīng)用程序?qū)㈤_始錄制。錄制按鈕將被更改為暫停按鈕。如果用戶點(diǎn)擊暫停按鈕,應(yīng)用程序?qū)和R纛l錄制,直到再次點(diǎn)擊按鈕。當(dāng)用戶點(diǎn)擊“停止”按鈕時,錄音就會停止

代碼如下 :

@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

}



當(dāng)然別忘 在 info.plist 里面 加入訪問權(quán)限??

訪問權(quán)限



暫停按鈕的實現(xiàn)??

當(dāng)用戶點(diǎn)擊停止按鈕時,會調(diào)用停止動作方法。這個方法很簡單。我們首先重置按鈕的狀態(tài),然后調(diào)用AVAudioRecorder對象的stop方法來停止錄制。最后,我們關(guān)閉音頻會話

代碼如下 :?

@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)

? ? }

}

實現(xiàn) AVAudioRecorderDelegate 協(xié)議

你可以使用AVAudioRecorderDelegate協(xié)議來處理音頻中斷(比如,錄音期間的電話)以及完成錄音。在本例中,RecordProController是委托。AVAudioRecorderDelegate協(xié)議中定義的方法是可選的。為了演示目的,我們將只實現(xiàn)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)

? ? ? ? }

? ? }

實現(xiàn) AVAudioPlayerDelegate 協(xié)議

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)

? ? }


最后實現(xiàn) 定時器?

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 截圖?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容