2014-10-20 85 views
34

有谁知道我在哪里可以找到有关如何在Swift应用程序中录制音频的信息?我一直在看一些音频播放的例子,但我似乎无法找到任何有关实施音频录制的内容。由于在Swift中录制音频

+0

的音频记录雨燕3.0:https://iosdevcenters.blogspot.com/2016/05/audio-recording-and-playing-in-swift-30.html – 2017-08-31 05:20:13

回答

38

这里是code.You可以记录IBAction。它easily.Write该代码将名称保存记录在DocumentsrecordTest.caf

//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() 
    }   
} 
+0

'documents'应该是' (文件为NSString).append ...'(var str声明代码) – 2016-06-22 09:57:39

15

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

} 
+0

嘿 - 测试完这段代码之后,我在fullPath行中得到“stringByAppendingPathComponent不可用,请尝试使用URLByAppendingPathComponent”,但这不起作用,因为存在没有这样的fullPath类型的方法。 – 2015-11-19 01:05:23

+0

@LiamShalon你确定你正确设置了'documentsDirectory' var?如果设置不正确,那么stringByAppendingPathComponent不存在。 – Kristian 2015-11-19 03:02:15

+1

当苹果推出swift 2.0时,一些字符串扩展消失了。检查这个链接手动创建扩展:https://forums.developer.apple.com/thread/13580 – 2015-12-10 18:16:03

6

除了以前的答案,我试图使它在7.2的Xcode工作后,我听不到任何声音,没有当我通过电子邮件发送的文件。没有警告或例外。 因此,我将设置更改为以下内容并存储为.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 { 
     } 
    } 
} 
+0

对于swift 2和Xcode 7.2,这应该是正确的答案。谢谢。 – user3298158 2016-04-10 13:18:22

+0

BRILLIANT SOLUTION !!! – Josh 2016-05-18 22:09:16

+0

以及如何通过电子邮件发送文件? – 2016-12-21 04:05:09

0

斯威夫特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) 
     } 
    } 
} 
+0

你可以添加暂停并继续功能吗? – Mamta 2017-06-16 07:51:46

+0

Hi @Mamta,你能否提交一个新的问题?所以我可以回答它,因为我需要使用不同的代表来播放音乐,暂停和停止播放功能。我希望你能理解它。此页面仅用于录音。请在此提供问题的网址。谢谢 - mriaz0011 – mriaz0011 2017-06-18 00:16:09

12

在斯威夫特3

enter image description here

  • 添加框架AVFoundation
  • 在信息。plist中添加键值:隐私 - 麦克风的使用说明和值:对于使用麦克风(该应用程序会崩溃,如果你不提供的价值 - 说明为什么你所要求的权限)

enter image description here

  • 进口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() { [unowned self] allowed in 
         DispatchQueue.main.async { 
          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") 
        } 
    } 
    
  • 开始录音时使用updateAudioMeter,&按钮start_recording按&显示秒,如果录音开始然后完成录制

    @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) 
    } 
    
+0

你可以添加暂停和继续功能吗? – Mamta 2017-06-16 07:52:52

+0

谢谢!它的工作非常棒。 – Raja 2017-08-11 11:29:44

+0

@Mamta无论何时我都会得到时间,我一定会做到的。 – 2017-10-06 15:15:37