關於iOS 錄音而且轉碼上傳的相關問題

第一步: 錄音html

錄音這個很簡單,給你們分享一個比較全面的demo,git

https://github.com/liuchunlao/RecordAndPlayVoice;github

錄音和播放的功能基本夠用了,json


/** 錄音工具的單例 */
+ (instancetype)sharedRecordTool;xcode

/** 開始錄音 */
- (void)startRecording;服務器

/** 中止錄音 */
- (void)stopRecording;網絡

/** 播放錄音文件 */
- (void)playRecordingFile;app

/** 中止播放錄音文件 */
- (void)stopPlaying;dom

/** 銷燬錄音文件 */
- (void)destructionRecordingFile;工具

/** 錄音對象 */
@property (nonatomic, strong) AVAudioRecorder *recorder;
/** 播放器對象 */
@property (nonatomic, strong) AVAudioPlayer *player;

/** 更新圖片的代理 */
@property (nonatomic, assign) id<LVRecordToolDelegate> delegate;


詳細的實現代碼你們能夠看下載的demo.

須要提醒你們注意一點:

若是你要轉碼成MP3,這部分的設置不能隨便寫<代碼一>

- (AVAudioRecorder *)recorder {
    if (!_recorder) {
        
        // 1.獲取沙盒地址
        NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        //  2.錄音文件的路徑 @"lvRecord.caf"
        NSString *filePath = [path stringByAppendingPathComponent:LVRecordFielName];
        self.recordFileUrl = [NSURL fileURLWithPath:filePath];
        NSLog(@"%@", filePath);
        
        
         NSDictionary *setting = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithInt:AVAudioQualityMin],
                             AVEncoderAudioQualityKey,
                             [NSNumber numberWithInt:16],
                             AVEncoderBitRateKey,
                             [NSNumber numberWithInt:2],
                             AVNumberOfChannelsKey,
                             [NSNumber numberWithFloat:44100.0],
                             AVSampleRateKey,
                               nil];
        
        _recorder = [[AVAudioRecorder alloc] initWithURL:self.recordFileUrl settings:setting error:NULL];
        _recorder.delegate = self;
        _recorder.meteringEnabled = YES;
//崩潰的地方
        [_recorder prepareToRecord];
    }
    return _recorder;
}

setting裏的參數設置,這些值是我嘗試出來的轉碼成MP3後還能夠正常播放的值,若是有某一個值不合適,你就聽不到本身錄的音了哦;至於爲何要設置成這些參數,本人目前還未深究,若是有這方面的大牛,能夠分享下;還有一點,你們注意看,我註釋的那行

//崩潰的地方
        [_recorder prepareToRecord];

若是你用了這個demo,可能會發現,模擬器上跑會崩在這一行,可是跑真機上能夠正常錄音和播放,我當時被這個bug卡了好久,一度都想要放棄了,後來同事幫忙查到,這是xcode的bug,真心有點想吐血的感受!!!

解決辦法很簡單,如圖,打個全局斷點,右擊,第一個選項Exception 選擇All,就OK了

這個問題能夠就這樣圓滿解決了!!

第二步:轉MP3

首先,你須要去網上下載一個lame的第三方庫,網上不少的但要提醒你們,你下載的lame.a必須是支持 64 位編譯器的,不然導入會報錯.下載完後,只須要把這兩個東西添加到你的項目中就能夠啦

如圖

 

 

而後還須要一段代碼<代碼2爲借鑑結果>

