iOS--录音相关功能的实现

1. 导入录音功能依赖的框架


.framework框架

2. 在相应界面引入头文件


头文件

然后遵守协议AVAudioRecorderDelegate,AVAudioPlayerDelegate

3. 定义一些需要用得到属性

//录音存储路径

@property (nonatomic, strong)NSURL *tmpFile;

//录音

@property (nonatomic, strong)AVAudioRecorder *recorder;

//播放

@property (nonatomic, strong)AVAudioPlayer *player;

//录音状态(是否录音)

@property (nonatomic, assign)BOOL isRecoding;

4. 录音功能的实现

(1)首先判断后台是否正在播放音乐,如果正在播放则停止播放

session = [AVAudioSession sharedInstance];

NSError *sessionError;

[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];

//判断后台有没有播放

if (session == nil) {

NSLog(@"Error creating sessing:%@", [sessionError description]);

} else {

[session setActive:YES error:nil];

}

(2)实现录音功能

//判断当录音状态为不录音的时候

if (!self.isRecoding)

//设置录音音质

NSMutableDictionary * recordSetting = [NSMutableDictionary dictionary];

[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];//

[recordSetting setValue:[NSNumber numberWithFloat:8000.0] forKey:AVSampleRateKey];//采样率

[recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];//声音通道,这里必须为双通道

[recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityLow] forKey:AVEncoderAudioQualityKey];//音频质量

//创建临时文件来存放录音文件

NSDate *  senddate=[NSDate date];

NSDateFormatter  *dateformatter=[[NSDateFormatter alloc] init];

[dateformatter setDateFormat:@"yyyyMMddhhmmss"];

String=[dateformatter stringFromDate:senddate];

NSDateFormatter  *dateformatter1=[[NSDateFormatter alloc] init];

[dateformatter1 setDateFormat:@"YYYY-MM-dd hh:mm:ss"];

string11=[dateformatter1 stringFromDate:senddate];

//创建临时文件来保存录音文件 (为了播放)

//        //保存录音文件到沙盒

