xcode: How to save audio file after recording audio using AVFoundation

17,067

Solution 1

You need to stop recording in order to save the data to the file permanently:

[recorder stop];

Solution 2

The problem is that when you tell XCode (in the viewDidLoad method) to [recorder prepareToRecord]; it gets rid of the previously recorded audio file. Eliminate that piece of code in the "if" statement and your audio file WILL be saved when you exit and come back in to the app.

Solution 3

FYI -- The "[recorder prepareToRecord]" method creates a fresh audio file, overwriting any previous recorded file.

Share:
17,067
iPhoneNoob
Author by

iPhoneNoob

Updated on June 05, 2022

Comments

  • iPhoneNoob
    iPhoneNoob almost 2 years

    I browsed through all kinds of post related to this topic but the answers just do not really help. I used this tutorial to implement recording of audio files and playback. What seems to be missing is how to save the record permanently. When I exit my app the sound file is there but nothing is in it. I don't even know if it is saving the rocerd or just creating the file. Here is a code sample:

    NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docsDir = [dirPaths objectAtIndex:0];
    NSString *soundFilePath = [docsDir
                                   stringByAppendingPathComponent:@"tmpSound.caf"];
    
    tempRecFile = [NSURL fileURLWithPath:soundFilePath];
    
    NSDictionary *recSettings = [NSDictionary 
                                        dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithInt:AVAudioQualityMin],
                                        AVEncoderAudioQualityKey,
                                        [NSNumber numberWithInt:16], 
                                        AVEncoderBitRateKey,
                                        [NSNumber numberWithInt: 2], 
                                        AVNumberOfChannelsKey,
                                        [NSNumber numberWithFloat:44100.0], 
                                        AVSampleRateKey,
                                        nil];
    
    recorder = [[AVAudioRecorder alloc] initWithURL:tempRecFile settings:recSettings error:nil];
    [recorder setDelegate:self];
    [recorder prepareToRecord];
    [recorder record];
    

    I saw a possible solution to this problem here but since I'm new to iOS I do not really get it or it is just does not working for me.

    Please help and provide a code example. I read the documentation about AVFoundation and other classes but with no positive results.

    SOS :)

    UPDATE This is my recording method:

    -(IBAction)recording{
        //***** METHOD for recording
    
        if(isNotRecording){
            isNotRecording = NO;
            [recButton setTitle:@"Stop"  forState:UIControlStateNormal];
            recStateLabel.text = @"Recording";
    
            [recorder setDelegate:self];
            [recorder prepareToRecord];
            [recorder record];
    
        }
        else{
            isNotRecording = YES;
            [recButton setTitle:@"Rec Begin" forState:UIControlStateNormal];
            playButton.hidden = NO;
            recStateLabel.text = @"Not recording";
            [recorder stop];
        }
    
    
    }
    

    This is my viewDidLoad:

    - (void)viewDidLoad
    {
        //record sound test code - start
        isNotRecording = YES;
        //playButton.hidden = YES;
        recStateLabel.text = @"Not recording";
    
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    
        [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    
        [audioSession setActive:YES error:nil];
        //record sound test code -  END
    
        [super viewDidLoad];
        // Do any additional setup after loading the view from its nib.
    
        // code for generating the sound file that is to be saved
        NSArray *dirPaths;
        NSString *docsDir;
    
        dirPaths = NSSearchPathForDirectoriesInDomains(
                                                       NSDocumentDirectory, NSUserDomainMask, YES);
        docsDir = [dirPaths objectAtIndex:0];
        NSString *soundFilePath = [docsDir
                                   stringByAppendingPathComponent:@"sound.caf"];
    
        NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
    
        NSDictionary *recordSettings = [NSDictionary 
                                        dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithInt:AVAudioQualityMin],
                                        AVEncoderAudioQualityKey,
                                        [NSNumber numberWithInt:16], 
                                        AVEncoderBitRateKey,
                                        [NSNumber numberWithInt: 2], 
                                        AVNumberOfChannelsKey,
                                        [NSNumber numberWithFloat:44100.0], 
                                        AVSampleRateKey,
                                        nil];
    
        NSError *error = nil;
    
        recorder = [[AVAudioRecorder alloc]
                         initWithURL:soundFileURL
                         settings:recordSettings
                         error:&error];
    
        if (error)
        {
            NSLog(@"error: %@", [error localizedDescription]);
    
        } else {
            [recorder prepareToRecord];
        }
    
    }
    

    This is my playBack method:

    -(IBAction)playback{
        //AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:temporaryRecFile error:nil];
        NSError *error;
        // setting the uri of the formed created file
        NSArray *dirPaths;
        NSString *docsDir;
    
    
    
    dirPaths = NSSearchPathForDirectoriesInDomains(
                                                   NSDocumentDirectory, NSUserDomainMask, YES);
    docsDir = [dirPaths objectAtIndex:0];
    NSString *soundFilePath = [docsDir
                               stringByAppendingPathComponent:@"sound.caf"];
    
    NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
    
    AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:soundFileURL error:&error];
    
    
    
    [player setNumberOfLoops:0];
    [player prepareToPlay];
    [player setVolume:1];
    [player play];
    NSLog(@"URL je: %@", soundFileURL);
    
    
    //method 2
    if (error)
        NSLog(@"Error: %@", 
              [error localizedDescription]);
    else
    {
    
        [player play];
        if(player.isPlaying==YES)
        {
            NSLog(@"It's playing");
        }
    }
    

    }

    I hopše this makes it clear what I do. Any suggestions where I might be wrong?

  • iPhoneNoob
    iPhoneNoob about 12 years
    Hello @mahboudz, I stop recording using [recorder stop]. I don't think that's the problem. After I stop recording, I can play the 'recorded' sound using the AVplayer with the same url as the recorder. The problem is that the sound is not played after I restart my app. Taht means that it is not saved permanetly but only during the session/instance.
  • mahboudz
    mahboudz about 12 years
    Are you saying that the file is zero-length after you stop recording?
  • mahboudz
    mahboudz about 12 years
    Have you implemented the delegate method: - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error? This could tell you if there was an error when encrypting. And when do you call -stop? Is it when the app is being put into the background? or before?
  • iPhoneNoob
    iPhoneNoob about 12 years
    I just updated my Question and filled in my code so you can see everything I got. There is no error just no sound when I push the play button after app restart. Then I record something and press the play button and the sound is there.
  • mahboudz
    mahboudz about 12 years
    Can you please post your log/console messages? I want to see what the NSLogs are outputting.
  • iPhoneNoob
    iPhoneNoob about 12 years
    There is no error in the console. actually there is nothing beside the url to the sound file(sound.caf) that I wrote here NSLog(@"URL je: %@", soundFileURL); there are no errors...
  • mahboudz
    mahboudz about 12 years
    Use Xcode's Organizer window to get to the application and download it to your Mac. Then open the documents folder and see if the sound file is zero length or not.
  • iPhoneNoob
    iPhoneNoob about 12 years
    Hi @mahboudz, I'll do that when I get home. In the meanwhile, is there any method to show in the console if the file is 0 lenght? Another question. Do you see anything wrong in my code or do you have any code samples that save recorded sound so I can see on that example?
  • mahboudz
    mahboudz about 12 years
    It's probably easiest to use the organizer window to download the app from the device to the Mac and open contents of the bundle and check the sound file. Otherwise you will have to use the File Manager routines to get the size of the file and use NSLog to display it. I don't see any glaring issues, but then it is late here and I haven't had much sleep. It would be easier to do this via chat, but StackOVerflow won't let you until you build up your reputation.
  • mahboudz
    mahboudz about 12 years
  • iPhoneNoob
    iPhoneNoob about 12 years
    Oh Thank you so much for the sample. I always typed 'xcode' in the search so I never found it. I'll try that code and write you tonight(CMT+1 here) :) how it was. Thanks again!
  • iPhoneNoob
    iPhoneNoob about 12 years
    Hey mahboudz, thanks a lot for the example. It helped me a lot. The error was saving it to NSDocumentDirectory instead of NSHomeDirectory. After changing that part the rest was working fine.
  • Rajneesh071
    Rajneesh071 over 11 years
    hi...using this code my recording in not working in iPad, its working fine in iPod