1. 程式人生 > >ios錄音功能實現

ios錄音功能實現

實現功能主要為:按下按鈕開始錄音,時間條開始計時,鬆開停止錄音,時間條停止計時,滑開手指放棄錄音。保存錄音檔案到本地document檔案中。

一、匯入標頭檔案和代理

#import <AVFoundation/AVFoundation.h>
<AVAudioRecorderDelegate>

二、在.h檔案中宣告

{
    MBProgressHUD *HUD;
    UILabel *noticeLabel;//提示標籤
}

@property (nonatomic,strong) UIView *recordView;//錄音介面
@property
(nonatomic,strong) UIButton *recordBtn;//錄音按鈕 @property (nonatomic,strong) UILabel *timeLabel; //錄音計時 @property (nonatomic,strong) AVAudioRecorder *audioRecorder;//音訊錄音機 @property (nonatomic,assign) NSInteger countNum;//錄音計時(秒) @property (nonatomic,strong) NSTimer *timer1; //控制錄音時長顯示更新 @property (nonatomic
,copy) NSString *cafPathStr;

三、正文

在.m檔案中新增

#define margin 15
#define kSandboxPathStr [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
#define kCafFileName @"myRecord.caf"
/**
 *存放所有的音樂播放器
 */
static NSMutableDictionary *_musices;
//頁面佈局
- (void)setupView
{
    CGFloat
recordH = SCREEN_HEIGHT * 0.4; CGFloat availH = recordH - margin * 4; _recordView = [[UIView alloc]initWithFrame:CGRectMake(0, SCREEN_HEIGHT - recordH, SCREEN_WIDTH, recordH)]; _recordView.backgroundColor = [UIColor whiteColor]; [self addSubview:_recordView]; CGFloat timeH = availH * 0.2; CGFloat btnH = availH * 0.7; CGFloat noticeH = availH * 0.1; self.timeLabel.frame = CGRectMake(0, margin, SCREEN_WIDTH, timeH); self.recordBtn.frame = CGRectMake((SCREEN_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(startRecordNotice) forControlEvents:UIControlEventTouchDown]; [self.recordBtn addTarget:self action:@selector(stopRecordNotice) forControlEvents:UIControlEventTouchUpInside]; [self.recordBtn addTarget:self action:@selector(cancelRecordNotice) forControlEvents:UIControlEventTouchUpOutside]; self.closeBtn.frame = CGRectMake(SCREEN_WIDTH - 25, 5, 20, 20); [_closeBtn addTarget:self action:@selector(closeBtnClick) forControlEvents:UIControlEventTouchUpInside]; [_recordView addSubview:self.timeLabel]; [_recordView addSubview:self.recordBtn]; [_recordView addSubview:self.closeBtn]; noticeLabel = [[UILabel alloc]init]; noticeLabel.frame = CGRectMake(0, recordH - noticeH - margin, SCREEN_WIDTH, noticeH); noticeLabel.textAlignment = NSTextAlignmentCenter; noticeLabel.textColor = [UIColor lightGrayColor]; noticeLabel.font = [UIFont systemFontOfSize:14]; noticeLabel.text = @"按住不放錄製語音"; [_recordView addSubview:noticeLabel]; self.timeLabel2.text = @""; self.cafPathStr = [kSandboxPathStr stringByAppendingPathComponent:kCafFileName]; } -(UIButton *)closeBtn { if (!_closeBtn) { _closeBtn = [[UIButton alloc]init]; [_closeBtn setBackgroundImage:[UIImage imageNamed:@"infoClose.png"] forState:UIControlStateNormal]; } return _closeBtn; } -(UILabel *)timeLabel { if (!_timeLabel) { _timeLabel = [[UILabel alloc]init]; _timeLabel.textAlignment = NSTextAlignmentCenter; _timeLabel.font = [UIFont fontWithName:@"HelveticaNeue-Thin" size:42]; _timeLabel.text = @"00:00"; _timeLabel.textColor = MF_ColorFromRGB(215, 155, 252); } return _timeLabel; } - (UIButton *)recordBtn { if (!_recordBtn) { _recordBtn = [[UIButton alloc]init]; _recordBtn.backgroundColor = [UIColor clearColor]; [_recordBtn setBackgroundImage:[UIImage imageNamed:@"record_norm"] forState:UIControlStateNormal]; [_recordBtn setBackgroundImage:[UIImage imageNamed:@"record_high"] forState:UIControlStateHighlighted]; // _recordBtn.userInteractionEnabled = YES;//方便新增長按手勢 } return _recordBtn; }
//點選關閉頁面按鈕
- (void)closeBtnClick
{
    [self removeFromSuperview];
}
#pragma mark - 錄音方法
//改變錄音時間
- (void)changeRecordTime
{

    self.countNum += 1;
    NSInteger min = self.countNum/60;
    NSInteger sec = self.countNum - min * 60;
 //   NSInteger sec = self.countNum;

    self.timeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld",(long)min,(long)sec];

    if (sec == 59) {
        [self stopRecordNotice];
    }
}

- (void)startRecordNotice{
    self.timeLabel2.text = @"";

    [self stopMusicWithUrl:[NSURL URLWithString:self.cafPathStr]];

    if ([self.audioRecorder isRecording]) {
        [self.audioRecorder stop];
    }
//    NSLog(@"----------開始錄音----------");
    [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];
    }

    noticeLabel.text = @"脫離按鈕,鬆開手指放棄錄音";
}

- (void)stopRecordNotice
{
//    NSLog(@"----------結束錄音----------");
    [self.audioRecorder stop];
    [self.timer1 invalidate];

//    計算檔案大小
    long long fileSize = [self fileSizeAtPath:self.mp3PathStr]/1024.0;
    NSString *fileSizeStr = [NSString stringWithFormat:@"%lld",fileSize];

    self.timeLabel2.text = [NSString stringWithFormat:@"%ld \" %@kb  ",(long)self.countNum,fileSizeStr];
    self.timeLabel.text = @"01:00";

    [self.delegate getRecordData:self.mp3PathStr type:@"2" fileName:kMp3FileName];

    [self removeFromSuperview];
}


- (void)cancelRecordNotice
{
//    NSLog(@"----------取消錄音----------");
    [self.audioRecorder stop];
    [self.timer1 invalidate];

    //    計算檔案大小
    long long fileSize = [self fileSizeAtPath:self.mp3PathStr]/1024.0;
    NSString *fileSizeStr = [NSString stringWithFormat:@"%lld",fileSize];

    self.timeLabel2.text = [NSString stringWithFormat:@"%ld \" %@kb  ",(long)self.countNum,fileSizeStr];
    self.timeLabel.text = @"00:00";

    noticeLabel.text = @"按住不放錄製語音";
}
//刪除舊錄音快取
-(void)deleteOldRecordFile{
    NSFileManager* fileManager=[NSFileManager defaultManager];

    BOOL blHave=[[NSFileManager defaultManager] fileExistsAtPath:self.cafPathStr];
    if (!blHave) {
//        NSLog(@"不存在");
        return ;
    }else {
//        NSLog(@"存在");
        BOOL blDele= [fileManager removeItemAtPath:self.cafPathStr error:nil];
        if (blDele) {
//            NSLog(@"刪除成功");
        }else {
//            NSLog(@"刪除失敗");
        }
    }
}
#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)stopMusicWithUrl:(NSURL *)fileUrl{
    if (!fileUrl) return;//如果沒有傳入檔名,那麼就直接返回

    //1.取出對應的播放器
    AVAudioPlayer *player=[self musices][fileUrl];

    //2.停止
    if ([player isPlaying]) {
        [player stop];
//        NSLog(@"播放結束:%@--------",fileUrl);
    }

    if ([[self musices].allKeys containsObject:fileUrl]) {
        [[self musices] removeObjectForKey:fileUrl];
    }
}
//單個檔案的大小
- (long long) fileSizeAtPath:(NSString*)filePath{

    NSFileManager* manager = [NSFileManager defaultManager];

    if ([manager fileExistsAtPath:filePath]){

        return [[manager attributesOfItemAtPath:filePath error:nil] fileSize];

    }else{
        NSLog(@"計算檔案大小:檔案不存在");
    }

    return 0;
}