您的位置:首页 > 移动开发 > IOS开发

iOS 实现录音并保存在指定文件目录下面

2016-01-07 16:31 423 查看
原理:

进入界面,先遍历文件目录,将所有的文件名,显示在uitableview中。在录音时需要设置session以及录音采样率。

1.ios录音主要使用ios自带的类,是工程中需要手动添加这俩个framework

#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>


2.在录音前,先监测文件存放目录是否存在,不存在就创建目录

NSDate *  date=[NSDate date];
NSDateFormatter  *dateformatter=[[NSDateFormatter alloc] init];
[dateformatter setDateFormat:@"YYYY-MM-dd"];
NSString *datefloder= [dateformatter stringFromDate:date];
dateaudioPath=[NSString stringWithFormat:@"%@/",datefloder];
fileMgr = [NSFileManager defaultManager];
//指向文件目录
NSString *documentsDirectory= [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
audioRecoderSavePath=[NSString stringWithFormat:@"%@/%@%@", documentsDirectory,audioPath,dateaudioPath];

if (![fileMgr fileExistsAtPath:audioRecoderSavePath]) {
[fileMgr createDirectoryAtPath:audioRecoderSavePath withIntermediateDirectories:YES attributes:nil error:nil];
}


3.点击录音,开始录音

if(!isRecording)
{
isRecording = YES;
stateLabel.text=@"录音中";
[startRecoderBtn setTitle:@"停止录音" forState:(UIControlStateNormal)];
// startRecoderBtn.titleLabel.text=@"停止录音";
NSDate *  date=[NSDate date];
NSDateFormatter  *dateformatter=[[NSDateFormatter alloc] init];
[dateformatter setDateFormat:@"YYYYMMddHHYYSS"];
recoderName= [NSString stringWithFormat:@"%@%@",[dateformatter stringFromDate:date],@".caf"];
//tempRecoderPath=[NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"%@%@",audioPath,recoderName]];
tempRecoderPath=[NSString stringWithFormat:@"%@%@",audioRecoderSavePath,recoderName];
tempRecordedFile = [NSURL fileURLWithPath:tempRecoderPath];
recorder = [[AVAudioRecorder alloc] initWithURL:tempRecordedFile settings:[self getAudioSetting] error:nil];
recorder.delegate=self;
[recorder prepareToRecord];
[recorder record];
avplayer = nil;
}
//If the app is recording, we want to stop recording, enable the play button, and make the record button say "REC"
else
{
isRecording = NO;
stateLabel.text=[NSString stringWithFormat:@"%@%@",@"录音完成",recoderName];
//startRecoderBtn.titleLabel.text=@"开始录音";
[startRecoderBtn setTitle:@"开始录音" forState:(UIControlStateNormal)];
[recorder stop];
recorder = nil;

}


4.在列表展示文件目录中,遍历所有的录音文件

-(NSMutableArray *)getFilenamelistOfType:(NSString *)type fromDirPath:(NSString *)dirPath
{
NSMutableArray *filenamelist = [[NSMutableArray alloc]init];
NSArray *tmplist = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:nil];

for (NSString *filename in tmplist) {
NSString *fullpath = [dirPath stringByAppendingPathComponent:filename];
if ([self isFileExistAtPath:fullpath]) {
if ([[filename pathExtension] isEqualToString:type]) {
AudioObject *ob=[[AudioObject alloc]init];
ob.audioRecoderName=filename;
ob.audioRecoderPath=fullpath;
ob.audioRecoderIsChecked=NO;
[filenamelist addObject:ob];
}
}
}

return filenamelist;
}

-(BOOL)isFileExistAtPath:(NSString*)fileFullPath {
BOOL isExist = NO;
isExist = [[NSFileManager defaultManager] fileExistsAtPath:fileFullPath];
return isExist;
}


完整代码

头文件

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h> #import <CoreAudio/CoreAudioTypes.h>
#import "Comm.h"
#import "AudioTableViewCell.h"
#import "AudioObject.h"
#import "AppDelegate.h"

