iOS录音、播放、WAV以及caf转成MP3上传后台

录音

#import <AVFoundation/AVFoundation.h>
#import "lame.h" // 转成MP3需要该文件

@interface RecorderTestController ()<AVAudioRecorderDelegate,AVAudioPlayerDelegate>
{
    
    
  AVAudioPlayer * player;// 音频播放
}
@property (nonatomic,strong) AVAudioRecorder * audioRecorder; // 录音工具

开始录音,下面这部分代码可以直接复制使用

-(void)startRecordcase{
    
    
    //删除上次生成的文件,保留最新文件
   NSFileManager *fileManager = [NSFileManager defaultManager];
   //默认就是wav格式,是无损的
    if ([fileManager fileExistsAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"testRecorder.WAV"]]) {
    
    
        [fileManager removeItemAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"testRecorder.WAV"] error:nil];
    
    }
    //录音设置
    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
   //设置录音格式 AVFormatIDKey==kAudioFormatLinearPCM
    [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
   //设置录音采样率(Hz) 如:AVSampleRateKey==8000/44100/96000(影响音频的质量), 采样率必须要设为11025才能使转化成mp3格式后不会失真
     [recordSetting setValue:[NSNumber numberWithFloat:8000] forKey:AVSampleRateKey];
     //录音通道数 1 或 2 ,要转换成mp3格式必须为双通道
     [recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
    //线性采样位数 8、16、24、32
    [recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    //录音的质量
    [recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityMax] forKey:AVEncoderAudioQualityKey];
    [recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsNonInterleaved]; //交叉的
    // 设置录制音频采用高位优先的记录格式
    [recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
    // 设置采样信号采用浮点数
    [recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
    //存储录音文件
    NSURL * recordUrl = [NSURL URLWithString:[NSTemporaryDirectory()stringByAppendingPathComponent:@"testRecorder.WAV"]];
    //初始化录音对象
    NSError * error;
    self.audioRecorder = [[AVAudioRecorder alloc] initWithURL:recordUrl settings:recordSetting error:&error];

    if (error) {
    
    
        NSLog(@"%@",error.description);
        return;
    }
    self.audioRecorder.delegate = self;
    //开启音量检测
    self.audioRecorder.meteringEnabled = YES;
    AVAudioSession * audioSession = [AVAudioSession sharedInstance];//得到音频会话单例对象
    //如果不是正在录音
    if (![self.audioRecorder isRecording]) {
    
    
        [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];//设置类别,表示该应用同时支持播放和录音
        [audioSession setActive:YES error:nil];//激活当前应用的音频会话,此时会阻断后台音乐的播放.
        [self.audioRecorder prepareToRecord];//准备录音
        [self.audioRecorder record];//开始录音
    }
}
//结束录音
- (void)endRecord
{
    
    
    [self.audioRecorder stop];  //录音停止
}
//录音结束后代理
-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{
    
    
    [[AVAudioSession sharedInstance] setActive:NO error:nil];//一定要在录音停止以后再关闭音频会话管理(否则会报错),此时会延续后台音乐播放
    if (!flag) return;
}

播放

- (void)playWav{
    
    
//获取录音数据
NSData * wavData = [NSData dataWithContentsOfFile:[NSTemporaryDirectory() stringByAppendingPathComponent:@"testRecorder.WAV"]];
NSError * error;

player = [[AVAudioPlayer alloc]initWithData:wavData error:&error];
    player.delegate = self;
    if (error) {
    
    
    NSLog(@"语音播放失败,%@",error);
    return;

}

//播放器的声音会自动切到receiver,所以听起来特别小,如果需要从speaker出声,需要自己设置。
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
// 单独设置音乐的音量(默认1.0,可设置范围为0.0至1.0,两个极端为静音、系统音量):
player.volume = 1.0;
//    修改左右声道的平衡(默认0.0,可设置范围为-1.0至1.0,两个极端分别为只有左声道、只有右声道):
player.pan = -1;
//    设置播放速度(默认1.0,可设置范围为0.5至2.0,两个极端分别为一半速度、两倍速度):
player.rate = 2.0;
//    设置循环播放(默认1,若设置值大于0,则为相应的循环次数,设置为-1可以实现无限循环):
player.numberOfLoops = 0;
//调用prepareToPlay方法,这样可以提前获取需要的硬件支持,并加载音频到缓冲区。在调用play方法时,减少开始播放的延迟。
[player prepareToPlay];
//    开始播放音乐:
[player play];
}

//播放完成代理
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    
    
    if (flag) {
    
    
		//调用pause或stop来暂停播放,这里的stop方法的效果也只是暂停播放,不同之处是stop会撤销prepareToPlay方法所做的准备。
		[player stop];
		player = nil;
    }
}

转成MP3

-(void)convertToMp3SouceFilePathName:(NSString *)sourcePath isDeleteSourchFile:(BOOL)isDelete
{
    
    
    // 输入路径
    NSString *inPath = sourcePath;
    // 判断输入路径是否存在
    NSFileManager *fm = [NSFileManager defaultManager];
    if (![fm fileExistsAtPath:sourcePath]) {
    
    
        NSLog(@"文件不存在");
    }
    // 输出路径
    NSString *outPath = [[sourcePath stringByDeletingPathExtension] stringByAppendingString:@".MP3"];
    @try {
    
    
        int read, write;
        
        FILE *pcm = fopen([inPath cStringUsingEncoding:1], "rb");  //source 被转换的音频文件位置
        fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header
        FILE *mp3 = fopen([outPath cStringUsingEncoding:1], "wb");  //output 输出生成的Mp3文件位置
        
        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE*2];
        unsigned char mp3_buffer[MP3_SIZE];
        
        lame_t lame = lame_init();
        lame_set_in_samplerate(lame, 8000);// 采样率
        lame_set_num_channels(lame, 2);//通道
        lame_set_quality(lame, 0);//质量 质量范围0~9。0最好。9最差
        lame_set_VBR(lame, vbr_default);
        lame_set_brate(lame, 8); //设置压缩比例 默认压缩比例是11
        lame_init_params(lame);
        do {
    
    
            size_t size = (size_t)(2 * sizeof(short int));
            read = (int)fread(pcm_buffer, size, PCM_SIZE, pcm);
            if (read == 0)
                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            else
                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
            
            fwrite(mp3_buffer, write, 1, mp3);
            
        } while (read != 0);
        
        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
    }
    @catch (NSException *exception) {
    
    
        NSLog(@"%@",[exception description]);
    }
    @finally {
    
    
        NSLog(@"MP3生成成功:");
        if (isDelete) {
    
    
            
            NSError *error;
            [fm removeItemAtPath:sourcePath error:&error];
            if (error == nil) {
    
    
                NSLog(@"删除源文件成功");
            }
        }
        return outPath;
    }
}

base64转码

-(NSString *)recordmp3ToBASE64; // mp3格式 base64转码
{
    
    
    NSString *strdatamp3 = [self convertToMp3SouceFilePathName:[NSTemporaryDirectory() stringByAppendingPathComponent:@"testRecorder.WAV"] isDeleteSourchFile:YES]; // 调用转码方法 转成MP3
    NSData *mp3Data = [[NSData dataWithContentsOfFile:strdatamp3] base64EncodedDataWithOptions:0];
    
    NSString * encodedRecordStr = [[NSString alloc]initWithData:mp3Data encoding:NSUTF8StringEncoding];
    
    return encodedRecordStr;
}

caf转码MP3

以上就是整个录音的过程,其中录音文件的名称以及后缀是可以更改的,后缀可以更改为caf格式。

testRecorder.WAV可以更改为testRecorder.caf。更改之后就是caf转MP3,可以根据项目要求进行格式更换。

调用

完成以上工作之后,就可以在使用的地方直接调用了。必须完成以上代码!!!
比如开始录音:

[self startRecordcase];

结束录音:

[self endRecord];

播放录音:

[self playWav];

通过接口上传录音:

[self recordmp3ToBASE64];

分享心得:

以上就是我在项目上使用的方法。其实在第一次写转码的时候出现了转码之后的文件全部是杂音的问题。找了很长时间才找到原因。
第一:

[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsNonInterleaved]; //交叉的录制
// 设置录制音频采用高位优先的记录格式
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
// 设置采样信号采用浮点数
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];

以上三种参数必须设置为No,转码之后的MP3文件就都是杂音。

第二:转成MP3需要lame文件。所以必须下载lame文件。这个在网上是都可以搜到。下载下来的lame文件包含了两个,如下图所示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/c1o2c3o4/article/details/117660341