IOS開發:錄音功能,播放功能的完整實現demo


我是在別人的demo基礎上繼續做的,百度cui ios ,博客園的那個,那人博客寫的相當仔細,大家想學的更多可以去他博客看看

原demo只有錄音界面,然后錄音結束自動播放的功能。

錄音界面我稍微改了下,本身是錄音結束就自動播放,我是選擇了在別的界面播放。然后是取路徑命名的問題,我改為了用當前時間命名。原demo是用myRecord.caf作為結尾命名,因為原demo錄完就播放嘛。

錄音界面有個列表按鈕,跳到第二個界面,可看到具體的錄音欄目。然后點擊右側的按鈕,進入第三個頁面自動播放,然后是暫停繼續等等

第三個頁面自動播放,其實就是把創建音頻播放器對象寫在了load里,然后調用下音頻會話,跟第一個界面的東西基本一樣的思路。

然后還有一個關鍵點是第二個界面點按鈕跳轉的時候,你必須知道你點的是第幾行,也就是你點的是哪個錄音,把這個路徑送到第三個界面給音頻對象用,這個采用單例模式實現跨界面傳值。

還有就是頁面間的跳轉,一種直接拉線,一種是用代碼,我的隨筆里也寫了用代碼的。

 

界面設計

 

 

錄音界面代碼

  1 #import "ViewController.h"
  2 #import <AVFoundation/AVFoundation.h>
  3 
  4 @interface ViewController ()<AVAudioRecorderDelegate>
  5 
  6 @property (nonatomic,strong) AVAudioRecorder *audioRecorder;//音頻錄音機
  7 @property (nonatomic,strong) AVAudioPlayer *audioPlayer;//音頻播放器,用於播放錄音文件
  8 @property (nonatomic,strong) NSTimer *timer;//錄音聲波監控(注意這里暫時不對播放進行監控)
  9 
 10 @property (weak, nonatomic) IBOutlet UIButton *record;//開始錄音
 11 @property (weak, nonatomic) IBOutlet UIButton *pause;//暫停錄音
 12 @property (weak, nonatomic) IBOutlet UIButton *resume;//恢復錄音
 13 @property (weak, nonatomic) IBOutlet UIButton *stop;//停止錄音
 14 @property (weak, nonatomic) IBOutlet UIProgressView *audioPower;//音頻波動
 15 @property (weak, nonatomic) IBOutlet UIButton *exit;//退出
 16 
 17 @end
 18 
 19 @implementation ViewController
 20 
 21 #pragma mark - 控制器視圖方法
 22 - (void)viewDidLoad {
 23     //f改變progressview的長寬
 24     _audioPower.transform=CGAffineTransformMakeScale(1.0f,4.0f);
 25     [super viewDidLoad];
 26     //自動播放的
 27     [self setAudioSession];
 28 }
 29 
 30 #pragma mark - 私有方法
 31 
 32 
 33 
 34 /**
 35  *  取得錄音文件保存路徑
 36  *
 37  *  @return 錄音文件路徑
 38  */
 39 -(NSURL *)getSavePath{
 40     //獲取文件路徑
 41     NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
 42     NSLog(@"%@",urlStr);
 43     NSDate *date=[NSDate date];
 44     NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
 45     [dateFormatter setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
 46     //NSDate轉NSString
 47     NSString *sss = [dateFormatter stringFromDate:date];
 48     NSString *ccc=[sss stringByAppendingString:@".caf"];
 49     urlStr=[urlStr stringByAppendingPathComponent:ccc];
 50     NSURL *url=[NSURL fileURLWithPath:urlStr];
 51    // NSLog(@"第一個頁面的路徑",url);
 52     return url;
 53 }
 54 
 55 /**
 56  *  取得錄音文件設置
 57  *
 58  *  @return 錄音設置
 59  */
 60 -(NSDictionary *)getAudioSetting{
 61     NSMutableDictionary *dicM=[NSMutableDictionary dictionary];
 62     //設置錄音格式
 63     [dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
 64     //設置錄音采樣率,8000是電話采樣率,對於一般錄音已經夠了
 65     [dicM setObject:@(8000) forKey:AVSampleRateKey];
 66     //設置通道,這里采用單聲道
 67     [dicM setObject:@(1) forKey:AVNumberOfChannelsKey];
 68     //每個采樣點位數,分為8、16、24、32
 69     [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
 70     //是否使用浮點數采樣
 71     [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];
 72     //....其他設置等
 73     return dicM;
 74 }
 75 
 76 /**
 77  *  獲得錄音機對象
 78  *
 79  *  @return 錄音機對象
 80  */
 81 -(AVAudioRecorder *)audioRecorder{
 82     if (!_audioRecorder) {
 83         //創建錄音文件保存路徑
 84         NSURL *url=[self getSavePath];
 85         //創建錄音格式設置
 86         NSDictionary *setting=[self getAudioSetting];
 87         //創建錄音機
 88         NSError *error=nil;
 89         _audioRecorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];
 90         _audioRecorder.delegate=self;
 91         _audioRecorder.meteringEnabled=YES;//如果要監控聲波則必須設置為YES
 92         if (error) {
 93             NSLog(@"創建錄音機對象時發生錯誤,錯誤信息:%@",error.localizedDescription);
 94             return nil;
 95         }
 96     }
 97     return _audioRecorder;
 98 }
 99 -(void)setAudioSession{
100     AVAudioSession *audioSession=[AVAudioSession sharedInstance];
101     //設置為錄音狀態
102     [audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
103     [audioSession setActive:YES error:nil];
104 }/**
105  *  錄音聲波監控定制器
106  *
107  *  @return 定時器
108  */
109 -(NSTimer *)timer{
110     if (!_timer) {
111         //創建一個定時器
112         _timer=[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(audioPowerChange) userInfo:nil repeats:YES];
113     }
114     return _timer;
115 };
116 
117 /**
118  *  錄音聲波狀態設置
119  */
120 -(void)audioPowerChange{
121     [self.audioRecorder updateMeters];//更新測量值
122     float power= [self.audioRecorder averagePowerForChannel:0];//取得第一個通道的音頻,注意音頻強度范圍時-160到0
123     CGFloat progress=(1.0/160.0)*(power+160.0);
124     [self.audioPower setProgress:progress];
125 };
126 #pragma mark - UI事件
127 /**
128  *  點擊錄音按鈕
129  *
130  *  @param sender 錄音按鈕
131  */
132 - (IBAction)recordBu:(UIButton *)sender {
133     if (![self.audioRecorder isRecording]) {
134         [self.audioRecorder record];//首次使用應用時如果調用record方法會詢問用戶是否允許使用麥克風,需要在info.plist加權限
135        //創建一個定時器
136         self.timer.fireDate=[NSDate distantPast];
137     }
138 };
139 
140 /**
141  *  點擊暫定按鈕
142  *
143  *  @param sender 暫停按鈕
144  */
145 - (IBAction)pauseBu:(UIButton *)sender {
146     if ([self.audioRecorder isRecording]) {
147         [self.audioRecorder pause];
148         self.timer.fireDate=[NSDate distantFuture];
149         NSLog(@"錄音暫停");
150     }
151 };
152 
153 /**
154  *  點擊恢復按鈕
155  *  恢復錄音只需要再次調用record,AVAudioSession會幫助你記錄上次錄音位置並追加錄音
156  *
157  *  @param sender 恢復按鈕
158  */
159 - (IBAction)resumeBu:(UIButton *)sender {
160     [self recordBu:sender];
161     NSLog(@"錄音繼續");
162 };
163 
164 /**
165  *  點擊停止按鈕
166  *
167  *  @param sender 停止按鈕
168  */
169 - (IBAction)stopBu:(UIButton *)sender {
170     [self.audioRecorder stop];
171     self.timer.fireDate=[NSDate distantFuture];
172     self.audioPower.progress=0.0;
173     NSLog(@"錄音文件路徑%@",[self getSavePath]);
174 };
175 /**
176  
177     退出
178  */
179 -(IBAction)exitBu:(UIButton *)sender{
180     exit(0);
181 };
182 #pragma mark - 錄音機代理方法
183 /**
184  *  錄音完成,錄音完成后播放錄音
185  *
186  *  @param recorder 錄音機對象
187  *  @param flag     是否成功
188  */
189 /*
190 -(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{
191     if (![self.audioPlayer isPlaying]) {
192         [self.audioPlayer play];
193     }
194     NSLog(@"錄音完成!");
195 };
196 */
197 @end

列表界面代碼

  9 #import "ViewController2.h"
 10 #import <Foundation/Foundation.h>
 11 #import <AVFoundation/AVFoundation.h>
 12 #import "ViewController3.h"
 13 #import "Single.h"
 14 @interface ViewController2 () <AVAudioRecorderDelegate,UITableViewDelegate,UITableViewDataSource>
 15 //,UITableViewDelegate, UITableViewDataSource>
 16 //tableView
 17 @property (strong, nonatomic) IBOutlet UITableView *recoderTableView;
 18 
 19 @property (strong,nonatomic ) IBOutlet UIButton  *remove;
 20 
 21 
 22 
 23 
 24 @end
 25 
 26 
 27 @implementation ViewController2
 28 
 29 - (void)viewDidLoad {
 30     [super viewDidLoad];
 31     self.recoderTableView.dataSource=self;
 32     
 33 }
 34 
 35 //返回數組共下面的方法調用
 36 -(NSMutableArray *)getFileList{
 37     NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
 38     NSFileManager *fileManager = [NSFileManager defaultManager];
 39     //將doc下面的文件,以caf為后綴的全部存入數組
 40     //  NSMutableArray *ss=[fileManager enumeratorAtPath:urlStr];
 41     NSMutableArray *ss=[fileManager contentsOfDirectoryAtPath:urlStr error:nil];
 42      return  ss;
 43     // NSString *file;
 44 /* for(int i=0;i<[ss count];i++)
 45     while(file=[ss indexOfObject:i])
 46     {
 47         if([[file pathExtension] isEqual:@".caf"])
 48         {
 49             [fileList addObject:file];
 50             //看file是否有信息
 51             NSLog(@"%@",file);
 52         }
 53     }*/
 54 }
 55 //tableView 的相關方法
 56 //告訴控件分為幾組
 57 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
 58 {
 59     return  1;
 60 }
 61 //告訴UI每組顯示幾行數據,section參數表示第幾組,只有1組,那么section為0
 62 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 63 {
 64     //一組數據,返回存儲文件名稱的數組長度
 65     return [[self getFileList]count];
 66 }
 67 //告訴控件每組的每行顯示什么單元格內容
 68 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
 69 {
 70     UITableViewCell  *cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
 71  //右側的按鈕
 72     cell.accessoryType=UITableViewCellAccessoryDetailButton;
 73     
 74     //獲取存了文件信息的數組然后遍歷賦值到cell文本中
 75    NSMutableArray *ss=[self getFileList];
 76     for(int i=0;i<[tableView numberOfRowsInSection:0];i++)
 77     {
 78      //   indexPath.section==0
 79     //控制每行的
 80       if( indexPath.row==i)
 81         cell.textLabel.text=[ss objectAtIndex:i];
 82     }
 83     return cell;
 84     
 85 }
 86 #pragma  ui控件操作
 87 -(IBAction)deleteBU:(UIButton *)sender{
 88     //setedit animate讓tableView進入可編輯模式
 89     [_recoderTableView setEditing:!_recoderTableView.isEditing animated:true];
 90 }
 91 //對tableView自帶刪除功能的方法實現
 92 -(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
 93 {
 94     
 95     if (editingStyle == UITableViewCellEditingStyleDelete) {//刪除
 96         NSFileManager *fileM=[NSFileManager new];
 97         NSString *newUrl2=[self cellItemPath:indexPath];
 98         [fileM removeItemAtPath:newUrl2 error:nil];
 99        // sing.singleCase=toUrl;
100         [self.recoderTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];//刪除刷新
101     }
102     
103 }
104 //tableView右側的點擊跳轉,需要將URL通過單例對象送到第三個頁面
105 - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
106 {
107     NSString *newUrl2=[self cellItemPath:indexPath];
108     NSURL *toUrl=[[NSURL alloc]initFileURLWithPath:newUrl2];
109     NSLog(@"頁面二准備復制給單例對象的URL是%@",toUrl);
110     [Single sharedInstance].value=toUrl;
111     //跳轉代碼
112     UIViewController *next = [[self storyboard] instantiateViewControllerWithIdentifier:@"ViewController3"];
113     [self presentModalViewController:next animated:NO];
114 
115 }
116 //cell中拿到每行文件的信息,並且拼裝成完整的路徑,供刪除當前行方法,和點擊當前行跳轉方法使用
117 -(NSString  *)cellItemPath:(NSIndexPath *)indexPath{
118     NSFileManager *fileM=[NSFileManager new];
119     NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
120     //     NSString *newStr=urlStr+indexPath.row;
121     NSArray *newArr=[fileM contentsOfDirectoryAtPath:urlStr error:nil];
122     //行數
123     int i=indexPath.row;
124     //接收要刪除的元素
125     NSString *newPro;
126     for(int j=0;j<[newArr count];j++)
127     {
128         if(j==i)
129         {
130             newPro= [newArr objectAtIndex:i];
131         }
132     }
133     //重新拼接路徑,路徑文件夾名+/+要刪除  的文件名
134     NSString *newUrl=[urlStr stringByAppendingString:@"/"];
135     NSString *newUrl2=[newUrl stringByAppendingString:newPro];
136     return  newUrl2;
137 }
138 
139 
140 
141 @end

播放界面代碼

#import "ViewController3.h"
#import <AVFoundation/AVFoundation.h>
#import "ViewController.h"
#import "ViewController2.h"
#import "Single.h"
@interface ViewController3 ()<AVAudioRecorderDelegate>
@property (nonatomic,strong) NSTimer *timer;  //聲波監控,對播放進行監控
@property (weak, nonatomic) IBOutlet UIProgressView *audioPower;//音頻波動
@property (nonatomic,strong) AVAudioPlayer *audioPlayer;//音頻播放器,用於播放錄音文件
@property (weak,nonatomic ) IBOutlet UIButton *pause;//暫停
@property (weak,nonatomic ) IBOutlet UIButton *conti;//繼續
@property (weak,nonatomic ) IBOutlet UIButton *back;//返回
//通過單例對象拿到第二個控制器的cell對象傳的URL
@property (nonatomic,copy) NSURL *url;

@property (weak, nonatomic) IBOutlet UIButton *exit0;

@end

@implementation ViewController3

- (void)viewDidLoad {
    [super viewDidLoad];
    _url=[Single sharedInstance].value;
    
    NSLog(@"頁面三%@",_url);
    if(!_audioPlayer){
    _audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:_url error:nil];
    _audioPlayer.numberOfLoops=0;
    [_audioPlayer prepareToPlay];
    
    //開啟定時器
    self.timer.fireDate=[NSDate distantPast];
    }
     
    [self setAudioSession];
[self.audioPlayer play]; }
/** * 設置音頻會話 */ -(void)setAudioSession{ AVAudioSession *audioSession=[AVAudioSession sharedInstance]; //設置為播放狀態 [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; } /** * 錄音聲波監控定制器 * * @return 定時器 */ -(NSTimer *)timer{ if (!_timer) { //創建一個定時器 _timer=[NSTimer scheduledTimerWithTimeInterval:0.5f target:self selector:@selector(audioPowerChange) userInfo:nil repeats:YES]; } return _timer; }; /** * 播放聲波狀態設置 */ -(void)audioPowerChange{ float progress= self.audioPlayer.currentTime /self.audioPlayer.duration; [self.audioPower setProgress:progress animated:true]; }; #pragma UI操作 //退出 -(IBAction)exitBu:(UIButton *)sender{ exit(0); }; //返回 -(IBAction)backBu:(UIButton *)sender{ UIViewController *next = [[self storyboard] instantiateViewControllerWithIdentifier:@"ViewController2"]; [self presentModalViewController:next animated:NO]; }; //暫停 -(IBAction)pauseBu:(UIButton *)sender { [self.audioPlayer pause]; self.timer.fireDate=[NSDate distantFuture]; }; //繼續 -(IBAction)contiBu:(UIButton *)sender{ [self.audioPlayer play]; self.timer.fireDate=[NSDate distantPast]; } @end

還有個單例類存URL的代碼,這個我寫過了,在隨筆里

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM