Reputation: 9797
I tried to record and I could find a good answer here: Recording audio in Swift
I could make it work. But now I would like to know how to play the recorded audio. From the recording I already have the general var audioRecorder, and defined the url path. So I tried audioRecorder.play() but it does not work.
I suppose that the problem comes form the fact that the global var audioRecorder is an instance of AVAudioRecorder and to play it should it be an instance of AVAudioPlayer?, how this two things are related?
I do not want to copy paste a peace of code I would like to understand. This is why I simplify the code here. Please explain why it does not work in this specific code and how to solve it.
(I have done a lot of tutorials related. The problem is that there is so much code I get lost. My question here is to understand how this specific part works)
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()
}
Upvotes: 4
Views: 9183
Reputation: 223
Here is the answer by @DharmeshKheni + updated for swift 4.0 Create three buttons and add outlets and methods to them.
New version
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")
}
}
Old version
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")
}
}
Upvotes: 2
Reputation: 71852
Here is the complete working code for record audio then store it to file then play it:
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")
}
}
Check THIS sample project for more Info.
In your code audioRecorder
is used for record audio and audioPlayer
is used for play audio. Thats why audioRecorder
doesn't have property play()
So you can not use audioRecorder.play()
.
Upvotes: 3