@protocol AudioViewControllerDelegate <NSObject>

-(void)passAudioValueArray:(NSMutableArray *)array;

@end
@interface AudioViewController : UIViewController<AVAudioRecorderDelegate,AVAudioPlayerDelegate,UITableViewDelegate,UITableViewDataSource,AudioTableViewCellDelegate>
{
NSURL *tempRecordedFile;
AVAudioPlayer *avplayer;
AVAudioRecorder *recorder;
BOOL isRecording;
NSString * tempRecoderPath;

NSMutableArray *audioRcoderMutableArray;

NSString *audioRecoderSavePath;
NSFileManager *fileMgr;
NSString *recoderName;

NSString *dateaudioPath;
AppDelegate* audioDelegate ;

NSMutableArray *passAudioMutableArray;
}
@property (strong, nonatomic) IBOutlet UIButton *startRecoderBtn;
@property (strong, nonatomic) IBOutlet UIButton *saveRecoderBtn;
@property (strong, nonatomic) IBOutlet UIButton *backBtn;
@property (strong, nonatomic) IBOutlet UILabel *stateLabel;
@property (strong, nonatomic) IBOutlet UIButton *cancelBtn;
@property (strong, nonatomic) IBOutlet UIButton *doneBtn;
@property (strong, nonatomic) IBOutlet UITableView *recoderTableView;
@property (nonatomic, strong) id <AudioViewControllerDelegate>delegate;

@end


.m文件


#import "AudioViewController.h"
#import "Comm.h"

@interface AudioViewController ()

@end

@implementation AudioViewController
@synthesize startRecoderBtn;
@synthesize saveRecoderBtn;
@synthesize backBtn;
@synthesize stateLabel;
@synthesize cancelBtn;
@synthesize doneBtn;
@synthesize recoderTableView;

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.

recoderTableView.delegate=self;
recoderTableView.dataSource=self;
isRecording=NO;
passAudioMutableArray=[[NSMutableArray alloc] init];
NSDate * date=[NSDate date]; NSDateFormatter *dateformatter=[[NSDateFormatter alloc] init]; [dateformatter setDateFormat:@"YYYY-MM-dd"]; NSString *datefloder= [dateformatter stringFromDate:date]; dateaudioPath=[NSString stringWithFormat:@"%@/",datefloder]; fileMgr = [NSFileManager defaultManager]; //指向文件目录 NSString *documentsDirectory= [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; audioRecoderSavePath=[NSString stringWithFormat:@"%@/%@%@", documentsDirectory,audioPath,dateaudioPath]; if (![fileMgr fileExistsAtPath:audioRecoderSavePath]) { [fileMgr createDirectoryAtPath:audioRecoderSavePath withIntermediateDirectories:YES attributes:nil error:nil]; }
audioDelegate = [[UIApplication sharedApplication] delegate];
audioRcoderMutableArray=[[NSMutableArray alloc]init];