- (void)audio_CAFtoMP3
{
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
     NSString *filePath = [path stringByAppendingPathComponent:@"lvRecord.caf"];
    NSString *mp3FilePath = [path stringByAppendingPathComponent:@"temp.mp3"];
    
    @try {
        int read, write;
        
        FILE *pcm = fopen([filePath cStringUsingEncoding:1], "rb");  //source 被轉換的音頻文件位置
        fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header
        FILE *mp3 = fopen([mp3FilePath 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_num_channels(lame,1);//設置1爲單通道,默認爲2雙通道
        lame_set_in_samplerate(lame, 44100.0);
        lame_set_VBR(lame, vbr_default);
        
        lame_set_brate(lame,8);
        
        lame_set_mode(lame,3);
        
        lame_set_quality(lame,2);
        
        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 {
//        self.audioFileSavePath = mp3FilePath;
//        NSLog(@"MP3生成成功: %@",self.audioFileSavePath);
    }
    
}


這樣就成功的把.caf 或者 .wav轉換成了mp3格式.若是你想問爲何要轉MP3或者不轉MP3能不能上傳,很差意思,我只能告訴你,蘋果的錄音格式安卓獲取到了沒法播放,不轉能不能上傳 這個須要你本身去嘗試一下.

第三步:上傳

咱們首先要拿到錄音文件的路徑,而後用NSFileManager以二進制的格式讀取出來,再用本身封裝的AFN上傳就能夠啦.咱們項目裏是有圖片和音頻一塊兒上傳的,在這裏把代碼拿出來和你們分享下

+(void)photoImagePost:(NSDictionary *)paramDict andImageDatas:(NSMutableArray*)imageArray andVoiceData:(NSString *)filePath success:(mSuccessBlock)successBlock errorBlock:(mErrorBlock)errorBlock
{
    [AppSettings httpSetCookies];
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer =[AFHTTPRequestSerializer serializer];
    manager.responseSerializer =[AFJSONResponseSerializer serializer];
    
    //[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    manager.responseSerializer.acceptableContentTypes=[manager.responseSerializer.acceptableContentTypes setByAddingObject: @"text/html"];
    
    //設置多個文件的分隔符
    unsigned int random = arc4random();
    NSString * boundary = [NSString stringWithFormat:@"%d",random];
    
    NSString *contentType = [NSString stringWithFormat:@"boundary=%@",boundary];
    [manager.requestSerializer setValue:contentType forHTTPHeaderField:@"Content-Type"];
    
    [manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
    manager.requestSerializer.timeoutInterval = 30.f;
    [manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
    
    
    NSString *uslStr =[postURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    //    NSMutableDictionary *dict=[NSMutableDictionary dictionaryWithCapacity:0];
    //    [dict setValue:serviceCode forKey:@"A"];
    //    [dict setValue:[paramDict JSONString] forKey:@"P"];
    
    [manager POST:uslStr parameters:paramDict constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
     {
         // 圖片處理
         for(int i=0;i<imageArray.count;i++)
         {
             NSData *data=UIImageJPEGRepresentation(imageArray[i], 0.2);
             [formData appendPartWithFileData:data name:[NSString stringWithFormat:@"Pictures[]"] fileName:[NSString stringWithFormat:@"pic%d.jpg",i+1] mimeType:@"image/*"];
         }
         // 語音處理
         //方法1
         NSFileManager* fm=[NSFileManager defaultManager];
         
         NSData *data = nil;
         
         //路徑是傳進來的
         if([fm fileExistsAtPath:filePath]){
             
             //讀取某個文件
             
              data = [NSData dataWithContentsOfFile:filePath];
             //    NSLog(@"%@",data);
         }
         
         [formData appendPartWithFileData:data name:@"voice[]" fileName:@"temp.mp3" mimeType:@"amr/mp3/wmr"];
         //
         
     } success:^(AFHTTPRequestOperation *operation,id responseObject) {
         
         successBlock(operation,responseObject);
         
     } failure:^(AFHTTPRequestOperation *operation,NSError *error) {
         errorBlock(operation, error);
         NSLog(@"%@",error);
     }];
    
}

這樣,就能夠上傳成功啦!

第四步:  從服務器獲取錄音文件並播放

其實,錄音成功了,播放很簡單,導入頭文件:

#import <AVFoundation/AVFoundation.h>

//播放
            NSString * urlStr = [NSString stringWithFormat:@"http://120.25.221.42:8010%@",model.Voice.lastObject];
            NSURL *url = [NSURL URLWithString:urlStr];
            
            //把音頻文件保存到本地
            NSData *audioData = [NSData dataWithContentsOfURL:url];
            NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
            NSString *filePath = [NSString stringWithFormat:@"%@/%@.mp3", docDirPath ,
                                  @"temp2"];
          //  DDLogWarn(@" 從網絡拿到的音頻數據寫入的本地路徑  %@",filePath);
            [audioData writeToFile:filePath atomically:YES];
            
            NSURL *fileURL = [NSURL fileURLWithPath:filePath];
            self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error: &error];
            
            
            self.player.volume=1;
            
            if (error) {
                
                NSLog(@"error:%@",[error description]);
                
                return;
                
            }
            
            //準備播放
            
            [self.player prepareToPlay];
            [self.player play];
            
           //顯示時長 (暫時是點擊了播放以後才知道時長)
            float duration = (float)self.player.duration;

            NSString *format = [self decimalwithFormat:@"0" floatV:duration ];
            
            
            self.voice.timeLable.text = [NSString stringWithFormat:@"%@S",format];

這裏須要注意:咱們的 self.player播放不了  非本地的URL的音頻文件,必須先以二進制的形式讀出來,保存到沙盒,再拿到沙盒路徑播放.

至此整個錄音,轉碼,上傳,下載,播放,都已圓滿的完成啦.

本人系iOS菜鳥一枚,博文中若有錯誤之處歡迎你們批評指正,也歡迎你們提問和分享,本文系原創,轉載請註明出處,謝謝!

相關文章
相關標籤/搜索