I am using AvAudioRecorder for to make audio recordings in my iOS Application. I am able to make an initial recording, but I want to give the user the option of re-recording.
I have these defined:
var recordingSession: AVAudioSession!
var audioRecorder: AVAudioRecorder!
and In my viewDidLoad I have this:
recordingSession = AVAudioSession.sharedInstance()
do {
try recordingSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
try recordingSession.setActive(true)
recordingSession.requestRecordPermission() { result in
DispatchQueue.main.async {
if(result == true)
{
}
else
{
}
}
}
}
catch
{
}
and then I have my record button:
#IBAction func recordButtonPressed(_ sender: Any) {
if audioRecorder == nil {
startRecording()
} else {
finishRecording(success: true)
}
}
and here are my start recording and finished recording methods:
func startRecording() {
audioFilename = getDocumentsDirectory().appendingPathComponent("recording.m4a")
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 12000,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
do {
audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
audioRecorder.delegate = self
audioRecorder.record()
recordButton.setTitle("Tap to Stop", for: .normal)
} catch {
finishRecording(success: false)
}
}
func finishRecording(success: Bool) {
audioRecorder.stop()
audioRecorder = nil
if success {
recordButton.setTitle("Tap to Re-record", for: .normal)
audioSlider.isHidden = false
playButton.isHidden = false
uploadButton.isHidden = false
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
self.audioPlayer = try AVAudioPlayer(contentsOf: audioFilename)
self.audioPlayer?.prepareToPlay()
}catch{
}
} else {
recordButton.setTitle("Tap to Record", for: .normal)
}
}
The problem is whatever I try to re-record it does't. I tried setting the audioRecorder to nil after it was done recording, but that didn't help at all.
Related
To put it in context, I'm developing an app that is recording a lot of time while in background or in the app. I'm facing two problems using AVAudioRecorder to record in my app:
My recording resumes fine when, for example, I play an audio in WhatsApp or a video in Instagram. But when I play a song in Apple Music or a play a voice note, it doesn't resume the recording again.
If I'm in a Phone Call and I start the recording, my app crashes and outputs the following:
(Error de OSStatus 561017449.)
I think also need to handle when the input/output device changes so my app doesn't crash.
The code that I implemented for the class where I'm recording (and also playing the sound I use recorder so I can try it and see if it works) is this:
class RecordViewController: UIViewController, AVAudioPlayerDelegate , AVAudioRecorderDelegate {
#IBOutlet weak var principalLabel: UILabel!
#IBOutlet weak var loginLabel: UILabel!
#IBOutlet weak var recordBTN: UIButton!
#IBOutlet weak var playBTN: UIButton!
var audioRecorder : AVAudioRecorder!
var audioPlayer : AVAudioPlayer!
var isAudioRecordingGranted: Bool!
var isRecording = false
var isPlaying = false
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
check_record_permission()
checkActivateMicrophone()
NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption(notification:)), name: AVAudioSession.interruptionNotification, object: audioRecorder)
let tapRegister: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.goToLogin))
loginLabel.addGestureRecognizer(tapRegister)
loginLabel.isUserInteractionEnabled = true
}
#objc func goToLogin() {
self.performSegue(withIdentifier: "goToLogin", sender: self)
}
#objc func handleInterruption(notification: Notification) {
guard let userInfo = notification.userInfo,
let typeInt = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
let type = AVAudioSession.InterruptionType(rawValue: typeInt) else {
return
}
switch type {
case .began:
if isRecording {
print("OOOOOOO")
audioRecorder.pause()
}
break
case .ended:
guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else { return }
let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
if options.contains(.shouldResume) {
audioRecorder.record()
print("AAAAAAA")
} else {
print("III")
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.audioRecorder.record()
}
}
default: ()
}
}
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
}
}
func checkActivateMicrophone() {
if !isAudioRecordingGranted {
playBTN.isEnabled = false
playBTN.alpha = 0.5
recordBTN.isEnabled = false
recordBTN.alpha = 0.5
principalLabel.text = "Activa el micrófono desde ajustes"
} else {
playBTN.isEnabled = true
playBTN.alpha = 1
recordBTN.isEnabled = true
recordBTN.alpha = 1
principalLabel.text = "¡Prueba las grabaciones!"
}
}
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(AVAudioSession.Category.playAndRecord, options: .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 {
print(error.localizedDescription)
}
}
else
{
print("AAAAA")
}
}
#IBAction func recordAct(_ sender: Any) {
if(isRecording) {
finishAudioRecording(success: true)
recordBTN.setTitle("Record", for: .normal)
playBTN.isEnabled = true
isRecording = false
}
else
{
setup_recorder()
audioRecorder.record()//aaaaaa
recordBTN.setTitle("Stop", for: .normal)
playBTN.isEnabled = false
isRecording = true
}
}
func finishAudioRecording(success: Bool)
{
if success
{
audioRecorder.stop()
audioRecorder = nil
print("recorded successfully.")
}
else
{
print("Recording failed.")
}
}
func prepare_play()
{
do
{
audioPlayer = try AVAudioPlayer(contentsOf: getFileUrl())
audioPlayer.delegate = self
audioPlayer.prepareToPlay()
}
catch{
print("Error")
}
}
#IBAction func playAct(_ sender: Any) {
if(isPlaying)
{
audioPlayer.stop()
recordBTN.isEnabled = true
playBTN.setTitle("Play", for: .normal)
isPlaying = false
}
else
{
if FileManager.default.fileExists(atPath: getFileUrl().path)
{
recordBTN.isEnabled = false
playBTN.setTitle("pause", for: .normal)
prepare_play()
audioPlayer.play()
isPlaying = true
}
else
{
print("Audio file is missing.")
}
}
}
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool)
{
if !flag
{
print("UUU")
finishAudioRecording(success: false)
}
playBTN.isEnabled = true
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
{
recordBTN.isEnabled = true
}
}
I implemented the "Background Mode" of Audio, AirPlay and Picture in Picture
So I didn't managed to find any code about this issue.
I have recorded an mp4 file(audioFile.mp4) and now i want to stream it through socket , yet i have problem in converting.
I know that there is the ffmpeg(https://www.ffmpeg.org/) platform yet i didn't see any code of that.
Would appreciate any idea.
class ViewController: UIViewController {
var requestManager = RequestManager()
var socket: WebSocket?
var audioRecorder: AVAudioRecorder!
#IBOutlet weak var recordBtn: UIButton!
#IBOutlet weak var playBtn: UIButton!
var fileName: String = "audioFile.mp4"
var soundRecorder: AVAudioRecorder?
var soundPlayer: AVAudioPlayer?
var audioSession = AVAudioSession.sharedInstance()
override func viewDidLoad() {
super.viewDidLoad()
self.socket?.delegate = self
setUpRecorder()
playBtn.isEnabled = false
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSession.Category.playAndRecord, mode: .measurement, options: .defaultToSpeaker)
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
} catch {
print(error)
}
}
func getDocDirector() -> URL {
let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return path[0]
}
func setUpRecorder() {
let audioFileName = getDocDirector().appendingPathComponent(fileName)
let recordSettings: [String: Any] = [AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue,
AVNumberOfChannelsKey: 1,
AVEncoderBitRateKey: 16000,
AVSampleRateKey: 16000]
do {
soundRecorder = try AVAudioRecorder(url: audioFileName, settings: recordSettings)
soundRecorder?.delegate = self
soundRecorder?.prepareToRecord()
} catch {
print(error)
}
}
func setUpPlayer() {
let audioFileName = getDocDirector().appendingPathComponent(fileName)
do {
soundPlayer = try AVAudioPlayer(contentsOf: audioFileName)
soundPlayer?.delegate = self
soundPlayer?.prepareToPlay()
soundPlayer?.volume = 1.0
} catch {
print(error)
}
}
#IBAction func recordAction(_ sender: Any) {
if recordBtn.titleLabel?.text == "Record" {
soundRecorder?.record()
recordBtn.setTitle("Stop", for: .normal)
playBtn.isEnabled = false
} else {
soundRecorder?.stop()
recordBtn.setTitle("Record", for: .normal)
playBtn.isEnabled = false
}
}
#IBAction func playAction(_ sender: Any) {
if playBtn.titleLabel?.text == "Play" {
playBtn.setTitle("Stop", for: .normal)
recordBtn.isEnabled = false
setUpPlayer()
soundPlayer?.play()
} else {
playBtn.setTitle("Play", for: .normal)
recordBtn.isEnabled = false
}
}
func openSocket() {
getUrl(success: { [weak self] (url) in
self?.socket = WebSocket(url: URL(string: url)!)
self?.socket?.connect()
}) { (e) in
//
}
}
}
I am trying to start recording when the user starts to talk and stops recording when the user is done talking. And I want to limit the maximum record audio length.I could not be able to find enough function in AVAudioRecorderDelegate.Hope you understand my problem.Thanks in Advance
#IBAction func recordAudio(_ sender: Any) {
recordingLabel.text = "Recording in progress..."
let dirPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask, true)[0] as String
let recordingName = "recordedVoice.wav"
let pathArray = [dirPath, recordingName]
let filePath = URL(string: pathArray.joined(separator: "/"))
let session = AVAudioSession.sharedInstance()
try! session.setCategory(AVAudioSessionCategoryPlayAndRecord, with:AVAudioSessionCategoryOptions.defaultToSpeaker)
try! audioRecorder = AVAudioRecorder(url: filePath!, settings: [:])
audioRecorder.delegate = self
audioRecorder.isMeteringEnabled = true
audioRecorder.prepareToRecord()
audioRecorder.record()
}
#IBAction func stopRecording(_ sender: Any) {
recordButton.isEnabled = true
stopRecordingButton.isEnabled = false
recordingLabel.text = "Tap to record..."
audioRecorder.stop()
let audioSession = AVAudioSession.sharedInstance()
try! audioSession.setActive(false)
}
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
if (flag) {
//Success
} else {
print("Could not save audio recording!")
}
}
To Record Audio When user tak1 you need some steps
1. Permission from User to all your app to use Mic
In your Info Plist Add Privacy - Microphone Usage Description in user Plist and add Text Description
2. Location to save Recorded File user FileManager
3. To End After time : use audioRecorder.record(forDuration: 30) // record for 30 Sec
Check complete code :
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var recordButton: UIButton!
var recordingSession: AVAudioSession!
var audioRecorder: AVAudioRecorder!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func recordAudio(_ sender: Any) {
self.requestRecordPermission()
}
func requestRecordPermission() {
recordingSession = AVAudioSession.sharedInstance()
do {
try recordingSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
try recordingSession.setActive(true)
recordingSession.requestRecordPermission() { [unowned self] allowed in
DispatchQueue.main.async {
if allowed {
// User allow you to record
// Start recording and change UIbutton color
self.recordButton.backgroundColor = .red
self.startRecording()
} else {
// failed to record!
}
}
}
} catch {
// failed to record!
}
}
func startRecording() {
let audioFilename = getDocumentsDirectory().appendingPathComponent("recordedFile.m4a")
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 12000,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
do {
audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
audioRecorder.delegate = self
audioRecorder.record(forDuration: 30) // record for 30 Sec
recordButton.setTitle("Tap to Stop", for: .normal)
recordButton.backgroundColor = .green
} catch {
finishRecording(success: false)
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
#objc func recordTapped() {
if audioRecorder == nil {
startRecording()
} else {
finishRecording(success: true)
}
}
public func finishRecording(success: Bool) {
audioRecorder.stop()
audioRecorder = nil
if success {
// record sucess
recordButton.backgroundColor = .green
} else {
// record fail
recordButton.backgroundColor = .yellow
}
}
}
extension ViewController :AVAudioRecorderDelegate{
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
if !flag {
finishRecording(success: false)
}
}
}
When I run below code, I get this error Domain=NSOSStatusErrorDomain Code=1718449215 "(null)"
Error in prepare audio recorder
Error Domain=NSOSStatusErrorDomain Code=1718449215 "(null)"
Error in prepare audio recorder
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var recordAoutlet: UIButton!
#IBOutlet weak var playOutlet: UIButton!
var audioRecorder:AVAudioRecorder!
var audioPLayer:AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.prepareAudioRecorder()
}
#IBAction func recorderAction(_ sender: AnyObject) {
if !audioRecorder.isRecording {
//Start Recorder
let audioSession = AVAudioSession.sharedInstance()
do{
try audioSession.setActive(true)
audioRecorder.record()
} catch{
print(error.localizedDescription)
print("error in recorder action 1")
}
} else {
//Stop Recorder
audioRecorder.stop()
let audioSession = AVAudioSession.sharedInstance()
do{
try audioSession.setActive(false)
}catch {
print(error.localizedDescription)
print("error in recorder action 2")
}
//check
if self.verifyFileExists() {
print("file exixts")
playOutlet.isHidden = false
} else {
print("there was a problem recording.")
}
}
self.updateRecorderbuttonTitle()
}
#IBAction func playAction(_ sender: AnyObject) {
self.playAudio()
}
//MARK: main
func prepareAudioRecorder() {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
try audioRecorder = AVAudioRecorder(url: URL(fileURLWithPath: self.audioFileLocation()), settings: self.audioSettings())
audioRecorder.prepareToRecord()
} catch {
print(error)
print("Error in prepare audio recorder")
}
}
func playAudio(){
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryPlayback)
try audioPLayer = AVAudioPlayer(contentsOf: URL(fileURLWithPath:self.audioFileLocation()))
audioPLayer.prepareToPlay()
audioPLayer.play()
} catch {
print(error)
print("error in audio session func")
}
}
// MARK:Helper
func audioFileLocation()-> String {
return NSTemporaryDirectory().appending("AudioRecording.mp4")
}
func audioSettings()->[String:Any] {
let settings = [AVFormatIDKey : NSNumber.init(value: kAudioFormatAppleLossless),
AVSampleRateKey : NSNumber.init(value: 44100.0),
AVNumberOfChannelsKey : NSNumber.init(value: 1),
AVLinearPCMBitDepthKey : NSNumber.init(value: 16),
AVEncoderAudioQualityKey : NSNumber.init(value: AVAudioQuality.high.rawValue)]
return settings
}
// update buttons titles
func updateRecorderbuttonTitle(){
if audioRecorder.isRecording {
recordAoutlet.setTitle("Recording...", for:.normal)
} else {
recordAoutlet.setTitle("Record", for: .normal)
}
}
// Verify File Exists
func verifyFileExists()-> Bool{
let fileManager = FileManager.default
return fileManager.fileExists(atPath: self.audioFileLocation())
}
}
I have an app that playing stream audio. How can I record streaming audio from AVPlayer using AVAudioRecorder (or something another?). Thanks.
Swift 3+
Here is simple VC which will save audio session to documents dir (audio.aac)
import UIKit
import AVFoundation
class ViewController: UIViewController {
var audioRecorder: AVAudioRecorder?
override func viewDidLoad() {
super.viewDidLoad()
verifyRecordPermission()
}
#IBAction func recordButonAction(_ sender: UIButton) {
if audioRecorder?.isRecording == true {
audioRecorder?.stop()
sender.setTitle("Record", for: .normal)
}
else {
startRecording()
sender.setTitle("Stop", for: .normal)
}
}
func verifyRecordPermission() {
let permission = AVAudioSession.sharedInstance().recordPermission()
switch permission {
case .denied:
print("recording not allowed")
case .granted:
print("recording allowed")
default:
AVAudioSession.sharedInstance().requestRecordPermission() { (granted) -> Void in
print("recording granted:\(granted)")
}
}
}
func startRecording() {
guard AVAudioSession.sharedInstance().recordPermission() == .granted else {
return
}
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let audioUrl = URL(fileURLWithPath: "\(documentsPath)/audio.aac")
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryRecord)
try session.setActive(true)
try audioRecorder = AVAudioRecorder(url: audioUrl,
settings: [AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 24000.0,
AVNumberOfChannelsKey: 1 as NSNumber,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue])
} catch {
// handle error...
return
}
guard let audioRecorder = audioRecorder else {
return
}
audioRecorder.prepareToRecord()
audioRecorder.record()
}
func stop(session: AVAudioSession = AVAudioSession.sharedInstance()) {
audioRecorder?.stop()
audioRecorder = nil
do {
try session.setActive(false)
} catch {
// handle session errors
}
}
}