self.tmpFile=[NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.caf",String]]];

yuanpath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.caf",String]];

这里创建了一个沙盒路径,并用当前录音时间命名(防止重复)

创建一个计时器来为录音计时,同时时间置0

sec=0;

timer=[NSTimer scheduledTimerWithTimeInterval:1

target:self selector:@selector(timer) userInfo:nil repeats:YES];

接下来设置录音,按钮的状态,以及对获取到的录音进行相关操作

//录音状态变为录音

self.isRecoding = YES;

//将录音按钮变为停止

[recordButton setImage:[UIImage imageNamed:@"recording_button.png"] forState:UIControlStateNormal];

recordla.text=NSLocalizedString(@"tingzhi",@"");

//播放按钮不能被点击

[playButton setEnabled:NO];

playButton.titleLabel.alpha = 0.5;

//开始录音,将所获取到得录音存到文件里,录音放进相应url里

self.recorder = [[AVAudioRecorder alloc] initWithURL:_tmpFile settings:recordSetting error:nil];

//准备记录录音

[_recorder prepareToRecord];

//启动或者恢复记录的录音文件

[_recorder record];

_player = nil;

5. 录音完成

(1)对录音的状态,按钮的设置,录音时间等进行设置

//录音状态 点击录音按钮 停止录音

self.isRecoding = NO;

[recordButton setImage:[UIImage imageNamed:@"record_button.png"] forState:UIControlStateNormal];

recordla.text=NSLocalizedString(@"luyin",@"");

//录音停止的时候,播放按钮可以点击

[playButton setEnabled:YES];

[setButton setEnabled:YES];

[playButton.titleLabel setAlpha:1];

//停止录音

[_recorder stop];

[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%d",sec] forKey:@"time"];

[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%d",min] forKey:@"min"];

NSString * timestr=[NSString stringWithFormat:@"%@:%02d:%02d",NSLocalizedString(@"luyinshichang",@""),min,sec];

[[NSUserDefaults standardUserDefaults] setObject:timestr forKey:@"soundtime"];

//计时器停止

[timer invalidate];

_recorder = nil;

(2)大多数情况下需要对录音文件的格式进行转换,这里是将录音文件转换成mp3格式,用到第三方libmp3lame


//设置mp3文件的存储路径  nsstring格式的

mp3FilePath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp3",String]];

@try {

int read, write;

FILE *pcm = fopen ([yuanpath cStringUsingEncoding:1],"rb");  //source 被 转换的音频文件位置

if (pcm == NULL )

{

NSLog ( @"mp3格式转换失败 所给路径没有音频文件" );

}

else{

//source 被转换的音频文件位置

fseek(pcm, 4*1024, SEEK_CUR);                                  //skip file header

FILE *mp3 = fopen([mp3FilePath 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];

//mp3格式语音的压缩参数

lame_t lame = lame_init ();

lame_set_num_channels (lame, 2); // 设置 1 为单通道,默认为 2 双通道

lame_set_in_samplerate (lame, 8000.0 ); //11025.0

//lame_set_VBR(lame, vbr_default);

lame_set_brate (lame, 8);

lame_set_mode (lame, 3);

lame_set_mode(lame, 6);

lame_set_brate(lame, 25);

lame_set_quality(lame, 5);

lame_set_quality (lame, 2 ); /* 2=high 5 = medium 7=low 音 质 */

lame_init_params (lame);

do {

read = fread(pcm_buffer, 2*sizeof(short int), 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 {

//        yuanpath = mp3FilePath;

//        NSLog(@"MP3生成成功: %@",yuanpath);

}

});

(3)检测录音是否录制成功

//根据路径播放录音

//        self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:_tmpFile error:&playError];

self.tmpFile=[NSURL URLWithString:mp3FilePath];

self.player = [[AVAudioPlayer alloc] initWithContentsOfURL: self.tmpFile error:&playError];

//当播放录音为空, 打印错误信息

if (self.player == nil) {

UIAlertView *alertView=[[ UIAlertView alloc ] initWithTitle :NSLocalizedString(@"luyinshibai",@"") message :nil delegate : nil cancelButtonTitle : NSLocalizedString(@"queren",@"") otherButtonTitles : nil ];

[alertView show ];

}

self.player.delegate = self;

6. 播放以及播放暂停,播放完成

(1)播放按钮的实现

//判断是否正在播放,如果正在播放

if ([self.player isPlaying]) {

//正在播放 录音按钮不能被点击

[recordButton setEnabled:YES];

//暂停播放

[_player pause];

[timer invalidate];

//按钮显示为播放

[playButton setImage:[UIImage imageNamed:@"play_button.png"] forState:UIControlStateNormal];

playla.text=NSLocalizedString(@"bofang",@"");

} else {

//开始播放

[recordButton setEnabled:NO];

[_player play];

sec=[[[NSUserDefaults standardUserDefaults] valueForKey:@"time"]intValue];

min=[[[NSUserDefaults standardUserDefaults] valueForKey:@"min"]intValue];

if (!(sec==0)) {

timer=[NSTimer scheduledTimerWithTimeInterval:1

target:self selector:@selector(timer1) userInfo:nil repeats:YES];

}

else{

sec=0;

}

[playButton setImage:[UIImage imageNamed:@"suspend_button.png"] forState:UIControlStateNormal];

playla.text=NSLocalizedString(@"tingzhi",@"");

}

这里又定义了一个计时器,来为播放录音计时

(2)下面两个计时器的实现方法

//录音计时

-(void)timer

{

sec++;

if (sec==60) {

min=min+1;

}

if (min==1) {

[self chaoTimeStop];

}

sec=sec%60;

time.text=[NSString stringWithFormat:@"%02d:%02d",min,sec];

}

/播放计时

-(void)timer1

{

if (sec==0 && min==0) {

sec=0;

}

else{

if (min==0) {

sec--;

sec=sec%60;

time.text=[NSString stringWithFormat:@"%02d:%02d",min,sec];

}

if (min>0) {

sec--;

min--;

sec=sec%60;

time.text=[NSString stringWithFormat:@"%02d:%02d",min,sec];

if (sec==0 && min>0) {

min=min-1;

sec=60;

}

}

}

}

(3)当播放结束时自动调用的方法

//当播放结束后调用这个方法

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag

{

//按钮标题变为播放

[playButton setImage:[UIImage imageNamed:@"play_button.png"] forState:UIControlStateNormal];

playla.text=NSLocalizedString(@"bofang",@"");

[timer invalidate];

int j=[[[NSUserDefaults standardUserDefaults] valueForKey:@"time"] intValue];

int i=[[[NSUserDefaults standardUserDefaults] valueForKey:@"min"] intValue];

if (j>0 && j<10) {

time.text=[NSString stringWithFormat:@"0%d:0%d",i,j];

}

if (j>=10) {

time.text=[NSString stringWithFormat:@"0%d:%d",i,j];

}

[recordButton setEnabled:YES];

}

7. 录音发送到服务器(请关注我的上一篇简书,与图片的发送一致,用力戳

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容