iOS录音播放Demo下载地址:http://download.csdn.net/detail/lovechris00/9587214
本文将涉及到以下内容:
一、搭建长按录音UI效果;
二、使用AVAudioRecorder录音;
三、使用AVAudioPlayer播放,并添加播放动画;
四、使用lame将caf音频转化为mp3;
五、将mp3 转化为 base64编码;
六、查看录音文件大小;
七、删除语音文件;
--------------------------
一、搭建长按录音UI效果;
页面样式效果如下:
其中:
1、录音按钮是由两个UIImageView实现,监听手势方法,长按第一层UIImageView时,第二层开始旋转动画;
这里我想过用UIButton来实现点击录音效果,其中UIControlEventTouchDown可以检测点击下去的效果,UIControlEventTouchUpInside可以检测点击后起来的效果,但是测试点击下去后,没有直接起来,而是将手指移动到其他位置,导致录音无法关闭,所以,还是使用了长按手势来监听。
2、其他控件比较简单。
核心代码
1、长按启动录音;
- <span style="font-size:18px;">- (UIImageView *)recordBtn
- {
- if (!_recordBtn) {
- _recordBtn = [[UIImageView alloc]init];
- _recordBtn.backgroundColor = [UIColor clearColor];
- [_recordBtn setImage:[UIImage imageNamed:@"record_norm"]];
- _recordBtn.userInteractionEnabled = YES;//方便添加长按手势
- }
- return _recordBtn;
- }</span>
- <span style="font-size:18px;">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];
- </span>
- <span style="font-size:18px;">//长按事件的实现方法
- - (void) handleTableviewCellLongPressed:(UILongPressGestureRecognizer *)gestureRecognizer {
- if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
- NSLog(@"UIGestureRecognizerStateBegan");
- [self startRecordNotice];
- }
- if (gestureRecognizer.state == UIGestureRecognizerStateChanged) {
- }
- if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
- NSLog(@"UIGestureRecognizerStateEnded");
- [self stopRecordNotice];
- }
- }
- </span>
2、录音过程中,录音外圈旋转效果
1)初始化
- <span style="font-size:18px;">-(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;
- }
- </span>
2)动画设置
- <span style="font-size:18px;">// 执行动画
- - (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"];
- }
- </span>
3、播放时的动画效果
1)动画设置
- <span style="font-size:18px;"><span style="font-size:18px;">#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;
- }</span></span>
2)开启动画
- <span style="font-size:18px;">[self.voiceView startAnimating];</span>
3)关闭动画
- <span style="font-size:18px;"> [self.voiceView.layer removeAllAnimations];
- self.voiceView.image = [UIImage imageNamed:@"voice3"];</span>
二、使用AVAudioRecorder录音;
- <span style="font-size:18px;">#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;
- }
- </span>
- <span style="font-size:18px;">/**
- * 取得录音文件设置
- *
- * @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;
- }
- </span>
- <span style="font-size:18px;">- (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];
- }
- </span>
- <span style="font-size:18px;">- (void)stopRecordNotice
- {
- NSLog(@"----------结束录音----------");
- [self.audioRecorder stop];
- [self.timer1 invalidate];
- }</span>
三、使用AVAudioPlayer播放;
这段代码写的不好,暂不分享,欢迎大家分享给我
四、使用lame将caf音频转化为mp3;
导入lame框架,import进来头文件即可使用,如果导出后是噪音,需要检查录音的设置
- <span style="font-size:18px;">#pragma mark - caf转mp3
- - (void)audio_PCMtoMP3
- {
- @try {
- int read, write;
- FILEFILE *pcm = fopen([self.cafPathStr cStringUsingEncoding:1], "rb"); //source 被转换的音频文件位置
- fseek(pcm, 4*1024, SEEK_CUR); //skip file header
- FILEFILE *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);
- }
- }
- </span>
五、将mp3 转化为 base64编码;
- <span style="font-size:18px;">#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;
- }</span>
六、查看录音文件大小;
- <span style="font-size:18px;">//单个文件的大小,返回单位为K
- - (long long) fileSizeAtPath:(NSString*)filePath{
- NSFileManager* manager = [NSFileManager defaultManager];
- if ([manager fileExistsAtPath:filePath]){
- return [[manager attributesOfItemAtPath:filePath error:nil] fileSize];
- }
- return 0;
- }</span>
调用
- <span style="font-size:18px;">
- //计算文件大小
- long long fileSize = [self fileSizeAtPath:self.mp3PathStr]/1024.0;
- NSString *fileSizeStr = [NSString stringWithFormat:@"%lld",fileSize];</span>
七、删除(语音)文件;
- <span style="font-size:18px;">-(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(@"删除失败");
- }
- }
- }</span>