Swift:播放录制的音频

4
我尝试录音并在这里找到了一个好答案:Recording audio in Swift 我已经让它工作了。但现在我想知道如何播放录制的音频。从录制中,我已经有了一般的var audioRecorder,并定义了url路径。所以我尝试了audioRecorder.play(),但它不起作用。
我认为问题出在全局变量audioRecorder是AVAudioRecorder的实例,而要播放它应该是AVAudioPlayer的实例,这两个东西有什么关系?
我不想复制粘贴代码,我想理解。这就是为什么我在这里简化代码。请解释为什么在这个特定的代码中它不起作用以及如何解决它。
(我已经做了很多相关的教程。问题在于有太多的代码,我迷失了方向。我的问题是要理解这个具体部分是如何工作的。)
import AVFoundation
var audioRecorder:AVAudioRecorder!
@IBAction func record(sender: AnyObject) {       
    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)
    println(url)

    audioRecorder = AVAudioRecorder(URL:url, settings: nil, error: nil)
    audioRecorder.record()
}

@IBAction func play(sender: AnyObject) {
   // this gives the error 'AVAudioRecorder' does not have a member named 'play'
   // audioRecorder.play() 
}
2个回答

3

以下是完整的工作代码,用于录制音频然后将其存储到文件中,最后播放它:

import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate {

    @IBOutlet weak var recordButton: UIButton!
    @IBOutlet weak var stopButton: UIButton!
    @IBOutlet weak var playButton: UIButton!
    
    var audioPlayer : AVAudioPlayer?
    var audioRecorder : AVAudioRecorder?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        playButton.enabled = false
        stopButton.enabled = false
        
        // getting URL path for audio
        let dirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        let docDir = dirPath[0] as! String
        let soundFilePath = docDir.stringByAppendingPathComponent("sound.caf")
        let soundFileURL = NSURL(fileURLWithPath: soundFilePath)
        println(soundFilePath)
        
        //Setting for recorder
        let recordSettings = [AVEncoderAudioQualityKey: AVAudioQuality.Min.rawValue,
            AVEncoderBitRateKey: 16,
            AVNumberOfChannelsKey : 2,
            AVSampleRateKey: 44100.0]
        var error : NSError?
        let audioSession = AVAudioSession.sharedInstance()
        audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, error: &error)
        if let err = error{
            println("audioSession error: \(err.localizedDescription)")
        }
        audioRecorder = AVAudioRecorder(URL: soundFileURL, settings: recordSettings as [NSObject : AnyObject], error: &error)
        
        if let err = error{
            println("audioSession error: \(err.localizedDescription)")
        }else{
            audioRecorder?.prepareToRecord()
        }
    }
    //record audio
    @IBAction func recordAudio(sender: AnyObject) {
        
        if audioRecorder?.recording == false{
            playButton.enabled = false
            stopButton.enabled = true
            audioRecorder?.record()
        }
    }
    //stop recording audio
    @IBAction func stopAudio(sender: AnyObject) {
        
        stopButton.enabled = false
        playButton.enabled = true
        recordButton.enabled = true
        
        if audioRecorder?.recording == true{
            audioRecorder?.stop()
        }else{
            audioPlayer?.stop()
        }
    }
    //play your recorded audio
    @IBAction func playAudio(sender: AnyObject) {
        
        if audioRecorder?.recording == false{
            stopButton.enabled = true
            recordButton.enabled = false
            
            var error : NSError?
            
            audioPlayer = AVAudioPlayer(contentsOfURL: audioRecorder?.url, error: &error)
            
            audioPlayer?.delegate = self
            
            if let err = error{
                println("audioPlayer error: \(err.localizedDescription)")
            }else{
                audioPlayer?.play()
            }
        }
    }
    
    func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) {
        recordButton.enabled = true
        stopButton.enabled = false
    }
    
    func audioPlayerDecodeErrorDidOccur(player: AVAudioPlayer!, error: NSError!) {
        println("Audio Play Decode Error")
    }
    
    func audioRecorderDidFinishRecording(recorder: AVAudioRecorder!, successfully flag: Bool) {
    }
    
    func audioRecorderEncodeErrorDidOccur(recorder: AVAudioRecorder!, error: NSError!) {
        println("Audio Record Encode Error")
    }
}

请参考此示例项目了解更多信息。

在您的代码中,audioRecorder用于录制音频,audioPlayer用于播放音频。因此,audioRecorder没有play()属性。

因此,您无法使用audioRecorder.play()


1
这是由@DharmeshKheni回答并更新至Swift 4.0的答案。创建三个按钮并添加输出口和方法。
import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate {

@IBOutlet weak var recordButton: UIButton!
@IBOutlet weak var stopButton: UIButton!
@IBOutlet weak var playButton: UIButton!

var audioPlayer : AVAudioPlayer?
var audioRecorder : AVAudioRecorder?


override func viewDidLoad() {
    super.viewDidLoad()
    playButton.isEnabled = false
    stopButton.isEnabled = false

    // getting URL path for audio
    let dirPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
    let docDir = dirPath[0]
    let soundFilePath = (docDir as NSString).appendingPathComponent("sound.caf")
    let soundFileURL = NSURL(fileURLWithPath: soundFilePath)
    print(soundFilePath)

    //Setting for recorder
    let recordSettings = [AVEncoderAudioQualityKey: AVAudioQuality.min.rawValue,
        AVEncoderBitRateKey: 16,
        AVNumberOfChannelsKey : 2,
        AVSampleRateKey: 44100.0] as [String : Any] as [String : Any] as [String : Any] as [String : Any]
    var error : NSError?
    let audioSession = AVAudioSession.sharedInstance()
    do {
        try audioSession.setCategory(AVAudioSession.Category.playAndRecord)
        audioRecorder = try AVAudioRecorder(url: soundFileURL as URL, settings: recordSettings as [String : AnyObject])
    } catch _ {
        print("Error")
    }

    if let err = error {
        print("audioSession error: \(err.localizedDescription)")
    }else{
        audioRecorder?.prepareToRecord()
    }
}
//record audio
@IBAction func recordAudio(sender: AnyObject) {

    if audioRecorder?.isRecording == false{
        playButton.isEnabled = false
        stopButton.isEnabled = true
        audioRecorder?.record()
    }
}
//stop recording audio
@IBAction func stopAudio(sender: AnyObject) {

    stopButton.isEnabled = false
    playButton.isEnabled = true
    recordButton.isEnabled = true

    if audioRecorder?.isRecording == true{
        audioRecorder?.stop()
    }else{
        audioPlayer?.stop()
    }
}
//play your recorded audio
@IBAction func playAudio(sender: AnyObject) {

    if audioRecorder?.isRecording == false{
        stopButton.isEnabled = true
        recordButton.isEnabled = false

        var error : NSError?
        do {
            let player = try AVAudioPlayer(contentsOf: audioRecorder!.url)
             audioPlayer = player
         } catch {
             print(error)
         }

        audioPlayer?.delegate = self

        if let err = error{
            print("audioPlayer error: \(err.localizedDescription)")
        }else{
            audioPlayer?.play()
        }
    }
}

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    recordButton.isEnabled = true
    stopButton.isEnabled = false
}

private func audioPlayerDecodeErrorDidOccur(player: AVAudioPlayer!, error: NSError!) {
    print("Audio Play Decode Error")
}

func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
}

private func audioRecorderEncodeErrorDidOccur(recorder: AVAudioRecorder!, error: NSError!) {
    print("Audio Record Encode Error")
}

}

旧版本

import UIKit
import AVFoundation

class PlayVC: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate {

    @IBOutlet weak var recordButton: UIButton!
    @IBOutlet weak var stopButton: UIButton!
    @IBOutlet weak var playButton: UIButton!

    var audioPlayer : AVAudioPlayer?
    var audioRecorder : AVAudioRecorder?


    override func viewDidLoad() {
        super.viewDidLoad()
        playButton.isEnabled = false
        stopButton.isEnabled = false

        // getting URL path for audio
        let dirPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let docDir = dirPath[0] as! String
        let soundFilePath = docDir.stringByAppendingPathComponent(path: "sound.caf")
        let soundFileURL = NSURL(fileURLWithPath: soundFilePath)
        print(soundFilePath)

        //Setting for recorder
        let recordSettings = [AVEncoderAudioQualityKey: AVAudioQuality.min.rawValue,
                              AVEncoderBitRateKey: 16,
                              AVNumberOfChannelsKey : 2,
                              AVSampleRateKey: 44100.0] as [String : Any]
        var error : NSError?
        let audioSession = AVAudioSession.sharedInstance()

        do {
            try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
        } catch {
            print(error)
        }
        if let err = error{
            print("audioSession error: \(err.localizedDescription)")
        }
        do {
            audioRecorder = try AVAudioRecorder(url: soundFileURL as URL, settings: recordSettings as [String : Any])
        } catch {
            print(error)
        }


        if let err = error{
            print("audioSession error: \(err.localizedDescription)")
        }else{
            audioRecorder?.prepareToRecord()
        }
    }
    //record audio
    @IBAction func recordAudio(sender: AnyObject) {

        if audioRecorder?.isRecording == false{
            playButton.isEnabled = false
            stopButton.isEnabled = true
            audioRecorder?.record()
        }
    }
    //stop recording audio
    @IBAction func stopAudio(sender: AnyObject) {

        stopButton.isEnabled = false
        playButton.isEnabled = true
        recordButton.isEnabled = true

        if audioRecorder?.isRecording == true{
            audioRecorder?.stop()
        }else{
            audioPlayer?.stop()
        }
    }
    //play your recorded audio
    @IBAction func playAudio(sender: AnyObject) {

        if audioRecorder?.isRecording == false{
            stopButton.isEnabled = true
            recordButton.isEnabled = false

            var error : NSError?

            do {

                audioPlayer = try AVAudioPlayer(contentsOf: (audioRecorder?.url)!)
            } catch {
                print(error)
            }

            audioPlayer?.delegate = self

            if let err = error{
                print("audioPlayer error: \(err.localizedDescription)")
            }else{
                audioPlayer?.play()
            }
        }
    }

    func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) {
        recordButton.isEnabled = true
        stopButton.isEnabled = false
    }

    func audioPlayerDecodeErrorDidOccur(player: AVAudioPlayer!, error: NSError!) {
        print("Audio Play Decode Error")
    }

    func audioRecorderDidFinishRecording(recorder: AVAudioRecorder!, successfully flag: Bool) {
    }

    func audioRecorderEncodeErrorDidOccur(recorder: AVAudioRecorder!, error: NSError!) {
        print("Audio Record Encode Error")
    }
}

1
这段代码在当前的Swift版本(即4)中存在许多问题。如果你说这段代码是为Swift 4编写的,请考虑改进它。 - Yash Bedi
2
谢谢您的评论,请帮助我改进这个答案,造福社区。 - dmyma
1
在Xcode 10.x中使用Swift 4运行它,你会遇到错误,然后解决它们并更新答案。就这样。 - Yash Bedi
1
谢谢您的评论,请帮助我,因为我点击了录制音频,但没有任何反应。 - Ayush jain
@Ayushjain,还是不行吗?我想我应该更新它以适用于Swift 5。 - dmyma
@dmyma,那时我使用了不同的方法来实现。谢谢你的帮助。 - Ayush jain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接