audioRcoderMutableArray = [self getFilenamelistOfType:@"caf" fromDirPath:audioRecoderSavePath];
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *sessionError;
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
//[session setCategory:AVAudioSessionCategoryPlayback error:nil];
if(session == nil)
NSLog(@"Error creating session: %@", [sessionError description]);
else
[session setActive:YES error:nil];
}
-(void)viewDidUnload
{

}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnControl:(UIButton *)sender {
switch (sender.tag) {
//返回
case 0:
[self.delegate passAudioValueArray:passAudioMutableArray];
audioDelegate.audioSelectedMutableArray=audioRcoderMutableArray;
[self dismissModalViewControllerAnimated:YES];
break;
//录音
case 1:

if(!isRecording)
{
isRecording = YES;
stateLabel.text=@"录音中";
[startRecoderBtn setTitle:@"停止录音" forState:(UIControlStateNormal)];
// startRecoderBtn.titleLabel.text=@"停止录音";
NSDate * date=[NSDate date];
NSDateFormatter *dateformatter=[[NSDateFormatter alloc] init];
[dateformatter setDateFormat:@"YYYYMMddHHYYSS"];
recoderName= [NSString stringWithFormat:@"%@%@",[dateformatter stringFromDate:date],@".caf"];
//tempRecoderPath=[NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"%@%@",audioPath,recoderName]];
tempRecoderPath=[NSString stringWithFormat:@"%@%@",audioRecoderSavePath,recoderName];
tempRecordedFile = [NSURL fileURLWithPath:tempRecoderPath];
recorder = [[AVAudioRecorder alloc] initWithURL:tempRecordedFile settings:[self getAudioSetting] error:nil];
recorder.delegate=self;
[recorder prepareToRecord];
[recorder record];
avplayer = nil;
}
//If the app is recording, we want to stop recording, enable the play button, and make the record button say "REC"
else
{
isRecording = NO;
stateLabel.text=[NSString stringWithFormat:@"%@%@",@"录音完成",recoderName];
//startRecoderBtn.titleLabel.text=@"开始录音";
[startRecoderBtn setTitle:@"开始录音" forState:(UIControlStateNormal)];
[recorder stop];
recorder = nil;

}

break;
//保存录音
//讲temp文件下的录音文件移动到docment 目录下面并且重命名

case 2:
[self SaveAudioRecoder];
break;
//取消
case 3:
[self.delegate passAudioValueArray:passAudioMutableArray];
audioDelegate.audioSelectedMutableArray=audioRcoderMutableArray;
[self dismissModalViewControllerAnimated:YES];
break;
//确定
case 4:
[self.delegate passAudioValueArray:passAudioMutableArray];
audioDelegate.audioSelectedMutableArray=audioRcoderMutableArray;
[self dismissModalViewControllerAnimated:YES];
break;
default:
break;
}
}

#pragma mark - 私有方法

/**
* 取得录音文件设置
*
* @return 录音设置
*/
-(NSMutableDictionary *)getAudioSetting{
NSMutableDictionary *dicM=[NSMutableDictionary dictionary];
//设置录音格式
[dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
//设置录音采样率,8000是电话采样率,对于一般录音已经够了
[dicM setObject:@(8000) forKey:AVSampleRateKey];
//设置通道,这里采用单声道
[dicM setObject:@(1) forKey:AVNumberOfChannelsKey];
//每个采样点位数,分为8、16、24、32
[dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
//是否使用浮点数采样
[dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];
//....其他设置等
return dicM;
}

//保存录音
-(void)SaveAudioRecoder
{
if (recorder!=nil) {

UIAlertController * alertController = [UIAlertController alertControllerWithTitle:nil message:@"请先停止录音" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
}];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:nil];

}
else
{
stateLabel.text=@"开始录音";
AudioObject *object=[[AudioObject alloc]init];
object.audioRecoderName=recoderName;
object.audioRecoderPath=tempRecoderPath;
object.audioRecoderIsChecked=NO;
[audioRcoderMutableArray addObject:object];
[recoderTableView reloadData];
}
}
//播放音频
-(void)PlayAudioRecoder :(NSString *) filePayh
{

NSError *playerError;
NSURL * playurl=[NSURL URLWithString:filePayh];
avplayer = [[AVAudioPlayer alloc] initWithContentsOfURL:playurl error:&playerError];

if (avplayer == nil)
{
NSLog(@"ERror creating player: %@", [playerError description]);
}
avplayer.delegate = self;
[avplayer prepareToPlay];
[avplayer play];

}

-(NSMutableArray *)getFilenamelistOfType:(NSString *)type fromDirPath:(NSString *)dirPath { NSMutableArray *filenamelist = [[NSMutableArray alloc]init]; NSArray *tmplist = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:nil]; for (NSString *filename in tmplist) { NSString *fullpath = [dirPath stringByAppendingPathComponent:filename]; if ([self isFileExistAtPath:fullpath]) { if ([[filename pathExtension] isEqualToString:type]) { AudioObject *ob=[[AudioObject alloc]init]; ob.audioRecoderName=filename; ob.audioRecoderPath=fullpath; ob.audioRecoderIsChecked=NO; [filenamelist addObject:ob]; } } } return filenamelist; } -(BOOL)isFileExistAtPath:(NSString*)fileFullPath { BOOL isExist = NO; isExist = [[NSFileManager defaultManager] fileExistsAtPath:fileFullPath]; return isExist; }

