[英]Recording audio in Swift
有誰知道我在哪里可以找到有關如何在 Swift 應用程序中錄制音頻的信息? 我一直在查看一些音頻播放示例,但我似乎無法找到任何關於實現錄音的內容。 謝謝
這是代碼。您可以輕松記錄。在IBAction
上編寫此代碼。它將以名稱recordTest.caf
將記錄保存在Documents
。
//declare instance variable
var audioRecorder:AVAudioRecorder!
func record(){
var audioSession:AVAudioSession = AVAudioSession.sharedInstance()
audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, error: nil)
audioSession.setActive(true, error: nil)
var documents: AnyObject = NSSearchPathForDirectoriesInDomains( NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
var str = documents.stringByAppendingPathComponent("recordTest.caf")
var url = NSURL.fileURLWithPath(str as String)
var recordSettings = [AVFormatIDKey:kAudioFormatAppleIMA4,
AVSampleRateKey:44100.0,
AVNumberOfChannelsKey:2,AVEncoderBitRateKey:12800,
AVLinearPCMBitDepthKey:16,
AVEncoderAudioQualityKey:AVAudioQuality.Max.rawValue]
println("url : \(url)")
var error: NSError?
audioRecorder = AVAudioRecorder(URL:url, settings: recordSettings, error: &error)
if let e = error {
println(e.localizedDescription)
} else {
audioRecorder.record()
}
}
在Swift 3中
密鑰 =隱私-麥克風使用說明和值 =用於使用麥克風
(如果您不提供該值,則應用程序將崩潰-說明您請求權限的原因)**
導入AVFoundation和AVAudioRecorderDelegate,AVAudioPlayerDelegate
import AVFoundation class RecordVC: UIViewController , AVAudioRecorderDelegate, AVAudioPlayerDelegate
創建用於錄制音頻和播放音頻的按鈕,以及用於顯示錄制時間的標簽,並為出口和動作指定start_recording,play_recording並聲明一些變量,稍后我們將使用它們
@IBOutlet var recordingTimeLabel: UILabel! @IBOutlet var record_btn_ref: UIButton! @IBOutlet var play_btn_ref: UIButton! var audioRecorder: AVAudioRecorder! var audioPlayer : AVAudioPlayer! var meterTimer:Timer! var isAudioRecordingGranted: Bool! var isRecording = false var isPlaying = false
在viewDidLoad中檢查記錄權限
override func viewDidLoad() { super.viewDidLoad() check_record_permission() } func check_record_permission() { switch AVAudioSession.sharedInstance().recordPermission() { case AVAudioSessionRecordPermission.granted: isAudioRecordingGranted = true break case AVAudioSessionRecordPermission.denied: isAudioRecordingGranted = false break case AVAudioSessionRecordPermission.undetermined: AVAudioSession.sharedInstance().requestRecordPermission({ (allowed) in if allowed { self.isAudioRecordingGranted = true } else { self.isAudioRecordingGranted = false } }) break default: break } }
生成要將記錄另存為myRecording.m4a的路徑
func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let documentsDirectory = paths[0] return documentsDirectory } func getFileUrl() -> URL { let filename = "myRecording.m4a" let filePath = getDocumentsDirectory().appendingPathComponent(filename) return filePath }
設置錄音機
func setup_recorder() { if isAudioRecordingGranted { let session = AVAudioSession.sharedInstance() do { try session.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker) try session.setActive(true) let settings = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 44100, AVNumberOfChannelsKey: 2, AVEncoderAudioQualityKey:AVAudioQuality.high.rawValue ] audioRecorder = try AVAudioRecorder(url: getFileUrl(), settings: settings) audioRecorder.delegate = self audioRecorder.isMeteringEnabled = true audioRecorder.prepareToRecord() } catch let error { display_alert(msg_title: "Error", msg_desc: error.localizedDescription, action_title: "OK") } } else { display_alert(msg_title: "Error", msg_desc: "Don't have access to use your microphone.", action_title: "OK") } }
當按鈕start_recording按下並使用updateAudioMeter顯示秒數時,開始錄制;如果開始錄制,則結束錄制
@IBAction func start_recording(_ sender: UIButton) { if(isRecording) { finishAudioRecording(success: true) record_btn_ref.setTitle("Record", for: .normal) play_btn_ref.isEnabled = true isRecording = false } else { setup_recorder() audioRecorder.record() meterTimer = Timer.scheduledTimer(timeInterval: 0.1, target:self, selector:#selector(self.updateAudioMeter(timer:)), userInfo:nil, repeats:true) record_btn_ref.setTitle("Stop", for: .normal) play_btn_ref.isEnabled = false isRecording = true } } func updateAudioMeter(timer: Timer) { if audioRecorder.isRecording { let hr = Int((audioRecorder.currentTime / 60) / 60) let min = Int(audioRecorder.currentTime / 60) let sec = Int(audioRecorder.currentTime.truncatingRemainder(dividingBy: 60)) let totalTimeString = String(format: "%02d:%02d:%02d", hr, min, sec) recordingTimeLabel.text = totalTimeString audioRecorder.updateMeters() } } func finishAudioRecording(success: Bool) { if success { audioRecorder.stop() audioRecorder = nil meterTimer.invalidate() print("recorded successfully.") } else { display_alert(msg_title: "Error", msg_desc: "Recording failed.", action_title: "OK") } }
播放錄音
func prepare_play() { do { audioPlayer = try AVAudioPlayer(contentsOf: getFileUrl()) audioPlayer.delegate = self audioPlayer.prepareToPlay() } catch{ print("Error") } } @IBAction func play_recording(_ sender: Any) { if(isPlaying) { audioPlayer.stop() record_btn_ref.isEnabled = true play_btn_ref.setTitle("Play", for: .normal) isPlaying = false } else { if FileManager.default.fileExists(atPath: getFileUrl().path) { record_btn_ref.isEnabled = false play_btn_ref.setTitle("pause", for: .normal) prepare_play() audioPlayer.play() isPlaying = true } else { display_alert(msg_title: "Error", msg_desc: "Audio file is missing.", action_title: "OK") } } }
錄制完成后,啟用播放按鈕;播放完成后,啟用錄制按鈕
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { if !flag { finishAudioRecording(success: false) } play_btn_ref.isEnabled = true } func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { record_btn_ref.isEnabled = true }
通用顯示警報功能
func display_alert(msg_title : String , msg_desc : String ,action_title : String) { let ac = UIAlertController(title: msg_title, message: msg_desc, preferredStyle: .alert) ac.addAction(UIAlertAction(title: action_title, style: .default) { (result : UIAlertAction) -> Void in _ = self.navigationController?.popViewController(animated: true) }) present(ac, animated: true) }
@codester的答案的Swift2版本。
func record() {
//init
let audioSession:AVAudioSession = AVAudioSession.sharedInstance()
//ask for permission
if (audioSession.respondsToSelector("requestRecordPermission:")) {
AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in
if granted {
print("granted")
//set category and activate recorder session
try! audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
try! audioSession.setActive(true)
//get documnets directory
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let fullPath = documentsDirectory.stringByAppendingPathComponent("voiceRecording.caf")
let url = NSURL.fileURLWithPath(fullPath)
//create AnyObject of settings
let settings: [String : AnyObject] = [
AVFormatIDKey:Int(kAudioFormatAppleIMA4), //Int required in Swift2
AVSampleRateKey:44100.0,
AVNumberOfChannelsKey:2,
AVEncoderBitRateKey:12800,
AVLinearPCMBitDepthKey:16,
AVEncoderAudioQualityKey:AVAudioQuality.Max.rawValue
]
//record
try! self.audioRecorder = AVAudioRecorder(URL: url, settings: settings)
} else{
print("not granted")
}
})
}
}
除了以前的答案外,我嘗試使其在Xcode 7.2上運行,並且之后通過電子郵件發送文件時也聽不到任何聲音。 沒有警告或異常。 因此,我將設置更改為以下內容並存儲為.m4a文件。
let recordSettings = [AVSampleRateKey : NSNumber(float: Float(44100.0)),
AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)),
AVNumberOfChannelsKey : NSNumber(int: 1),
AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Medium.rawValue))]
之后,我可以聽聲音了。 為了保存文件,我在viewDidLoad上添加了它以初始化記錄器:
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
try audioRecorder = AVAudioRecorder(URL: self.directoryURL()!,
settings: recordSettings)
audioRecorder.prepareToRecord()
} catch {
}
並用於創建目錄:
func directoryURL() -> NSURL? {
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let documentDirectory = urls[0] as NSURL
let soundURL = documentDirectory.URLByAppendingPathComponent("sound.m4a")
return soundURL
}
我還添加了用於開始錄制,停止和播放之后的操作
@IBAction func doRecordAction(sender: AnyObject) {
if !audioRecorder.recording {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
audioRecorder.record()
} catch {
}
}
}
@IBAction func doStopRecordingAction(sender: AnyObject) {
audioRecorder.stop()
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(false)
} catch {
}
}
@IBAction func doPlayAction(sender: AnyObject) {
if (!audioRecorder.recording){
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: audioRecorder.url)
audioPlayer.play()
} catch {
}
}
}
這是用Swift 4.2編寫的具有簡單界面的錄音機。
final class AudioRecorderImpl: NSObject {
private let session = AVAudioSession.sharedInstance()
private var player: AVAudioPlayer?
private var recorder: AVAudioRecorder?
private lazy var permissionGranted = false
private lazy var isRecording = false
private lazy var isPlaying = false
private var fileURL: URL?
private let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey:AVAudioQuality.high.rawValue
]
override init() {
fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("note.m4a")
}
func record(to url: URL?) {
guard permissionGranted,
let url = url ?? fileURL else { return }
setupRecorder(url: url)
if isRecording {
stopRecording()
}
isRecording = true
recorder?.record()
}
func stopRecording() {
isRecording = false
recorder?.stop()
try? session.setActive(false)
}
func play(from url: URL?) {
guard let url = url ?? fileURL else { return }
setupPlayer(url: url)
if isRecording {
stopRecording()
}
if isPlaying {
stopPlaying()
}
if FileManager.default.fileExists(atPath: url.path) {
isPlaying = true
setupPlayer(url: url)
player?.play()
}
}
func stopPlaying() {
player?.stop()
}
func pause() {
player?.pause()
}
func resume() {
if player?.isPlaying == false {
player?.play()
}
}
func checkPermission(completion: ((Bool) -> Void)?) {
func assignAndInvokeCallback(_ granted: Bool) {
self.permissionGranted = granted
completion?(granted)
}
switch session.recordPermission {
case .granted:
assignAndInvokeCallback(true)
case .denied:
assignAndInvokeCallback(false)
case .undetermined:
session.requestRecordPermission(assignAndInvokeCallback)
}
}
}
extension AudioRecorderImpl: AVAudioRecorderDelegate, AVAudioPlayerDelegate {
}
private extension AudioRecorderImpl {
func setupRecorder(url: URL) {
guard
permissionGranted else { return }
try? session.setCategory(.playback, mode: .default)
try? session.setActive(true)
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
recorder = try? AVAudioRecorder(url: url, settings: settings)
recorder?.delegate = self
recorder?.isMeteringEnabled = true
recorder?.prepareToRecord()
}
func setupPlayer(url: URL) {
player = try? AVAudioPlayer(contentsOf: url)
player?.delegate = self
player?.prepareToPlay()
}
}
Swift 3代碼版本:完整的音頻錄制解決方案!
import UIKit
import AVFoundation
class ViewController: UIViewController, AVAudioRecorderDelegate {
//Outlets
@IBOutlet weak var recordingTimeLabel: UILabel!
//Variables
var audioRecorder: AVAudioRecorder!
var meterTimer:Timer!
var isAudioRecordingGranted: Bool!
override func viewDidLoad() {
super.viewDidLoad()
switch AVAudioSession.sharedInstance().recordPermission() {
case AVAudioSessionRecordPermission.granted:
isAudioRecordingGranted = true
break
case AVAudioSessionRecordPermission.denied:
isAudioRecordingGranted = false
break
case AVAudioSessionRecordPermission.undetermined:
AVAudioSession.sharedInstance().requestRecordPermission() { [unowned self] allowed in
DispatchQueue.main.async {
if allowed {
self.isAudioRecordingGranted = true
} else {
self.isAudioRecordingGranted = false
}
}
}
break
default:
break
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
audioRecorder = nil
}
//MARK:- Audio recorder buttons action.
@IBAction func audioRecorderAction(_ sender: UIButton) {
if isAudioRecordingGranted {
//Create the session.
let session = AVAudioSession.sharedInstance()
do {
//Configure the session for recording and playback.
try session.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker)
try session.setActive(true)
//Set up a high-quality recording session.
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
//Create audio file name URL
let audioFilename = getDocumentsDirectory().appendingPathComponent("audioRecording.m4a")
//Create the audio recording, and assign ourselves as the delegate
audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
audioRecorder.delegate = self
audioRecorder.isMeteringEnabled = true
audioRecorder.record()
meterTimer = Timer.scheduledTimer(timeInterval: 0.1, target:self, selector:#selector(self.updateAudioMeter(timer:)), userInfo:nil, repeats:true)
}
catch let error {
print("Error for start audio recording: \(error.localizedDescription)")
}
}
}
@IBAction func stopAudioRecordingAction(_ sender: UIButton) {
finishAudioRecording(success: true)
}
func finishAudioRecording(success: Bool) {
audioRecorder.stop()
audioRecorder = nil
meterTimer.invalidate()
if success {
print("Recording finished successfully.")
} else {
print("Recording failed :(")
}
}
func updateAudioMeter(timer: Timer) {
if audioRecorder.isRecording {
let hr = Int((audioRecorder.currentTime / 60) / 60)
let min = Int(audioRecorder.currentTime / 60)
let sec = Int(audioRecorder.currentTime.truncatingRemainder(dividingBy: 60))
let totalTimeString = String(format: "%02d:%02d:%02d", hr, min, sec)
recordingTimeLabel.text = totalTimeString
audioRecorder.updateMeters()
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
//MARK:- Audio recoder delegate methods
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
if !flag {
finishAudioRecording(success: false)
}
}
}
使用Swift 4編寫類文件中的代碼
代碼是
class AudioRecordViewController: UIViewController {
@IBOutlet weak var recodeBtn: UIButton!
@IBOutlet weak var playBtn: UIButton!
var state: AGAudioRecorderState = .Ready
var recorder: AGAudioRecorder = AGAudioRecorder(withFileName: "TempFile")
override func viewDidLoad() {
super.viewDidLoad()
recodeBtn.setTitle("Recode", for: .normal)
playBtn.setTitle("Play", for: .normal)
recorder.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func recode(_ sender: UIButton) {
recorder.doRecord()
}
@IBAction func play(_ sender: UIButton) {
recorder.doPlay()
}
}
extension AudioRecordViewController: AGAudioRecorderDelegate {
func agAudioRecorder(_ recorder: AGAudioRecorder, withStates state: AGAudioRecorderState) {
switch state {
case .error(let e): debugPrint(e)
case .Failed(let s): debugPrint(s)
case .Finish:
recodeBtn.setTitle("Recode", for: .normal)
case .Recording:
recodeBtn.setTitle("Recoding Finished", for: .normal)
case .Pause:
playBtn.setTitle("Pause", for: .normal)
case .Play:
playBtn.setTitle("Play", for: .normal)
case .Ready:
recodeBtn.setTitle("Recode", for: .normal)
playBtn.setTitle("Play", for: .normal)
refreshBtn.setTitle("Refresh", for: .normal)
}
debugPrint(state)
}
func agAudioRecorder(_ recorder: AGAudioRecorder, currentTime timeInterval: TimeInterval, formattedString: String) {
debugPrint(formattedString)
}
}
對於Swift 5 ,
func setup_recorder()
{
if isAudioRecordingGranted
{
let session = AVAudioSession.sharedInstance()
do
{
try session.setCategory(.playAndRecord, mode: .default)
try session.setActive(true)
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey:AVAudioQuality.high.rawValue
]
audioRecorder = try AVAudioRecorder(url: getFileUrl(), settings: settings)
audioRecorder.delegate = self
audioRecorder.isMeteringEnabled = true
audioRecorder.prepareToRecord()
}
catch let error {
display_alert(msg_title: "Error", msg_desc: error.localizedDescription, action_title: "OK")
}
}
else
{
display_alert(msg_title: "Error", msg_desc: "Don't have access to use your microphone.", action_title: "OK")
}
較舊的答案不起作用。
需要...
var mic: AVAudioRecorder?
var workingFile: URL {
return FileManager.default.temporaryDirectory.appendingPathComponent("temp.m4a")
}
接着
@IBAction public func tapTalkSend() {
switch AVCaptureDevice.authorizationStatus(for: .audio) {
case .authorized: _talkSend()
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
if granted { self?._talkSend() }
}
case .denied: return
case .restricted: return
@unknown default:
return
}
}
接着
public func _talkSend() {
if mic != nil && mic!.isRecording {
mic?.stop()
mic = nil
return
}
do {
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
mic = try AVAudioRecorder(url: workingFile, settings: [:])
}
catch let error {
return print("mic drama \(error)")
}
mic!.delegate = self
mic!.record()
}
在你的 vc 上添加AVAudioRecorderDelegate
。 和:
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
_testPlay() ...
_sendFileSomewhere() ...
}
func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
print("audioRecorderEncodeErrorDidOccur")
}
通過回放進行測試:
var myPlayer: AVAudioPlayer!
func _testPlay() {
do {
myPlayer = try AVAudioPlayer(contentsOf: workingFile)
myPlayer.prepareToPlay()
myPlayer.play()
}
catch let error {
return print("play drama \(error)")
}
}
在你的列表中:
<key>NSCameraUsageDescription</key>
<string>For spoken messages.</string>
<key>NSMicrophoneUsageDescription</key>
<string>For spoken messages.</string>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.