在Swift中录制音频

vnzz0bqm  于 2022-12-17  发布在  Swift
关注(0)|答案(9)|浏览(226)

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

bcs8qyzn

bcs8qyzn1#

雨燕3

添加框架AVFoundation
在信息列表中添加键值
=隐私-麦克风用法说明和
=用于使用麦克风

(the如果您不提供值,应用程序将崩溃-请说明您请求权限的原因)**

*导入AV基础和AV音频录制器代理、AV音频播放器代理

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)
}
d4so4syb

d4so4syb2#

下面是代码。您可以轻松录制。将此代码写在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()
    }        
}
evrscar2

evrscar23#

@codester答案的swift 2版本。

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

}
ippsafx7

ippsafx74#

除了之前的答案,我还试着在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 {
        }
    }
}
biswetbf

biswetbf5#

Here录音机,界面简单,采用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()
  }
}
kxeu7u2r

kxeu7u2r6#

对于雨燕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")
    }
e1xvtsh3

e1xvtsh37#

使用Swift 4的类文件中的代码

类为AGAudioRecorder
代码为

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)
    }
}
c9qzyr3d

c9qzyr3d8#

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)
        }
    }
}
wswtfjt7

wswtfjt79#

简单的2022语法,在iPhone上录制音频。

旧的答案不管用。
需要...

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>

相关问题