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
}
}
}
Related
I am using the below code to record a 5 second sound sample in an iOS Swift app. The code works fine for recording and also recognised headphone correctly if they are plugged in. However, if during the recording the headphones are added or removed, the recording is interrupted. I wonder why that is as otherwise it runs smoothly?
import AVFoundation
class RecorderViewController: UIViewController {
var recorder: AVAudioRecorder!
var uploadObjectSuccess = false
#IBOutlet weak var recordButton: UIButton!
#IBOutlet weak var statusLabel: UILabel!
#IBOutlet weak var progressView: UIProgressView!
var meterTimer: Timer!
var soundFileURL: URL!
override func viewDidLoad() {
super.viewDidLoad()
setSessionPlayback()
askForNotifications()
checkHeadphones()
}
func updateAudioMeter(_ timer:Timer) {
self.progressView.setProgress(0, animated: false)
if recorder != nil && recorder.isRecording {
let sec = Int(recorder.currentTime.truncatingRemainder(dividingBy: 60))
let s = String(format: "%02d", sec)
statusLabel.text = s
recorder.updateMeters()
self.progressView.setProgress(Float(sec*4), animated: true)
if (sec==6) && recorder != nil {
func aux()->Bool {
recorder.stop()
return true
}
if aux()==true {
if self.soundFileURL != nil {
self.uploadObjectSuccess = false
let path = Auth.auth().currentUser?.uid
let FIRStoragePath = Storage.storage().reference().child(path!).child(FileName!)
let uploadObject = FIRStoragePath.putFile(from: self.soundFileURL!, metadata: nil)
uploadObject.observe(.success) { snapshot in
// Upload completed successfully
self.uploadObjectSuccess = true
}
uploadObject.observe(.failure) { snapshot in
// Upload failed
self.uploadObjectSuccess = true
}
}
}
}
} else if (uploadObjectSuccess==true) {
self.statusLabel.text = "00"
self.recordButton.isEnabled = true
isPlaying = false
self.uploadObjectSuccess = false
} else {
self.statusLabel.text = "00"
}
}
#IBAction func record(_ sender: Any) {
if recorder != nil {
recorder.stop()
}
recordButton.isEnabled = false
recordWithPermission(true)
}
func setupRecorder() {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
self.soundFileURL = documentsDirectory.appendingPathComponent(self.currentFileName) //appendingPathComponent(currentFileName)
if FileManager.default.fileExists(atPath: soundFileURL.absoluteString) {
do {
try FileManager.default.removeItem(atPath: self.soundFileURL.absoluteString)
} catch let error as NSError {
print("Ooops! Something went wrong: \(error)")
}
}
let recordSettings:[String : AnyObject] = [
AVFormatIDKey: NSNumber(value:(kAudioFormatMPEG4AAC)),
AVEncoderAudioQualityKey : NSNumber(value:AVAudioQuality.min.rawValue),
//AVEncoderBitRateKey : NSNumber(value:16),
AVNumberOfChannelsKey: NSNumber(value:1),
AVSampleRateKey : NSNumber(value:16000.0)
]
do {
recorder = try AVAudioRecorder(url: soundFileURL, settings: recordSettings)
recorder.delegate = self
recorder.isMeteringEnabled = true
recorder.prepareToRecord() // creates/overwrites the file at soundFileURL
} catch let error as NSError {
recorder = nil
print(error.localizedDescription)
}
}
func recordWithPermission(_ setup:Bool) {
checkHeadphones()
setSessionPlayback()
askForNotifications()
let session:AVAudioSession = AVAudioSession.sharedInstance()
// ios 8 and later
if (session.responds(to: #selector(AVAudioSession.requestRecordPermission(_:)))) {
AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in
if granted {
print("Permission to record granted")
self.setSessionPlayAndRecord()
if setup {
self.setupRecorder()
}
self.recorder.record()
self.meterTimer = Timer.scheduledTimer(timeInterval: 0.1,
target:self,
selector:#selector(RecorderViewController.updateAudioMeter(_:)),
userInfo:nil,
repeats:true)
} else {
print("Permission to record not granted")
self.statusLabel.text = "00"
self.recordButton.isEnabled = true
self.uploadObjectSuccess = false
self.recorder.stop()
}
})
} else {
print("requestRecordPermission unrecognized")
self.statusLabel.text = "00"
self.recordButton.isEnabled = true
self.uploadObjectSuccess = false
self.recorder.stop()
}
}
func setSessionPlayback() {
let session:AVAudioSession = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryPlayback)
} catch let error as NSError {
print("could not set session category")
print(error.localizedDescription)
}
do {
try session.setActive(true)
} catch let error as NSError {
print("could not make session active")
print(error.localizedDescription)
}
}
func setSessionPlayAndRecord() {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch let error as NSError {
print("could not set session category")
print(error.localizedDescription)
}
do {
try session.setActive(true)
} catch let error as NSError {
print("could not make session active")
print(error.localizedDescription)
}
}
func askForNotifications() {
NotificationCenter.default.addObserver(self,
selector:#selector(RecorderViewController.background(_:)),
name:NSNotification.Name.UIApplicationWillResignActive,
object:nil)
NotificationCenter.default.addObserver(self,
selector:#selector(RecorderViewController.foreground(_:)),
name:NSNotification.Name.UIApplicationWillEnterForeground,
object:nil)
NotificationCenter.default.addObserver(self,
selector:#selector(RecorderViewController.routeChange(_:)),
name:NSNotification.Name.AVAudioSessionRouteChange,
object:nil)
}
#objc func background(_ notification:Notification) {
print("background")
if recorder != nil {
recorder.stop()
}
}
#objc func foreground(_ notification:Notification) {
print("foreground")
}
#objc func routeChange(_ notification:Notification) {
print("routeChange \(String(describing: (notification as NSNotification).userInfo))")
if let userInfo = (notification as NSNotification).userInfo {
//print("userInfo \(userInfo)")
if let reason = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt {
//print("reason \(reason)")
switch AVAudioSessionRouteChangeReason(rawValue: reason)! {
case AVAudioSessionRouteChangeReason.newDeviceAvailable:
print("NewDeviceAvailable")
print("did you plug in headphones?")
checkHeadphones()
case AVAudioSessionRouteChangeReason.oldDeviceUnavailable:
print("OldDeviceUnavailable")
print("did you unplug headphones?")
checkHeadphones()
case AVAudioSessionRouteChangeReason.categoryChange:
print("CategoryChange")
case AVAudioSessionRouteChangeReason.override:
print("Override")
case AVAudioSessionRouteChangeReason.wakeFromSleep:
print("WakeFromSleep")
case AVAudioSessionRouteChangeReason.unknown:
print("Unknown")
case AVAudioSessionRouteChangeReason.noSuitableRouteForCategory:
print("NoSuitableRouteForCategory")
case AVAudioSessionRouteChangeReason.routeConfigurationChange:
print("RouteConfigurationChange")
}
}
}
}
func checkHeadphones() {
// check NewDeviceAvailable and OldDeviceUnavailable for them being plugged in/unplugged
let currentRoute = AVAudioSession.sharedInstance().currentRoute
if currentRoute.outputs.count > 0 {
for description in currentRoute.outputs {
if description.portType == AVAudioSessionPortHeadphones {
print("headphones are plugged in")
break
} else {
print("headphones are unplugged")
}
}
} else {
print("checking headphones requires a connection to a device")
}
}
}
// MARK: AVAudioRecorderDelegate
extension RecorderViewController : AVAudioRecorderDelegate {
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder,
successfully flag: Bool) {
print("finished recording \(flag)")
}
func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder,
error: Error?) {
if let e = error {
print("\(e.localizedDescription)")
}
}
}
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.
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)
}
}
}
I am getting an error that reads Thread 1: EX_BAD_INSTRUCTION(code=EXC_1386_INVOP, subcode=0x0). Specifically, this line, player.rate = sliderValue.value is being flagged.
// RecorderViewController.swift
import UIKit
import AVFoundation
/**
Uses AVAudioRecorder to record a sound file and an AVAudioPlayer to play it back.
*/
class RecorderViewController: UIViewController {
var recorder: AVAudioRecorder!
var player:AVAudioPlayer!
#IBOutlet var recordButton: UIButton!
#IBOutlet var stopButton: UIButton!
#IBOutlet var playButton: UIButton!
#IBOutlet var statusLabel: UILabel!
#IBOutlet weak var sliderValue: UISlider!
var meterTimer:NSTimer!
var soundFileURL:NSURL!
override func viewDidLoad() {
super.viewDidLoad()
stopButton.enabled = false
playButton.enabled = false
setSessionPlayback()
askForNotifications()
checkHeadphones()
}
func updateAudioMeter(timer:NSTimer) {
if recorder.recording {
let min = Int(recorder.currentTime / 60)
let sec = Int(recorder.currentTime % 60)
let s = String(format: "%02d:%02d", min, sec)
statusLabel.text = s
recorder.updateMeters()
// if you want to draw some graphics...
//var apc0 = recorder.averagePowerForChannel(0)
//var peak0 = recorder.peakPowerForChannel(0)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
recorder = nil
player = nil
}
#IBAction func removeAll(sender: AnyObject) {
deleteAllRecordings()
}
#IBAction func record(sender: UIButton) {
if player != nil && player.playing {
player.stop()
}
if recorder == nil {
print("recording. recorder nil")
recordButton.setTitle("Pause", forState:.Normal)
playButton.enabled = false
stopButton.enabled = true
recordWithPermission(true)
return
}
if recorder != nil && recorder.recording {
print("pausing")
recorder.pause()
recordButton.setTitle("Continue", forState:.Normal)
} else {
print("recording")
recordButton.setTitle("Pause", forState:.Normal)
playButton.enabled = false
stopButton.enabled = true
// recorder.record()
recordWithPermission(false)
}
}
#IBAction func stop(sender: UIButton) {
print("stop")
recorder?.stop()
player?.stop()
meterTimer.invalidate()
recordButton.setTitle("Record", forState:.Normal)
let session = AVAudioSession.sharedInstance()
do {
try session.setActive(false)
playButton.enabled = true
stopButton.enabled = false
recordButton.enabled = true
} catch let error as NSError {
print("could not make session inactive")
print(error.localizedDescription)
}
//recorder = nil
}
#IBAction func play(sender: UIButton) {
setSessionPlayback()
play()
}
func play() {
var url:NSURL?
if self.recorder != nil {
url = self.recorder.url
} else {
url = self.soundFileURL!
}
print("playing \(url)")
do {
self.player = try AVAudioPlayer(contentsOfURL: url!)
stopButton.enabled = true
player.enableRate = true
player.delegate = self
player.prepareToPlay()
player.volume = 1.0
player.play()
} catch let error as NSError {
self.player = nil
print(error.localizedDescription)
}
}
#IBAction func slideChange(sender: AnyObject) {
player.rate = sliderValue.value
}
func setupRecorder() {
let format = NSDateFormatter()
format.dateFormat="yyyy-MM-dd-HH-mm-ss"
let currentFileName = "recording-\(format.stringFromDate(NSDate())).m4a"
print(currentFileName)
let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
self.soundFileURL = documentsDirectory.URLByAppendingPathComponent(currentFileName)
if NSFileManager.defaultManager().fileExistsAtPath(soundFileURL.absoluteString) {
// probably won't happen. want to do something about it?
print("soundfile \(soundFileURL.absoluteString) exists")
}
let recordSettings:[String : AnyObject] = [
AVFormatIDKey: NSNumber(unsignedInt:kAudioFormatAppleLossless),
AVEncoderAudioQualityKey : AVAudioQuality.Max.rawValue,
AVEncoderBitRateKey : 320000,
AVNumberOfChannelsKey: 2,
AVSampleRateKey : 44100.0
]
do {
recorder = try AVAudioRecorder(URL: soundFileURL, settings: recordSettings)
recorder.delegate = self
recorder.meteringEnabled = true
recorder.prepareToRecord() // creates/overwrites the file at soundFileURL
} catch let error as NSError {
recorder = nil
print(error.localizedDescription)
}
}
func recordWithPermission(setup:Bool) {
let session:AVAudioSession = AVAudioSession.sharedInstance()
// ios 8 and later
if (session.respondsToSelector("requestRecordPermission:")) {
AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in
if granted {
print("Permission to record granted")
self.setSessionPlayAndRecord()
if setup {
self.setupRecorder()
}
self.recorder.record()
self.meterTimer = NSTimer.scheduledTimerWithTimeInterval(0.1,
target:self,
selector:"updateAudioMeter:",
userInfo:nil,
repeats:true)
} else {
print("Permission to record not granted")
}
})
} else {
print("requestRecordPermission unrecognized")
}
}
func setSessionPlayback() {
let session:AVAudioSession = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryPlayback)
} catch let error as NSError {
print("could not set session category")
print(error.localizedDescription)
}
do {
try session.setActive(true)
} catch let error as NSError {
print("could not make session active")
print(error.localizedDescription)
}
}
func setSessionPlayAndRecord() {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch let error as NSError {
print("could not set session category")
print(error.localizedDescription)
}
do {
try session.setActive(true)
} catch let error as NSError {
print("could not make session active")
print(error.localizedDescription)
}
}
func deleteAllRecordings() {
let docsDir =
NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let fileManager = NSFileManager.defaultManager()
do {
let files = try fileManager.contentsOfDirectoryAtPath(docsDir)
var recordings = files.filter( { (name: String) -> Bool in
return name.hasSuffix("m4a")
})
for var i = 0; i < recordings.count; i++ {
let path = docsDir + "/" + recordings[i]
print("removing \(path)")
do {
try fileManager.removeItemAtPath(path)
} catch let error as NSError {
NSLog("could not remove \(path)")
print(error.localizedDescription)
}
}
} catch let error as NSError {
print("could not get contents of directory at \(docsDir)")
print(error.localizedDescription)
}
}
func askForNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"background:",
name:UIApplicationWillResignActiveNotification,
object:nil)
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"foreground:",
name:UIApplicationWillEnterForegroundNotification,
object:nil)
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"routeChange:",
name:AVAudioSessionRouteChangeNotification,
object:nil)
}
func background(notification:NSNotification) {
print("background")
}
func foreground(notification:NSNotification) {
print("foreground")
}
func routeChange(notification:NSNotification) {
print("routeChange \(notification.userInfo)")
if let userInfo = notification.userInfo {
//print("userInfo \(userInfo)")
if let reason = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt {
//print("reason \(reason)")
switch AVAudioSessionRouteChangeReason(rawValue: reason)! {
case AVAudioSessionRouteChangeReason.NewDeviceAvailable:
print("NewDeviceAvailable")
print("did you plug in headphones?")
checkHeadphones()
case AVAudioSessionRouteChangeReason.OldDeviceUnavailable:
print("OldDeviceUnavailable")
print("did you unplug headphones?")
checkHeadphones()
case AVAudioSessionRouteChangeReason.CategoryChange:
print("CategoryChange")
case AVAudioSessionRouteChangeReason.Override:
print("Override")
case AVAudioSessionRouteChangeReason.WakeFromSleep:
print("WakeFromSleep")
case AVAudioSessionRouteChangeReason.Unknown:
print("Unknown")
case AVAudioSessionRouteChangeReason.NoSuitableRouteForCategory:
print("NoSuitableRouteForCategory")
case AVAudioSessionRouteChangeReason.RouteConfigurationChange:
print("RouteConfigurationChange")
}
}
}
}
func checkHeadphones() {
// check NewDeviceAvailable and OldDeviceUnavailable for them being plugged in/unplugged
let currentRoute = AVAudioSession.sharedInstance().currentRoute
if currentRoute.outputs.count > 0 {
for description in currentRoute.outputs {
if description.portType == AVAudioSessionPortHeadphones {
print("headphones are plugged in")
break
} else {
print("headphones are unplugged")
}
}
} else {
print("checking headphones requires a connection to a device")
}
}
#IBAction
func trim() {
if self.soundFileURL == nil {
print("no sound file")
return
}
print("trimming \(soundFileURL!.absoluteString)")
print("trimming path \(soundFileURL!.lastPathComponent)")
let asset = AVAsset(URL:self.soundFileURL!)
exportAsset(asset, fileName: "trimmed.m4a")
}
func exportAsset(asset:AVAsset, fileName:String) {
let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let trimmedSoundFileURL = documentsDirectory.URLByAppendingPathComponent(fileName)
print("saving to \(trimmedSoundFileURL.absoluteString)")
if NSFileManager.defaultManager().fileExistsAtPath(trimmedSoundFileURL.absoluteString) {
print("sound exists, removing \(trimmedSoundFileURL.absoluteString)")
do {
var error:NSError?
if trimmedSoundFileURL.checkResourceIsReachableAndReturnError(&error) {
print("is reachable")
}
if let e = error {
print(e.localizedDescription)
}
try NSFileManager.defaultManager().removeItemAtPath(trimmedSoundFileURL.absoluteString)
} catch let error as NSError {
NSLog("could not remove \(trimmedSoundFileURL)")
print(error.localizedDescription)
}
}
if let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) {
exporter.outputFileType = AVFileTypeAppleM4A
exporter.outputURL = trimmedSoundFileURL
let duration = CMTimeGetSeconds(asset.duration)
if (duration < 5.0) {
print("sound is not long enough")
return
}
// e.g. the first 5 seconds
let startTime = CMTimeMake(0, 1)
let stopTime = CMTimeMake(5, 1)
exporter.timeRange = CMTimeRangeFromTimeToTime(startTime, stopTime)
// do it
exporter.exportAsynchronouslyWithCompletionHandler({
switch exporter.status {
case AVAssetExportSessionStatus.Failed:
if let e = exporter.error {
print("export failed \(e)")
switch e.code {
case AVError.FileAlreadyExists.rawValue:
print("File Exists")
break
default: break
}
} else {
print("export failed")
}
case AVAssetExportSessionStatus.Cancelled:
print("export cancelled \(exporter.error)")
default:
print("export complete")
}
})
}
}
#IBAction
func speed() {
let asset = AVAsset(URL:self.soundFileURL!)
exportSpeedAsset(asset, fileName: "trimmed.m4a")
}
func exportSpeedAsset(asset:AVAsset, fileName:String) {
let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let trimmedSoundFileURL = documentsDirectory.URLByAppendingPathComponent(fileName)
let filemanager = NSFileManager.defaultManager()
if filemanager.fileExistsAtPath(trimmedSoundFileURL.absoluteString) {
print("sound exists")
}
if let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) {
exporter.outputFileType = AVFileTypeAppleM4A
exporter.outputURL = trimmedSoundFileURL
exporter.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmVarispeed
let duration = CMTimeGetSeconds(asset.duration)
if (duration < 5.0) {
print("sound is not long enough")
return
}
// do it
exporter.exportAsynchronouslyWithCompletionHandler({
switch exporter.status {
case AVAssetExportSessionStatus.Failed:
print("export failed \(exporter.error)")
case AVAssetExportSessionStatus.Cancelled:
print("export cancelled \(exporter.error)")
default:
print("export complete")
}
})
}
}
}
// MARK: AVAudioRecorderDelegate
extension RecorderViewController : AVAudioRecorderDelegate {
func audioRecorderDidFinishRecording(recorder: AVAudioRecorder,
successfully flag: Bool) {
print("finished recording \(flag)")
stopButton.enabled = false
playButton.enabled = true
recordButton.setTitle("Record", forState:.Normal)
// iOS8 and later
let alert = UIAlertController(title: "Recorder",
message: "Finished Recording",
preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Keep", style: .Default, handler: {action in
print("keep was tapped")
}))
alert.addAction(UIAlertAction(title: "Delete", style: .Default, handler: {action in
print("delete was tapped")
self.recorder.deleteRecording()
}))
self.presentViewController(alert, animated:true, completion:nil)
}
func audioRecorderEncodeErrorDidOccur(recorder: AVAudioRecorder,
error: NSError?) {
if let e = error {
print("\(e.localizedDescription)")
}
}
}
// MARK: AVAudioPlayerDelegate
extension RecorderViewController : AVAudioPlayerDelegate {
func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
print("finished playing \(flag)")
recordButton.enabled = true
stopButton.enabled = false
}
func audioPlayerDecodeErrorDidOccur(player: AVAudioPlayer, error: NSError?) {
if let e = error {
print("\(e.localizedDescription)")
}
}
}
reviewing your code I think that you should check first if player is not nil
something like this
#IBAction func slideChange(sender: AnyObject) {
if(player != nil)
{
player.rate = sliderValue.value
}
}
I hope this helps you!
Any one help to me to record and play audio Simultaneously in Iphone.
You can get a use from AVFoundation framework. It has AVAudioPlayer to play audio files and AVAudioRecorder to record.
You have to bear in mind that Recorder will record with the use of mic only.
So with the simultameously playing a audio file and recording it depends on how the mic will perceive the audio that is played.
Please Check aurioTouch apple sample code for audio record-and-play simultaneously
You can also check Recording Audio on an iPhone
To record an play the audio files in iOS, you can use AVFoundation framework. Use below swift code to record and play the audios.
Remember that recorder will record the audio with the use of mic, so please test this code on device.
import UIKit
import AVFoundation
extension String {
func stringByAppendingPathComponent(path: String) -> String {
let nsSt = self as NSString
return nsSt.stringByAppendingPathComponent(path)
}
}
class ViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate{
var audioPlayer : AVAudioPlayer!
var audioRecorder : AVAudioRecorder!
#IBOutlet var recordButton : UIButton!
#IBOutlet var playButton : UIButton!
#IBOutlet var stopButton : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.recordButton.enabled = true
self.playButton.enabled = false
self.stopButton.enabled = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//MARK: UIButton action methods
#IBAction func playButtonClicked(sender : AnyObject){
let dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(dispatchQueue, {
if let data = NSData(contentsOfFile: self.audioFilePath())
{
do{
self.audioPlayer = try AVAudioPlayer(data: data)
self.audioPlayer.delegate = self
self.audioPlayer.prepareToPlay()
self.audioPlayer.play()
}
catch{
print("\(error)")
}
}
});
}
#IBAction func stopButtonClicked(sender : AnyObject){
if let player = self.audioPlayer{
player.stop()
}
if let record = self.audioRecorder{
record.stop()
let session = AVAudioSession.sharedInstance()
do{
try session.setActive(false)
}
catch{
print("\(error)")
}
}
}
#IBAction func recordButtonClicked(sender : AnyObject){
let session = AVAudioSession.sharedInstance()
do{
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
try session.setActive(true)
session.requestRecordPermission({ (allowed : Bool) -> Void in
if allowed {
self.startRecording()
}
else{
print("We don't have request permission for recording.")
}
})
}
catch{
print("\(error)")
}
}
func startRecording(){
self.playButton.enabled = false
self.recordButton.enabled = false
self.stopButton.enabled = true
do{
let fileURL = NSURL(string: self.audioFilePath())!
self.audioRecorder = try AVAudioRecorder(URL: fileURL, settings: self.audioRecorderSettings() as! [String : AnyObject])
if let recorder = self.audioRecorder{
recorder.delegate = self
if recorder.record() && recorder.prepareToRecord(){
print("Audio recording started successfully")
}
}
}
catch{
print("\(error)")
}
}
func audioFilePath() -> String{
let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
let filePath = path.stringByAppendingPathComponent("test.caf") as String
return filePath
}
func audioRecorderSettings() -> NSDictionary{
let settings = [AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)), AVSampleRateKey : NSNumber(float: Float(16000.0)), AVNumberOfChannelsKey : NSNumber(int: 1), AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Medium.rawValue))]
return settings
}
//MARK: AVAudioPlayerDelegate methods
func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
if flag == true{
print("Player stops playing successfully")
}
else{
print("Player interrupted")
}
self.recordButton.enabled = true
self.playButton.enabled = false
self.stopButton.enabled = false
}
//MARK: AVAudioRecorderDelegate methods
func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) {
if flag == true{
print("Recording stops successfully")
}
else{
print("Stopping recording failed")
}
self.playButton.enabled = true
self.recordButton.enabled = false
self.stopButton.enabled = false
}
}
I had tested this code on xCode 7.0 & iOS 9.