iOS 实现录音并保存在指定文件目录下面
2016-01-07 16:31
423 查看
原理:
进入界面,先遍历文件目录,将所有的文件名,显示在uitableview中。在录音时需要设置session以及录音采样率。
1.ios录音主要使用ios自带的类,是工程中需要手动添加这俩个framework
2.在录音前,先监测文件存放目录是否存在,不存在就创建目录
3.点击录音,开始录音
4.在列表展示文件目录中,遍历所有的录音文件
完整代码
头文件
.m文件
存在问题:
1.播放录音是听筒声音。
2.未将录音转换为通用的音频格式。
进入界面,先遍历文件目录,将所有的文件名,显示在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.未将录音转换为通用的音频格式。
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- winform异型不规则界面设计的实现方法
- Android中设置只有程序第一次运行才显示的界面实现思路
- hta 实现的五子棋界面
- 讲解iOS开发中基本的定位功能实现
- js判断客户端是iOS还是Android等移动终端的方法
- IOS开发环境windows化攻略
- 浅析iOS应用开发中线程间的通信与线程安全问题
- 检测iOS设备是否越狱的方法
- android开发之欢迎界面的小例子
- C#中载入界面的常用方法
- .net平台推送ios消息的实现方法
- 探讨Android与iOS,我们将何去何从?
- android编程实现局部界面动态切换的方法