【问题标题】:How do I record audio on iPhone with AVAudioRecorder?如何使用 AVAudioRecorder 在 iPhone 上录制音频?
【发布时间】:2010-11-03 20:45:57
【问题描述】:

既然 iPhone 3.0 SDK 是公开的,我想我可以向那些已经在使用 3.0 SDK 的人提出这个问题。我想在我的应用程序中录制音频,但我想使用AVAudioRecorder,而不是像SpeakHere 示例所示的较旧的录制方式。 iPhone Dev Center 中没有任何关于如何最好地做到这一点的示例,仅引用了这些类。我是 iPhone 开发的新手,所以我正在寻找一个简单的示例来帮助我入门。

【问题讨论】:

    标签: ios objective-c iphone audio recording


    【解决方案1】:

    实际上,根本没有例子。 这是我的工作代码。记录由用户按下导航栏上的按钮触发。 录音使用 cd 质量(44100 个样本)、立体声(2 通道)线性 pcm。注意:如果您想使用不同的格式,尤其是编码格式,请确保您完全了解如何设置 AVAudioRecorder 设置(仔细阅读音频类型文档),否则您将永远无法正确初始化它。还有一件事。在代码中,我没有展示如何处理计量数据,但您可以轻松搞定。 最后,请注意,在撰写本文时,AVAudioRecorder 方法 deleteRecording 会使您的应用程序崩溃。这就是我通过文件管理器删除录制文件的原因。录制完成后,我使用 KVC 将录制的音频保存为 NSData 在当前编辑的对象中。

    #define DOCUMENTS_FOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]
    
    
    - (void) startRecording{
    
    UIBarButtonItem *stopButton = [[UIBarButtonItem alloc] initWithTitle:@"Stop" style:UIBarButtonItemStyleBordered  target:self action:@selector(stopRecording)];
    self.navigationItem.rightBarButtonItem = stopButton;
    [stopButton release];
    
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    NSError *err = nil;
    [audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
    if(err){
        NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
        return;
    }
    [audioSession setActive:YES error:&err];
    err = nil;
    if(err){
        NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
        return;
    }
    
    recordSetting = [[NSMutableDictionary alloc] init];
    
    [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
    [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; 
    [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
    
    [recordSetting setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    [recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
    [recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
    
    
    
    // Create a new dated file
    NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0];
    NSString *caldate = [now description];
    recorderFilePath = [[NSString stringWithFormat:@"%@/%@.caf", DOCUMENTS_FOLDER, caldate] retain];
    
    NSURL *url = [NSURL fileURLWithPath:recorderFilePath];
    err = nil;
    recorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&err];
    if(!recorder){
        NSLog(@"recorder: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
        UIAlertView *alert =
        [[UIAlertView alloc] initWithTitle: @"Warning"
                                   message: [err localizedDescription]
                                  delegate: nil
                         cancelButtonTitle:@"OK"
                         otherButtonTitles:nil];
        [alert show];
        [alert release];
        return;
    }
    
    //prepare to record
    [recorder setDelegate:self];
    [recorder prepareToRecord];
    recorder.meteringEnabled = YES;
    
    BOOL audioHWAvailable = audioSession.inputIsAvailable;
    if (! audioHWAvailable) {
        UIAlertView *cantRecordAlert =
        [[UIAlertView alloc] initWithTitle: @"Warning"
                                   message: @"Audio input hardware not available"
                                  delegate: nil
                         cancelButtonTitle:@"OK"
                         otherButtonTitles:nil];
        [cantRecordAlert show];
        [cantRecordAlert release]; 
        return;
    }
    
    // start recording
    [recorder recordForDuration:(NSTimeInterval) 10];
    
    }
    
    - (void) stopRecording{
    
    [recorder stop];
    
    NSURL *url = [NSURL fileURLWithPath: recorderFilePath];
    NSError *err = nil;
    NSData *audioData = [NSData dataWithContentsOfFile:[url path] options: 0 error:&err];
    if(!audioData)
        NSLog(@"audio data: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
    [editedObject setValue:[NSData dataWithContentsOfURL:url] forKey:editedFieldKey];   
    
    //[recorder deleteRecording];
    
    
    NSFileManager *fm = [NSFileManager defaultManager];
    
    err = nil;
    [fm removeItemAtPath:[url path] error:&err];
    if(err)
        NSLog(@"File Manager: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
    
    
    
    UIBarButtonItem *startButton = [[UIBarButtonItem alloc] initWithTitle:@"Record" style:UIBarButtonItemStyleBordered  target:self action:@selector(startRecording)];
    self.navigationItem.rightBarButtonItem = startButton;
    [startButton release];
    
    }
    
    - (void)audioRecorderDidFinishRecording:(AVAudioRecorder *) aRecorder successfully:(BOOL)flag
    {
    
    NSLog (@"audioRecorderDidFinishRecording:successfully:");
    // your actions here
    
    }
    

    【讨论】:

    • 我想我已经接近让你的代码工作了,但我正在努力处理委托的事情。我对Objective C还是很陌生,但仍然没有弄清楚为这样的事情做委托的正确方法。我让我的代表尝试实现 NSObject ,但我认为我做得不对。也发布委托代码会不会太麻烦?谢谢。
    • 我终于把它添加到我的委托类 @protocol AVAudioRecorder @optional - (void)audioRecorderBeginInterruption:(AVAudioRecorder *)recorder; - (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)录音成功:(BOOL)flag; - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)录音机错误:(NSError *)error; - (void)audioRecorderEndInterruption:(AVAudioRecorder *)recorder;它似乎有效,但我不知道这是否是最佳做法。现在我需要将它保存到本地数据存储中并在其他内容中播放它。
    • 这不对,吉姆。在您的记录器控制器标题中,您可以执行类似... #import @interface RecorderViewController : UIViewController {
    • 一些问题:stopRecording 中的editedObject 和editedFieldKey 未定义。你能给我点灯吗?
    • @Olie,它们在功能上是相同的。我修改了我没有使用当前日期的原始代码,所以我的代码中已经有一个像recordingDate = [NSDate dateWithTimeIntervalSinceNow:lastEvent]这样的语句。我只是把它改成了你在代码sn-p中看到的那个,但是,因为懒,我没有重写语句;-)
    【解决方案2】:

    虽然这是一个已回答的问题(而且有点老),但我决定将我的完整工作代码发布给那些发现很难找到好的工作(开箱即用)播放和录制示例的其他人 - 包括编码、pcm、通过扬声器播放,在此处写入文件:

    AudioPlayerViewController.h:

    #import <UIKit/UIKit.h>
    #import <AVFoundation/AVFoundation.h>
    
    @interface AudioPlayerViewController : UIViewController {
    AVAudioPlayer *audioPlayer;
    AVAudioRecorder *audioRecorder;
    int recordEncoding;
    enum
    {
        ENC_AAC = 1,
        ENC_ALAC = 2,
        ENC_IMA4 = 3,
        ENC_ILBC = 4,
        ENC_ULAW = 5,
        ENC_PCM = 6,
    } encodingTypes;
    }
    
    -(IBAction) startRecording;
    -(IBAction) stopRecording;
    -(IBAction) playRecording;
    -(IBAction) stopPlaying;
    
    @end
    

    AudioPlayerViewController.m:

    #import "AudioPlayerViewController.h"
    
    @implementation AudioPlayerViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        recordEncoding = ENC_AAC;
    }
    
    -(IBAction) startRecording
    {
    NSLog(@"startRecording");
    [audioRecorder release];
    audioRecorder = nil;
    
    // Init audio with record capability
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
    
    NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] initWithCapacity:10];
    if(recordEncoding == ENC_PCM)
    {
        [recordSettings setObject:[NSNumber numberWithInt: kAudioFormatLinearPCM] forKey: AVFormatIDKey];
        [recordSettings setObject:[NSNumber numberWithFloat:44100.0] forKey: AVSampleRateKey];
        [recordSettings setObject:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
        [recordSettings setObject:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
        [recordSettings setObject:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
        [recordSettings setObject:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];   
    }
    else
    {
        NSNumber *formatObject;
    
        switch (recordEncoding) {
            case (ENC_AAC): 
                formatObject = [NSNumber numberWithInt: kAudioFormatMPEG4AAC];
                break;
            case (ENC_ALAC):
                formatObject = [NSNumber numberWithInt: kAudioFormatAppleLossless];
                break;
            case (ENC_IMA4):
                formatObject = [NSNumber numberWithInt: kAudioFormatAppleIMA4];
                break;
            case (ENC_ILBC):
                formatObject = [NSNumber numberWithInt: kAudioFormatiLBC];
                break;
            case (ENC_ULAW):
                formatObject = [NSNumber numberWithInt: kAudioFormatULaw];
                break;
            default:
                formatObject = [NSNumber numberWithInt: kAudioFormatAppleIMA4];
        }
    
        [recordSettings setObject:formatObject forKey: AVFormatIDKey];
        [recordSettings setObject:[NSNumber numberWithFloat:44100.0] forKey: AVSampleRateKey];
        [recordSettings setObject:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
        [recordSettings setObject:[NSNumber numberWithInt:12800] forKey:AVEncoderBitRateKey];
        [recordSettings setObject:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
        [recordSettings setObject:[NSNumber numberWithInt: AVAudioQualityHigh] forKey: AVEncoderAudioQualityKey];
    }
    
    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/recordTest.caf", [[NSBundle mainBundle] resourcePath]]];
    
    
    NSError *error = nil;
    audioRecorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:&error];
    
    if ([audioRecorder prepareToRecord] == YES){
        [audioRecorder record];
    }else {
        int errorCode = CFSwapInt32HostToBig ([error code]); 
        NSLog(@"Error: %@ [%4.4s])" , [error localizedDescription], (char*)&errorCode); 
    
    }
    NSLog(@"recording");
    }
    
    -(IBAction) stopRecording
    {
    NSLog(@"stopRecording");
    [audioRecorder stop];
    NSLog(@"stopped");
    }
    
    -(IBAction) playRecording
    {
    NSLog(@"playRecording");
    // Init audio with playback capability
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
    
    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/recordTest.caf", [[NSBundle mainBundle] resourcePath]]];
    NSError *error;
    audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    audioPlayer.numberOfLoops = 0;
    [audioPlayer play];
    NSLog(@"playing");
    }
    
    -(IBAction) stopPlaying
    {
    NSLog(@"stopPlaying");
    [audioPlayer stop];
    NSLog(@"stopped");
    }
    
    - (void)dealloc
    {
    [audioPlayer release];
    [audioRecorder release];
    [super dealloc];
    }
    
    @end
    

    希望这对你们中的一些人有所帮助。

    【讨论】:

    • 您好,当我在 iphone 模拟器上构建并运行 ShayBC 提供的第二个代码时,我没有得到任何结果,但在控制台中它显示它正在工作。 Iphone 模拟器是使用我笔记本电脑的扬声器和麦克风,还是静音,我必须在设备上构建应用程序?
    • @Bataly iphone 模拟器会播放你的声音文件 (mp3 / caf...) 并且可以通过你的笔记本电脑麦克风录制如果有问题,请尝试查看 leopard System Preferences,但最好的方法是测试您的应用程序是在真正的 iDevice 上运行它,这对于您编写的所有代码都是一个好主意,因为有很多应用程序由于崩溃而被应用商店拒绝,因为它们从未在真正的 iDevice 上进行过测试,还有更多模拟器不支持的功能(蓝牙、摄像头、适当的多点触控、加速度计、IAP、GPS,它将比大多数 iDevice 具有更好的性能......)
    • [recordSettings setObject:formatObject forKey: AVFormatIDKey];这条线不会让我使用 AVFormatIDKey 作为键。是什么赋予了?如果我将它设置为另一个值,它就可以工作......
    • 最新发现,对于 kAudioFormatMPEG4AAC,我们无法将 AVEncoderBitRateKey 设置为 12800。注释掉行,它会起作用。将尝试找出 AAC 的正确比特率。
    • 我不认为你可以写包,所以我写这样的文档: NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *basePath = 路径[0]; NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/recordTest.caf", basePath]];
    【解决方案3】:

    我已经上传了一个示例项目。你可以看看。

    VoiceRecorder

    【讨论】:

    • 以防万一您找不到下载:转到右上角的“下载”,然后转到“下载包”
    • @Phlibbo:现在什么都找不到?
    • @user523234:这里是下载地址 - github.com/AvinashP/VoiceRecorder/downloads#download_128004
    • 示例代码没有按照 6 个月前 Github 问题中的说明进行编译。
    • 我已经修复了代码并签入了 github。它现在应该可以工作了。
    【解决方案4】:

    真的很有帮助。我唯一的问题是录制后创建的声音文件的大小。我需要减小文件大小,所以我对设置进行了一些更改。

    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
    [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
    [recordSetting setValue:[NSNumber numberWithFloat:16000.0] forKey:AVSampleRateKey];
    [recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
    

    文件大小从 360kb 减少到仅 25kb(录制 2 秒)。

    【讨论】:

    • 您也可以发布其余代码吗?因为我想我错过了什么。我尝试更改许多设置,但无法减小文件大小..
    • 我已经上传了一个示例项目。你可以看看。 github.com/AvinashP/VoiceRecorder
    【解决方案5】:

    在过去的 2 个小时里,我一直试图让这段代码正常工作,虽然它在模拟器上没有显示错误,但在设备上有一个错误。

    事实证明,至少在我的情况下,错误来自使用的目录(捆绑):

    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/recordTest.caf", [[NSBundle mainBundle] resourcePath]]];
    

    它不可写或类似的东西......除了prepareToRecord失败的事实之外没有错误......

    因此我将其替换为:

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *recDir = [paths objectAtIndex:0];
    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/recordTest.caf", recDir]]
    

    它现在就像一个魅力。

    希望这对其他人有所帮助。

    【讨论】:

    • 你没有权限写入资源文件夹
    【解决方案6】:

    非常感谢 @Massimo CafaroShaybc 我能够完成以下任务

    在 iOS 8 中:

    录制音频并保存

    播放保存的录音

    1.将“AVFoundation.framework”添加到您的项目中

    在.h文件中

    2.在导入语句'AVFoundation/AVFoundation.h'下面添加。

    3.定义“AVAudioRecorderDelegate”

    4.使用录制、播放按钮及其操作方法创建布局

    5.定义记录器和播放器等

    这是完整的示例代码,可能会对您有所帮助。

    ViewController.h

    #import <UIKit/UIKit.h>
    #import <AVFoundation/AVFoundation.h>
    
    @interface ViewController : UIViewController <AVAudioRecorderDelegate>
    
    @property(nonatomic,strong) AVAudioRecorder *recorder;
    @property(nonatomic,strong) NSMutableDictionary *recorderSettings;
    @property(nonatomic,strong) NSString *recorderFilePath;
    @property(nonatomic,strong) AVAudioPlayer *audioPlayer;
    @property(nonatomic,strong) NSString *audioFileName;
    
    - (IBAction)startRecording:(id)sender;
    - (IBAction)stopRecording:(id)sender;
    
    - (IBAction)startPlaying:(id)sender;
    - (IBAction)stopPlaying:(id)sender;
    
    @end
    

    然后在

    中完成工作

    ViewController.m

    #import "ViewController.h"
    
    #define DOCUMENTS_FOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]
    
    @interface ViewController ()
    @end
    
    @implementation ViewController
    
    @synthesize recorder,recorderSettings,recorderFilePath;
    @synthesize audioPlayer,audioFileName;
    
    
    #pragma mark - View Controller Life cycle methods
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
    }
    
    
    #pragma mark - Audio Recording
    - (IBAction)startRecording:(id)sender
    {
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        NSError *err = nil;
        [audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
        if(err)
        {
            NSLog(@"audioSession: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]);
            return;
        }
        [audioSession setActive:YES error:&err];
        err = nil;
        if(err)
        {
            NSLog(@"audioSession: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]);
            return;
        }
        
        recorderSettings = [[NSMutableDictionary alloc] init];
        [recorderSettings setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
        [recorderSettings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
        [recorderSettings setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
        [recorderSettings setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
        [recorderSettings setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
        [recorderSettings setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
        
        // Create a new audio file
        audioFileName = @"recordingTestFile";
        recorderFilePath = [NSString stringWithFormat:@"%@/%@.caf", DOCUMENTS_FOLDER, audioFileName] ;
        
        NSURL *url = [NSURL fileURLWithPath:recorderFilePath];
        err = nil;
        recorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recorderSettings error:&err];
        if(!recorder){
            NSLog(@"recorder: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]);
            UIAlertView *alert =
            [[UIAlertView alloc] initWithTitle: @"Warning" message: [err localizedDescription] delegate: nil
                             cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
            return;
        }
        
        //prepare to record
        [recorder setDelegate:self];
        [recorder prepareToRecord];
        recorder.meteringEnabled = YES;
        
        BOOL audioHWAvailable = audioSession.inputIsAvailable;
        if (! audioHWAvailable) {
            UIAlertView *cantRecordAlert =
            [[UIAlertView alloc] initWithTitle: @"Warning"message: @"Audio input hardware not available"
                                      delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [cantRecordAlert show];
            return;
        }
        
        // start recording
        [recorder recordForDuration:(NSTimeInterval) 60];//Maximum recording time : 60 seconds default
        NSLog(@"Recroding Started");
    }
    
    - (IBAction)stopRecording:(id)sender
    {
        [recorder stop];
        NSLog(@"Recording Stopped");
    }
    
    - (void)audioRecorderDidFinishRecording:(AVAudioRecorder *) aRecorder successfully:(BOOL)flag
    {
        NSLog (@"audioRecorderDidFinishRecording:successfully:");
    }
    
    
    #pragma mark - Audio Playing
    - (IBAction)startPlaying:(id)sender
    {
        NSLog(@"playRecording");
        
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
        
         NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@.caf", DOCUMENTS_FOLDER, audioFileName]];
        NSError *error;
        audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
        audioPlayer.numberOfLoops = 0;
        [audioPlayer play];
        NSLog(@"playing");
    }
    - (IBAction)stopPlaying:(id)sender
    {
        [audioPlayer stop];
        NSLog(@"stopped");
    }
    
    @end
    

    【讨论】:

      【解决方案7】:
      This is from Multimedia programming guide...
      
      - (IBAction) recordOrStop: (id) sender {
      if (recording) {
          [soundRecorder stop];
          recording = NO;
          self.soundRecorder = nil;
          [recordOrStopButton setTitle: @"Record" forState:
           UIControlStateNormal];
          [recordOrStopButton setTitle: @"Record" forState:
           UIControlStateHighlighted];
          [[AVAudioSession sharedInstance] setActive: NO error:nil];
      } 
      else {
          [[AVAudioSession sharedInstance]
           setCategory: AVAudioSessionCategoryRecord
           error: nil];
          NSDictionary *recordSettings =
          [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
           [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
           [NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
           [NSNumber numberWithInt: AVAudioQualityMax],
           AVEncoderAudioQualityKey,
           nil];
          AVAudioRecorder *newRecorder =
          [[AVAudioRecorder alloc] initWithURL: soundFileURL
                                      settings: recordSettings
                                         error: nil];
          [recordSettings release];
          self.soundRecorder = newRecorder;
          [newRecorder release];
          soundRecorder.delegate = self;
          [soundRecorder prepareToRecord];
          [soundRecorder record];
          [recordOrStopButton setTitle: @"Stop" forState: UIControlStateNormal];
          [recordOrStopButton setTitle: @"Stop" forState: UIControlStateHighlighted];
          recording = YES;
      }
      }
      

      【讨论】:

        【解决方案8】:

        在以下链接中,您可以找到有关使用 AVAudioRecording 进行录制的有用信息。在第一部分“使用音频”的此链接中,有一个名为“使用 AVAudioRecorder 类录制”的锚点。这将引导您进入示例。

        AudioVideo Conceptual MultimediaPG

        【讨论】:

          【解决方案9】:

          好的,所以我得到的答案帮助我朝着正确的方向前进,我非常感谢。它帮助我弄清楚了如何在 iPhone 上实际录制,但我想我还会包含一些从 iPhone 参考库中获得的有用代码:

          AudioandVideoTechnologies

          我使用了这段代码并很容易地将其添加到 avTouch 示例中。使用上面的代码示例和参考库中的示例,我能够让它工作得很好。

          【讨论】:

            【解决方案10】:

            音频设置下的wav格式

            NSDictionary *audioSetting = [NSDictionary dictionaryWithObjectsAndKeys:
                                          [NSNumber numberWithFloat:44100.0],AVSampleRateKey,
                                          [NSNumber numberWithInt:2],AVNumberOfChannelsKey,
                                          [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
                                          [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
                                          [NSNumber numberWithBool:NO], AVLinearPCMIsFloatKey, 
                                          [NSNumber numberWithBool:0], AVLinearPCMIsBigEndianKey,
                                          [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
                                          [NSData data], AVChannelLayoutKey, nil];
            

            参考: http://objective-audio.jp/2010/09/avassetreaderavassetwriter.html

            【讨论】:

            • 谢谢兄弟,这是你的 Swift 代码:let recordSettings:[String:AnyObject] = [ AVFormatIDKey:Int(kAudioFormatLinearPCM), AVLinearPCMIsFloatKey:false, AVLinearPCMIsBigEndianKey:0, AVLinearPCMIsNonInterleaved:false, AVSampleRateKey:44100.0, AVNumberOfChannelsKey:2, AVEncoderBitRateKey:12800, AVLinearPCMBitDepthKey:16, AVEncoderAudioQualityKey:AVAudioQuality.Max.rawValue]
            【解决方案11】:

            开始

            NSError *sessionError = nil;
            [[AVAudioSession sharedInstance] setDelegate:self];
            [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
            [[AVAudioSession sharedInstance] setActive: YES error: nil];
            UInt32 doChangeDefaultRoute = 1;
            AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof(doChangeDefaultRoute), &doChangeDefaultRoute);
            
            NSError *error = nil;
            NSString *filename = [NSString stringWithFormat:@"%@.caf",FILENAME];
            NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:filename];
            NSURL *soundFileURL = [NSURL fileURLWithPath:path];
            
            
            NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                            [NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
                                            [NSNumber numberWithInt:AVAudioQualityMedium],AVEncoderAudioQualityKey,
                                            [NSNumber numberWithInt:AVAudioQualityMedium], AVSampleRateConverterAudioQualityKey,
                                            [NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
                                            [NSNumber numberWithFloat:22050.0],AVSampleRateKey,
                                            nil];
            
            AVAudioRecorder *audioRecorder = [[AVAudioRecorder alloc]
                             initWithURL:soundFileURL
                             settings:recordSettings
                             error:&error];
            
            
            if (!error && [audioRecorder prepareToRecord])
            {
                [audioRecorder record];
            }
            

            停止

            [audioRecorder stop];
            [audioRecorder release];
            audioRecorder = nil;
            

            【讨论】:

            • 我找到的最佳音质设置
            【解决方案12】:
            -(void)viewDidLoad {
             // Setup audio session
                AVAudioSession *session = [AVAudioSession sharedInstance];
                [session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
            
                // Define the recorder setting
                NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
            
                [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
                [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
                [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
            
                // Initiate and prepare the recorder
                recorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:NULL];
                recorder.delegate = self;
                recorder.meteringEnabled = YES;
                [recorder prepareToRecord];
            
            }    
            
            - (IBAction)btnRecordDidClicked:(UIButton *)sender {
                    if (player1.playing) {
                        [player1 stop];
                    }
            
                    if (!recorder.recording) {
                        AVAudioSession *session = [AVAudioSession sharedInstance];
                        [session setActive:YES error:nil];
            
                        // Start recording
                        [recorder record];
                        [_recordTapped setTitle:@"Pause" forState:UIControlStateNormal];
            
                    } else {
            
                        // Pause recording
                        [recorder pause];
                        [_recordTapped setTitle:@"Record" forState:UIControlStateNormal];
                    }
            
                    [_stopTapped setEnabled:YES];
                    [_playTapped setEnabled:NO];
            
                }
            
                - (IBAction)btnPlayDidClicked:(UIButton *)sender {
                    if (!recorder.recording){
                        player1 = [[AVAudioPlayer alloc] initWithContentsOfURL:recorder.url error:nil];
                        [player1 setDelegate:self];
                        [player1 play];
                    }
                }
            
                - (IBAction)btnStopDidClicked:(UIButton *)sender {
                    [recorder stop];
                    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
                    [audioSession setActive:NO error:nil];
                }
            
                - (void) audioRecorderDidFinishRecording:(AVAudioRecorder *)avrecorder successfully:(BOOL)flag{
                    [_recordTapped setTitle:@"play" forState:UIControlStateNormal];
            
                    [_stopTapped setEnabled:NO];
                    [_playTapped setEnabled:YES];
            
                }
            

            【讨论】:

              【解决方案13】:

              根据上述答案,我做了一些更改,得到了正确的输出。

              第 1 步: 在“inf.plist”下添加麦克风使用权限 ==>

                <key>NSMicrophoneUsageDescription</key>
                <string>${PRODUCT_NAME} Microphone Usage</string>
              

              第 2 步:

              1. 将录音文件保存到本地文档目录

              2. 播放/停止录制

              3. 获取保存的音频文件的持续时间

              这里是源代码。请看一下并使用它。

              ViewController.h

              #import <UIKit/UIKit.h>
              #import <AVFoundation/AVFoundation.h>
              
              @interface ViewController : UIViewController{
              AVAudioPlayer *audioPlayer;
              AVAudioRecorder *audioRecorder;
              }
              
              -(IBAction) startRecording;
              -(IBAction) stopRecording;
              -(IBAction) playRecording;
              -(IBAction) stopPlaying;
              
              @end
              

              ViewController.m

              #import "ViewController.h"
              @interface ViewController () <AVAudioRecorderDelegate, AVAudioPlayerDelegate>
              
              @end
              
              @implementation ViewController
              
              - (void)viewDidLoad {
              [super viewDidLoad];
              // Do any additional setup after loading the view, typically from a nib.
              }
              
              -(IBAction) startRecording{
              // Setup audio session
              AVAudioSession *audioSession = [AVAudioSession sharedInstance];
              NSError *err = nil;
              [audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
              if(err)
              {
                  NSLog(@"audioSession: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]);
                  return;
              }
              [audioSession setActive:YES error:&err];
              err = nil;
              if(err)
              {
                  NSLog(@"audioSession: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]);
                  return;
              }
              AVAudioSessionRecordPermission permissionStatus = [audioSession recordPermission];
              switch (permissionStatus) {
                  case AVAudioSessionRecordPermissionUndetermined:{
                      [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
                          // CALL YOUR METHOD HERE - as this assumes being called only once from user interacting with permission alert!
                          if (granted) {
                              // Microphone enabled code
                              NSLog(@"Mic permission granted.  Call method for granted stuff.");
                              [self startRecordingAudioSound];
                          }
                          else {
                              // Microphone disabled code
                              NSLog(@"Mic permission indeterminate. Call method for indeterminate stuff.");
                              //        UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
                          }
                      }];
                      break;
                  }
                  case AVAudioSessionRecordPermissionDenied:
                      // direct to settings...
                      NSLog(@"Mic permission denied. Call method for denied stuff.");
              
                      break;
                  case AVAudioSessionRecordPermissionGranted:
                      // mic access ok...
                      NSLog(@"Mic permission granted.  Call method for granted stuff.");
                      [self startRecordingAudioSound];
                      break;
                  default:
                      // this should not happen.. maybe throw an exception.
                      break;
              }
              }
              
              #pragma mark - Audio Recording
              - (BOOL)startRecordingAudioSound{
              NSError *error = nil;
              NSMutableDictionary *recorderSettings = [[NSMutableDictionary alloc] init];
              [recorderSettings setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
              [recorderSettings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
              [recorderSettings setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
              [recorderSettings setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
              [recorderSettings setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
              [recorderSettings setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
              
              // Create a new audio file
              NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
              NSString *documentPath_ = [searchPaths objectAtIndex: 0];
              NSString *pathToSave = [documentPath_ stringByAppendingPathComponent:[self dateString]];
              NSLog(@"the path is %@",pathToSave);
              
              // File URL
              NSURL *url = [NSURL fileURLWithPath:pathToSave];//FILEPATH];
              
              //Save recording path to preferences
              NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
              [prefs setURL:url forKey:@"Test1"];
              [prefs synchronize];
              
              audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:recorderSettings error:&error];
              if (!audioRecorder)
              {
                  NSLog(@"Error establishing recorder: %@", error.localizedFailureReason);
                  return NO;
              }
              
              // Initialize degate, metering, etc.
              audioRecorder.delegate = self;
              audioRecorder.meteringEnabled = YES;
              //self.title = @"0:00";
              
              if (![audioRecorder prepareToRecord])
              {
                  NSLog(@"Error: Prepare to record failed");
                  //[self say:@"Error while preparing recording"];
                  return NO;
              }
              
              if (![audioRecorder record])
              {
                  NSLog(@"Error: Record failed");
                  //  [self say:@"Error while attempting to record audio"];
                  return NO;
              }
              NSLog(@"Recroding Started");
              return YES;
              }
              
              #pragma mark - AVAudioRecorderDelegate
              - (void) audioRecorderDidFinishRecording:(AVAudioRecorder *)avrecorder successfully:(BOOL)flag{
              NSLog (@"audioRecorderDidFinishRecording:successfully:");
              }
              
              #pragma mark - AVAudioPlayerDelegate
              - (void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
              NSLog (@"audioPlayerDidFinishPlaying:successfully:");
              }
              
              - (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"];
              }
              
              -(IBAction) stopRecording{
              NSLog(@"stopRecording");
              [audioRecorder stop];
              NSLog(@"stopped");
              }
              
              -(IBAction) playRecording{
              //Load recording path from preferences
              NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
              NSURL *temporaryRecFile = [prefs URLForKey:@"Test1"];
              
              //Get Duration of Audio File
              AVURLAsset* audioAsset = [AVURLAsset URLAssetWithURL:temporaryRecFile options:nil];
              CMTime audioDuration = audioAsset.duration;
              float audioDurationSeconds = CMTimeGetSeconds(audioDuration);
              NSLog(@"Duration Of Audio: %f", audioDurationSeconds);
              
              audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:temporaryRecFile error:nil];
              audioPlayer.delegate = self;
              [audioPlayer setNumberOfLoops:0];
              audioPlayer.volume = 1;
              [audioPlayer prepareToPlay];
              [audioPlayer play];
              NSLog(@"playing");
              }
              
              -(IBAction) stopPlaying{
              NSLog(@"stopPlaying");
              [audioPlayer stop];
              NSLog(@"stopped");
               }
              
               @end
              

              【讨论】:

              • 不要使用-[NSUserDefaults synchronize]。来自Apple's documentation“这个方法是不必要的,不应该使用。”
              • 谢谢你!这个答案需要更高,因为最近的 iOS 版本需要 info.plist 文件中的隐私信息。此外,仅供任何其他偶然发现此问题的 iOS 新手参考:您可以打开“Info.plist”,然后右键单击文件底部附近的背景,点击“添加行”,然后粘贴“NSMicrophoneUsageDescription”跨度>
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-09-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多