I have been looking all over the place for an answer to this but cant find exactly what I need. Basically in my app I am recording voice to an audio file (like the iOS Voice Memo app) and then would like to save it to the local document dir. From some reason the URL that I am being given with the recorded file expires next time I launch the app. Besides, even if it did not, if I record twice, the second file URL gets the same URL as the first one, so I am losing the first file.
Recording this way:
[audioRecorder record];
Where: AVAudioRecorder *audioRecorder;
Playing is ok:
[audioPlayer play];
Where: AVAudioPlayer *audioPlayer;
What is the best way to record voice memo and save it to the local disk on the iPhone?
Thanks.
Update:
I tried to use this code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
BOOL status = [data writeToFile:filePath atomically:YES];
With the data being the data of my AVAudioPlayer NSData property, but BOOL gets 0, and no idea why.
To keep a single audio message, tap "Keep" underneath an audio message to prevent it from being automatically removed. If your device is using a version previous to iOS12, you also have the option to save audio messages to the Voice Memos app. To do this, tap and hold an audio message, then choose "Save".
If you have an iOS version earlier than iOS 12, your saved audio files will be in the Voice Memos app. To access them: Open 'Messages. '
The MPEG-4 codec used to record and play back audio files in the iPhone's Voice Memo app is compressed using the Advanced Audio Coding (AAC) codec or the Apple Lossless Audio Codec (ALAC). Because the Voice Memo app only records audio data, the ". M4A" file extension is used, rather than the ". MP4" file extension.
Return current date and time which we are use as sound file name.
Objective-c
- (NSString *) dateString
{
// return a formatted string for a file name
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"ddMMMYY_hhmmssa";
return [[formatter stringFromDate:[NSDate date]] stringByAppendingString:@".aif"];
}
Swift 4
func dateString() -> String {
let formatter = DateFormatter()
formatter.dateFormat = "ddMMMYY_hhmmssa"
let fileName = formatter.string(from: Date())
return "\(fileName).aif"
}
Setup Audio Session
Objective-c
- (BOOL) startAudioSession
{
// Prepare the audio session
NSError *error;
AVAudioSession *session = [AVAudioSession sharedInstance];
if (![session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error])
{
NSLog(@"Error setting session category: %@", error.localizedFailureReason);
return NO;
}
if (![session setActive:YES error:&error])
{
NSLog(@"Error activating audio session: %@", error.localizedFailureReason);
return NO;
}
return session.inputIsAvailable;
}
Swift 4
func startAudioSession() -> Bool {
let session = AVAudioSession()
do {
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch(let error) {
print("--> \(error.localizedDescription)")
}
do {
try session.setActive(true)
} catch (let error) {
print("--> \(error.localizedDescription)")
}
return session.isInputAvailable;
}
Record Sound..
Objective-c
- (BOOL) record
{
NSError *error;
// Recording settings
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
[settings setValue: [NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[settings setValue: [NSNumber numberWithFloat:8000.0] forKey:AVSampleRateKey];
[settings setValue: [NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
[settings setValue: [NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[settings setValue: [NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[settings setValue: [NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
[settings setValue: [NSNumber numberWithInt: AVAudioQualityMax] forKey:AVEncoderAudioQualityKey];
NSArray *searchPaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath_ = [searchPaths objectAtIndex: 0];
NSString *pathToSave = [documentPath_ stringByAppendingPathComponent:[self dateString]];
// File URL
NSURL *url = [NSURL fileURLWithPath:pathToSave];//FILEPATH];
// Create recorder
recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
if (!recorder)
{
NSLog(@"Error establishing recorder: %@", error.localizedFailureReason);
return NO;
}
// Initialize degate, metering, etc.
recorder.delegate = self;
recorder.meteringEnabled = YES;
//self.title = @"0:00";
if (![recorder prepareToRecord])
{
NSLog(@"Error: Prepare to record failed");
//[self say:@"Error while preparing recording"];
return NO;
}
if (![recorder record])
{
NSLog(@"Error: Record failed");
// [self say:@"Error while attempting to record audio"];
return NO;
}
// Set a timer to monitor levels, current time
timer = [NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(updateMeters) userInfo:nil repeats:YES];
return YES;
}
Swift 4
func record() -> Bool {
var settings: [String: Any] = [String: String]()
settings[AVFormatIDKey] = kAudioFormatLinearPCM
settings[AVSampleRateKey] = 8000.0
settings[AVNumberOfChannelsKey] = 1
settings[AVLinearPCMBitDepthKey] = 16
settings[AVLinearPCMIsBigEndianKey] = false
settings[AVLinearPCMIsFloatKey] = false
settings[AVAudioQualityMax] = AVEncoderAudioQualityKey
let searchPaths: [String] = NSSearchPathForDirectoriesInDomains(.documentDirectory, .allDomainsMask, true)
let documentPath_ = searchPaths.first
let pathToSave = "\(documentPath_)/\(dateString)"
let url: URL = URL(pathToSave)
recorder = try? AVAudioRecorder(url: url, settings: settings)
// Initialize degate, metering, etc.
recorder.delegate = self;
recorder.meteringEnabled = true;
recorder?.prepareToRecord()
if let recordIs = recorder {
return recordIs.record()
}
return false
}
Play sound...Retrieve From document directiory
Objective-c
-(void)play
{
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath_ = [searchPaths objectAtIndex: 0];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:[self recordingFolder]])
{
arrayListOfRecordSound=[[NSMutableArray alloc]initWithArray:[fileManager contentsOfDirectoryAtPath:documentPath_ error:nil]];
NSLog(@"====%@",arrayListOfRecordSound);
}
NSString *selectedSound = [documentPath_ stringByAppendingPathComponent:[arrayListOfRecordSound objectAtIndex:0]];
NSURL *url =[NSURL fileURLWithPath:selectedSound];
//Start playback
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
if (!player)
{
NSLog(@"Error establishing player for %@: %@", recorder.url, error.localizedFailureReason);
return;
}
player.delegate = self;
// Change audio session for playback
if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error])
{
NSLog(@"Error updating audio session: %@", error.localizedFailureReason);
return;
}
self.title = @"Playing back recording...";
[player prepareToPlay];
[player play];
}
Swift 4
func play() {
let searchPaths: [String] = NSSearchPathForDirectoriesInDomains(.documentDirectory, .allDomainsMask, true)
let documentPath_ = searchPaths.first
let fileManager = FileManager.default
let arrayListOfRecordSound: [String]
if fileManager.fileExists(atPath: recordingFolder()) {
let arrayListOfRecordSound = try? fileManager.contentsOfDirectory(atPath: documentPath_)
}
let selectedSound = "\(documentPath_)/\(arrayListOfRecordSound.first)"
let url = URL.init(fileURLWithPath: selectedSound)
let player = try? AVAudioPlayer(contentsOf: url)
player?.delegate = self;
try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
player?.prepareToPlay()
player?.play()
}
stopRecording
Objective-c
- (void) stopRecording
{
// This causes the didFinishRecording delegate method to fire
[recorder stop];
}
Swift 4
func stopRecording() {
recorder?.stop()
}
continueRecording
Objective-c
- (void) continueRecording
{
// resume from a paused recording
[recorder record];
}
Swift 4
func continueRecording() {
recorder?.record()
}
pauseRecording
Objective-c
- (void) pauseRecording
{ // pause an ongoing recording
[recorder pause];
}
Swift 4
func pauseRecording() {
recorder?.pause()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With