#pragma mark - 录音机代理方法
/**
* 录音完成,录音完成后播放录音
*
* @param recorder 录音机对象
* @param flag 是否成功
*/
-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{

NSLog(@"录音完成!");
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
[avplayer stop];
avplayer=nil;
NSLog(@"播放完成!");
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:nil message:@"录音播放完成" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
recorder=nil;
avplayer=nil;
}];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:nil];

}
#pragma tableviewdelege

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

return audioRcoderMutableArray.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//指定cellIdentifier为自定义的cell
static NSString *CellIdentifier = @"AudioTableViewCell";
//自定义cell类
AudioTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
//通过xib的名称加载自定义的cell
cell = [[[NSBundle mainBundle] loadNibNamed:@"AudioTableViewCell" owner:self options:nil] lastObject];
cell.delegate=self;
}
cell.checkBtn.tag=indexPath.row;
cell.playBtn.tag=indexPath.row;
AudioObject *item=[audioRcoderMutableArray objectAtIndex:indexPath.row];
cell.audioNameLabel.text=item.audioRecoderName;
if (item.audioRecoderIsChecked) {
[ cell.checkBtn setImage:[UIImage imageNamed:@"abc_btn_check_to_on_mtrl_015.png"] forState:UIControlStateNormal];
}else
{
[ cell.checkBtn setImage:[UIImage imageNamed:@"abc_btn_check_to_on_mtrl_000.png"] forState:UIControlStateNormal];
}

return cell;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{

return YES;
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
AudioObject *zz=[audioRcoderMutableArray objectAtIndex:indexPath.row];
NSString * deletefile=zz.audioRecoderPath;

BOOL bRet = [fileMgr fileExistsAtPath:deletefile];
if (bRet) {
//
NSError *err;
[fileMgr removeItemAtPath:deletefile error:&err];

}
[ audioRcoderMutableArray removeObjectAtIndex:indexPath.row];
// Delete the row from the data source.
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

}
//修改左滑删除按钮的title
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @"删除";
}

int selectCount=0;
#pragma celldelegate
-(void)SelectAudioClicked:(UIButton *)button
{
NSInteger s=button.tag;
AudioObject *sm=[audioRcoderMutableArray objectAtIndex:s];

if (sm.audioRecoderIsChecked) {
sm.audioRecoderIsChecked=NO;
if (selectCount==0) {
return;
}
else
{
selectCount=selectCount-1;
[passAudioMutableArray removeObject:sm];
[ button setImage:[UIImage imageNamed:@"abc_btn_check_to_on_mtrl_000.png"] forState:UIControlStateNormal];
NSString *btntile=[NSString stringWithFormat:@"完成(%d/5)",selectCount];
[doneBtn setTitle:btntile forState:(UIControlStateNormal)];

}

}else
{
sm.audioRecoderIsChecked=YES;
if (selectCount>5) {
return;
}
else
{
selectCount=selectCount+1;
[passAudioMutableArray addObject:sm];
[ button setImage:[UIImage imageNamed:@"abc_btn_check_to_on_mtrl_015.png"] forState:UIControlStateNormal];
NSString *btntile=[NSString stringWithFormat:@"完成(%d/5)",selectCount];
[doneBtn setTitle:btntile forState:(UIControlStateNormal)];
}

}

}
-(void)PlayAudioClicked:(UIButton *)button
{
NSInteger s=button.tag;
AudioObject *j=[audioRcoderMutableArray objectAtIndex:s];
NSString *pp=j.audioRecoderPath;
[self PlayAudioRecoder:pp];

}
/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/

@end


存在问题:

1.播放录音是听筒声音。

2.未将录音转换为通用的音频格式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios uitableview 界面