AVfoundation无法在iOS 5中录制音频

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AVfoundation无法在iOS 5中录制音频相关的知识,希望对你有一定的参考价值。

我在尝试构建一个简单的录音功能时遇到了一些重大麻烦,我不知道为什么。我已经按照一些代码(从这里和其他地方)来构建一个非常简单的录音机和播放,但没有任何作用。我已经采用了适用于ios 4.3的示例代码,并且当我单独运行它时工作正常,但是只要我将它带到iOS 5并使用ARC,就没有任何反应。该应用程序运行,但没有录制音频......任何想法都会很棒!谢谢...附上我所有的代码。这是来自此处示例的代码。

record_audio_testViewController.h

 #import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>

@interface record_audio_testViewController : UIViewController <AVAudioRecorderDelegate> {

    IBOutlet UIButton * btnStart;
    IBOutlet UIButton * btnPlay;
    IBOutlet UIActivityIndicatorView * actSpinner;
    BOOL toggle;

    //Variables setup for access in the class:
    NSURL * recordedTmpFile;
    AVAudioRecorder * recorder;
    NSError *__autoreleasing * error;
    AVAudioSession * audioSession;

}

@property (nonatomic,retain)IBOutlet UIActivityIndicatorView * actSpinner;
@property (nonatomic,retain)IBOutlet UIButton * btnStart;
@property (nonatomic,retain)IBOutlet UIButton * btnPlay;
@property (nonatomic,strong)    AVAudioSession * audioSession;
@property (nonatomic,strong)    AVAudioRecorder * recorder;

- (IBAction) start_button_pressed;
- (IBAction) play_button_pressed;
@end

record_audio_testViewController.m

#import "record_audio_testViewController.h"


@implementation record_audio_testViewController
@synthesize actSpinner, btnStart, btnPlay, audioSession, recorder;



/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/



// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    //Start the toggle in true mode.
    toggle = YES;
    btnPlay.hidden = YES;

    //Instanciate an instance of the AVAudioSession object.
    audioSession = [AVAudioSession sharedInstance];
    //Setup the audioSession for playback and record. 
    //We could just use record and then switch it to playback leter, but
    //since we are going to do both lets set it up once.
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: error];
    //Activate the session
    [audioSession setActive:YES error: error];
    NSLog(@"%@",error);

}



/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (IBAction)  start_button_pressed{

    if(toggle)
    {
        toggle = NO;
        [actSpinner startAnimating];
        [btnStart setTitle:@"Stop Recording" forState: UIControlStateNormal ];  
        btnPlay.enabled = toggle;
        btnPlay.hidden = !toggle;

        //Begin the recording session.
        //Error handling removed.  Please add to your own code.

        //Setup the dictionary object with all the recording settings that this 
        //Recording sessoin will use
        //Its not clear to me which of these are required and which are the bare minimum.
        //This is a good resource: http://www.totodotnet.net/tag/avaudiorecorder/
        NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init];
        [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
        [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; 
        [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];

        //Now that we have our settings we are going to instanciate an instance of our recorder instance.
        //Generate a temp file for use by the recording.
        //This sample was one I found online and seems to be a good choice for making a tmp file that
        //will not overwrite an existing one.
        //I know this is a mess of collapsed things into 1 call.  I can break it out if need be.
        recordedTmpFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: @"%.0f.%@", [NSDate timeIntervalSinceReferenceDate] * 1000.0, @"caf"]]];
        NSLog(@"Using File called: %@",recordedTmpFile);
        //Setup the recorder to use this file and record to it.
        NSLog(@"%@",error);
        recorder = [[ AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSetting error:error];
        NSLog(@"%@",error);
        //Use the recorder to start the recording.
        //Im not sure why we set the delegate to self yet.  
        //Found this in antother example, but Im fuzzy on this still.
        [recorder setDelegate:self];
        //We call this to start the recording process and initialize 
        //the subsstems so that when we actually say "record" it starts right away.
        [recorder prepareToRecord];
        //Start the actual Recording
        [recorder record];
        //There is an optional method for doing the recording for a limited time see 
        //[recorder recordForDuration:(NSTimeInterval) 10]

    }
    else
    {
        toggle = YES;
        [actSpinner stopAnimating];
        [btnStart setTitle:@"Start Recording" forState:UIControlStateNormal ];
        btnPlay.enabled = toggle;
        btnPlay.hidden = !toggle;

        NSLog(@"Using File called: %@",recordedTmpFile);
        //Stop the recorder.
        [recorder stop];
    }
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

-(IBAction) play_button_pressed{

    //The play button was pressed... 
    //Setup the AVAudioPlayer to play the file that we just recorded.

    AVAudioPlayer * avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:recordedTmpFile error:error];
    [avPlayer prepareToPlay];
    [avPlayer play];
     NSLog(@"%@",error);

}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    //Clean up the temp file.
    NSFileManager * fm = [NSFileManager defaultManager];

    [fm removeItemAtPath:[recordedTmpFile path] error:error];
    //Call the dealloc on the remaining objects.

}



@end

viewController.h

#import <UIKit/UIKit.h>
#import "record_audio_testViewController.h"


@interface ViewController : UIViewController{
record_audio_testViewController *audioControl;

}

@end

viewController.m

#import "ViewController.h"
#import "record_audio_testViewController.h"


@implementation ViewController


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{

    [super viewDidLoad];
    audioControl = [[record_audio_testViewController alloc] init];
    [self.view addSubview:audioControl.view];

    // Do any additional setup after loading the view, typically from a nib.
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end
答案

(1)这可能与你的问题无关,但我很惊讶这甚至编译:

NSError *__autoreleasing * error; // ivar
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: error];

那是无法谈论的。 error应该是一个局部变量,你应该拿它的地址,你没有业务标记为自动释放:

NSError *error;
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: &error];

(2)除非你像VoIP应用程序一样,否则不要使用PlayAndRecord。如果您要执行的操作是录制,则您的音频会话策略应为“录制”,并且仅在您实际录制时。

我很抱歉,如果这些都没有解决问题,但它们可能是你应该首先解决的问题。

以上是关于AVfoundation无法在iOS 5中录制音频的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在不使用 AVFoundation 框架的情况下在 iOS 中录制音频?

Swift IOS 使用 AVFoundation 录制视频和音频

Objective-C:在 iOS 上使用 AVFoundation 录制视频时静音/取消静音

xcode:如何在使用 AVFoundation 录制音频后保存音频文件

Swift 4 AVFoundation - 同时录制多个音频源

iOS音频播放录音视频播放拍照视频录制