iOS录音方法实用详解
程序员文章站
2022-06-02 23:53:17
本文将涉及到以下内容:
一、搭建长按录音ui效果;
二、使用avaudiorecorder录音;
三、使用avaudioplayer播放,并添加播放动画;
四、使用lame将caf音频转化为mp3;...
本文将涉及到以下内容:
一、搭建长按录音ui效果;
二、使用avaudiorecorder录音;
三、使用avaudioplayer播放,并添加播放动画;
四、使用lame将caf音频转化为mp3;
五、将mp3 转化为 base64编码;
六、查看录音文件大小;
七、删除语音文件;
--------------------------
一、搭建长按录音ui效果;
页面样式效果如下:
其中:
1、录音按钮是由两个uiimageview实现,监听手势方法,长按第一层uiimageview时,第二层开始旋转动画;
这里我想过用uibutton来实现点击录音效果,其中uicontroleventtouchdown可以检测点击下去的效果,uicontroleventtouchupinside可以检测点击后起来的效果,但是测试点击下去后,没有直接起来,而是将手指移动到其他位置,导致录音无法关闭,所以,还是使用了长按手势来监听。
2、其他控件比较简单。
核心代码
1、长按启动录音;
- (uiimageview *)recordbtn { if (!_recordbtn) { _recordbtn = [[uiimageview alloc]init]; _recordbtn.backgroundcolor = [uicolor clearcolor]; [_recordbtn setimage:[uiimage imagenamed:@"record_norm"]]; _recordbtn.userinteractionenabled = yes;//方便添加长按手势 } return _recordbtn; }
self.recordbtn.frame = cgrectmake((kscreen_width - btnh)*0.5, cgrectgetmaxy(self.timelabel.frame) + margin, btnh, btnh); self.recordbtn.layer.cornerradius = self.recordbtn.frame.size.width * 0.5; [self.recordbtn.layer setmaskstobounds:yes]; // [self.recordbtn addtarget:self action:@selector(recordnotice) forcontrolevents:uicontroleventtouchdown]; // [self.recordbtn addtarget:self action:@selector(stopnotice) forcontrolevents:uicontroleventtouchupinside]; //实例化长按手势监听 uilongpressgesturerecognizer *longpress = [[uilongpressgesturerecognizer alloc] initwithtarget:self action:@selector(handletableviewcelllongpressed:)]; //代理 longpress.delegate = self; longpress.minimumpressduration = 0.5; [self.recordbtn addgesturerecognizer:longpress];
//长按事件的实现方法 - (void) handletableviewcelllongpressed:(uilongpressgesturerecognizer *)gesturerecognizer { if (gesturerecognizer.state == uigesturerecognizerstatebegan) { nslog(@"uigesturerecognizerstatebegan"); [self startrecordnotice]; } if (gesturerecognizer.state == uigesturerecognizerstatechanged) { } if (gesturerecognizer.state == uigesturerecognizerstateended) { nslog(@"uigesturerecognizerstateended"); [self stoprecordnotice]; } }
2、录音过程中,录音外圈旋转效果
1)初始化
-(uiimageview *)rotateimgview { if (!_rotateimgview) { _rotateimgview = [[uiimageview alloc]init]; _rotateimgview.image = [uiimage imagenamed:@"rcirle_norm"]; _rotateimgview.frame = cgrectmake(0, 0, btnh, btnh); _rotateimgview.center = self.recordbtn.center; } return _rotateimgview; }
2)动画设置
// 执行动画 - (void)staranimalwithtime:(cftimeinterval)time //time为旋转一周的时间 { self.rotateimgview.image = [uiimage imagenamed:@"rcirle_high"]; self.rotationanimation = [cabasicanimation animationwithkeypath:@"transform.rotation.z"]; self.rotationanimation.tovalue = [nsnumber numberwithfloat: m_pi * 2.0 ]; self.rotationanimation.duration = time; self.rotationanimation.cumulative = yes; self.rotationanimation.repeatcount = huge_valf; [self.rotateimgview.layer addanimation:self.rotationanimation forkey:@"rotationanimation"]; }
3、播放时的动画效果
1)动画设置
#pragma mark - 动画效果 - (void)picturechangeanimationsetting { nsarray *picarray = @[[uiimage imagenamed:@"voice1"], [uiimage imagenamed:@"voice2"], [uiimage imagenamed:@"voice3"],]; // self.imageview.image = [uiimage imagenamed:@"voice1"]; //imageview的动画图片是数组images self.voiceview.animationimages = picarray; //按照原始比例缩放图片,保持纵横比 self.voiceview.contentmode = uiviewcontentmodescaleaspectfit; //切换动作的时间3秒,来控制图像显示的速度有多快, self.voiceview.animationduration = 1; //动画的重复次数,想让它无限循环就赋成0 self.voiceview.animationrepeatcount = 0; }
2)开启动画
[self.voiceview startanimating];
3)关闭动画
[self.voiceview.layer removeallanimations]; self.voiceview.image = [uiimage imagenamed:@"voice3"];
二、使用avaudiorecorder录音;
#pragma mark - getter /** * 获得录音机对象 * * @return 录音机对象 */ -(avaudiorecorder *)audiorecorder{ if (!_audiorecorder) { //创建录音文件保存路径 nsurl *url=[nsurl urlwithstring:self.cafpathstr]; //创建录音格式设置 nsdictionary *setting=[self getaudiosetting]; //创建录音机 nserror *error=nil; _audiorecorder=[[avaudiorecorder alloc]initwithurl:url settings:setting error:&error]; _audiorecorder.delegate=self; _audiorecorder.meteringenabled=yes;//如果要监控声波则必须设置为yes if (error) { nslog(@"创建录音机对象时发生错误,错误信息:%@",error.localizeddescription); return nil; } } return _audiorecorder; }
/** * 取得录音文件设置 * * @return 录音设置 */ -(nsdictionary *)getaudiosetting{ //linearpcm 是ios的一种无损编码格式,但是体积较为庞大 //录音设置 nsmutabledictionary *recordsettings = [[nsmutabledictionary alloc] init]; //录音格式 无法使用 [recordsettings setvalue :[nsnumber numberwithint:kaudioformatlinearpcm] forkey: avformatidkey]; //采样率 [recordsettings setvalue :[nsnumber numberwithfloat:11025.0] forkey: avsampleratekey];//44100.0 //通道数 [recordsettings setvalue :[nsnumber numberwithint:2] forkey: avnumberofchannelskey]; //线性采样位数 //[recordsettings setvalue :[nsnumber numberwithint:16] forkey: avlinearpcmbitdepthkey]; //音频质量,采样质量 [recordsettings setvalue:[nsnumber numberwithint:avaudioqualitymin] forkey:avencoderaudioqualitykey]; return recordsettings; }
- (void)startrecordnotice{ if ([self.audiorecorder isrecording]) { [self.audiorecorder stop]; } [self deleteoldrecordfile]; //如果不删掉,会在原文件基础上录制;虽然不会播放原来的声音,但是音频长度会是录制的最大长度。 avaudiosession *audiosession=[avaudiosession sharedinstance]; [audiosession setcategory:avaudiosessioncategoryplayandrecord error:nil]; if (![self.audiorecorder isrecording]) {//0--停止、暂停,1-录制中 [self.audiorecorder record];//首次使用应用时如果调用record方法会询问用户是否允许使用麦克风 self.countnum = 0; nstimeinterval timeinterval =1 ; //0.1s self.timer1 = [nstimer scheduledtimerwithtimeinterval:timeinterval target:self selector:@selector(changerecordtime) userinfo:nil repeats:yes]; [self.timer1 fire]; } [self staranimalwithtime:2.0]; }
- (void)stoprecordnotice { nslog(@"----------结束录音----------"); [self.audiorecorder stop]; [self.timer1 invalidate]; }
三、使用avaudioplayer播放;
这段代码写的不好,暂不分享,欢迎大家分享给我
四、使用lame将caf音频转化为mp3;
导入lame框架,import进来头文件即可使用,如果导出后是噪音,需要检查录音的设置
#pragma mark - caf转mp3 - (void)audio_pcmtomp3 { @try { int read, write; file *pcm = fopen([self.cafpathstr cstringusingencoding:1], "rb"); //source 被转换的音频文件位置 fseek(pcm, 4*1024, seek_cur); //skip file header file *mp3 = fopen([self.mp3pathstr 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, 11025.0); lame_set_vbr(lame, vbr_default); 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 { nslog(@"mp3生成成功: %@",self.mp3pathstr); } }
五、将mp3 转化为 base64编码;
#pragma mark - 文件转换 // 二进制文件转为base64的字符串 - (nsstring *)base64strwithmp3data:(nsdata *)data{ if (!data) { nslog(@"mp3data 不能为空"); return nil; } // nsstring *str = [data base64encodedstringwithoptions:nsdatabase64encoding64characterlinelength]; nsstring *str = [data base64encodedstringwithoptions:nsdatabase64encodingendlinewithlinefeed]; return str; } // base64的字符串转化为二进制文件 - (nsdata *)mp3datawithbase64str:(nsstring *)str{ if (str.length ==0) { nslog(@"mp3datawithbase64str:base64str 不能为空"); return nil; } nsdata *data = [[nsdata alloc] initwithbase64encodedstring:str options:nsdatabase64decodingignoreunknowncharacters]; nslog(@"mp3datawithbase64str:转换成功"); return data; }
六、查看录音文件大小;
//单个文件的大小,返回单位为k - (long long) filesizeatpath:(nsstring*)filepath{ nsfilemanager* manager = [nsfilemanager defaultmanager]; if ([manager fileexistsatpath:filepath]){ return [[manager attributesofitematpath:filepath error:nil] filesize]; } return 0; }
调用
//计算文件大小 long long filesize = [self filesizeatpath:self.mp3pathstr]/1024.0; nsstring *filesizestr = [nsstring stringwithformat:@"%lld",filesize];
七、删除(语音)文件;
-(void)deleteoldrecordfileatpath:(nsstring *)pathstr{ nsfilemanager* filemanager=[nsfilemanager defaultmanager]; bool blhave=[[nsfilemanager defaultmanager] fileexistsatpath:pathstr]; if (!blhave) { nslog(@"不存在"); return ; }else { nslog(@"存在"); bool bldele= [filemanager removeitematpath:self.cafpathstr error:nil]; if (bldele) { nslog(@"删除成功"); }else { nslog(@"删除失败"); } } }
上一篇: 堂嫂教训她家小女儿
下一篇: JavaNio之Buffer