iOS開發(fā)項(xiàng)目- 基于WebSocket的聊天通訊(2)
公司項(xiàng)目需要開發(fā)一個(gè)類似QQ、微信的即時(shí)IM聊天功能,做到實(shí)時(shí)監(jiān)控消息,需要用的技術(shù)是websocket,今天整理下語(yǔ)言聊天這塊;其實(shí)語(yǔ)言聊天,包含兩部分,錄音和音樂播放,關(guān)于簡(jiǎn)單語(yǔ)言聊天功能如下圖:
錄音
在AVFoundation框架中有一個(gè)AVAudioRecorder類專門處理錄音操作,它同樣支持多種音頻格式。與AVAudioPlayer類似,你完全可以將它看成是一個(gè)錄音機(jī)控制類,下面是常用的屬性和方法:
先來了解下AVAudioRecorder的常用屬性:
@property (readonly, getter=isRecording) BOOL recording;//是否正在錄音 @property (readonly) NSDictionary<NSString *, id> *settings;//錄音配置 @property (readonly) NSURL *url;//錄音文件存放URL @property (readonly) NSTimeInterval currentTime;//錄音時(shí)長(zhǎng) @property (getter=isMeteringEnabled) BOOL meteringEnabled;//是否監(jiān)控聲波
常用對(duì)象方法:
- (BOOL)prepareToRecord;//為錄音準(zhǔn)備緩沖區(qū) - (BOOL)record;//錄音開始,暫停后調(diào)用會(huì)恢復(fù)錄音 - (BOOL)recordAtTime:(NSTimeInterval)time;//在指定時(shí)間后開始錄音 - (BOOL)recordForDuration:(NSTimeInterval) duration;//按指定時(shí)長(zhǎng)錄音 - (BOOL)recordAtTime:(NSTimeInterval)time forDuration:(NSTimeInterval)duration;//上面2個(gè)的合體 - (void)pause; //中斷錄音 - (void)stop; //停止錄音 - (BOOL)deleteRecording;//刪除錄音,必須先停止錄音再刪除
常用的代理方法:
//錄音完成后調(diào)用 - (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag;//錄音編碼發(fā)送錯(cuò)誤時(shí)調(diào)用 - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error;
音頻
如果播放較大的音頻或者要對(duì)音頻有精確的控制則System Sound Service可能就很難滿足實(shí)際需求了,通常這種情況會(huì)選擇使用AVFoundation.framework中的AVAudioPlayer來實(shí)現(xiàn)。AVAudioPlayer可以看成一個(gè)播放器,它支持多種音頻格式,而且能夠進(jìn)行進(jìn)度、音量、播放速度等控制
AVAudioPlayer的使用比較簡(jiǎn)單:
1.初始化AVAudioPlayer對(duì)象,此時(shí)通常指定本地文件路徑。
2.設(shè)置播放器屬性,例如重復(fù)次數(shù)、音量大小等。
3.調(diào)用play方法播放。
具體實(shí)現(xiàn)代碼
#import <AVFoundation/AVFoundation.h> #define kRecordAudioFile @"myRecord.caf" @interface ViewController ()<AVAudioRecorderDelegate> { NSString *dateName; } @property (weak, nonatomic) IBOutlet UITableView *table; @property (nonatomic,strong) AVAudioRecorder *audioRecorder;//音頻錄音機(jī) @property (nonatomic,strong) AVAudioPlayer *audioPlayer;//音頻播放器,用于播放錄音文件 @property(nonatomic,strong) NSMutableArray *spaceData; @end @implementation ViewController #pragma mark - 私有方法 /** * 設(shè)置音頻會(huì)話 */ -(void)setAudioSession{ AVAudioSession *audioSession=[AVAudioSession sharedInstance]; //設(shè)置為播放和錄音狀態(tài),以便可以在錄制完之后播放錄音 [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; [audioSession setActive:YES error:nil]; } /** * 取得錄音文件設(shè)置 * * @return 錄音設(shè)置 */ -(NSDictionary *)getAudioSetting{ NSMutableDictionary *dicM=[NSMutableDictionary dictionary]; //設(shè)置錄音格式 [dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey]; //設(shè)置錄音采樣率,8000是電話采樣率,對(duì)于一般錄音已經(jīng)夠了 [dicM setObject:@(8000) forKey:AVSampleRateKey]; //設(shè)置通道,這里采用單聲道 [dicM setObject:@(1) forKey:AVNumberOfChannelsKey]; //每個(gè)采樣點(diǎn)位數(shù),分為8、16、24、32 [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey]; //是否使用浮點(diǎn)數(shù)采樣 [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey]; //....其他設(shè)置等 return dicM; } /** * 取得錄音文件保存路徑 * * @return 錄音文件路徑 */ -(NSURL *)getPlayPath:(NSString *)title{ // static int index = 0; NSString *urlStr=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; urlStr=[urlStr stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",title,kRecordAudioFile]]; NSLog(@"play file path:%@",urlStr); NSURL *url=[NSURL fileURLWithPath:urlStr]; return url; } /** * 以日期為title,來保存錄音 * * @return <#return value description#> */ - (NSString *) convertDateFromString { NSDate *date = [NSDate date]; // NSLog(@"%@--askl",date); // NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; //zzz表示時(shí)區(qū),zzz可以刪除,這樣返回的日期字符將不包含時(shí)區(qū)信息。 [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSString *destDateString = [dateFormatter stringFromDate:date]; return destDateString; }
長(zhǎng)按錄音,松開停止
- (void)setClikeSpaceState:(NSString *)aState { NSLog(@"點(diǎn)擊語(yǔ)音---"); if([aState isEqualToString:@"begin"]) { NSLog(@"begin---"); dateName = [self convertDateFromString]; //創(chuàng)建錄音文件保存路徑 NSURL *url=[self getPlayPath:dateName]; //創(chuàng)建錄音格式設(shè)置 NSDictionary *setting=[self getAudioSetting]; //創(chuàng)建錄音機(jī) NSError *error=nil; _audioRecorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error]; _audioRecorder.delegate=self; _audioRecorder.meteringEnabled=YES;//如果要監(jiān)控聲波則必須設(shè)置為YES if (![self.audioRecorder isRecording]) { [self.audioRecorder record];//首次使用應(yīng)用時(shí)如果調(diào)用record方法會(huì)詢問用戶是否允許使用麥克風(fēng) // self.timer.fireDate=[NSDate distantPast]; NSLog(@"111"); } }else { NSLog(@"end---"); /** 停止錄音*/ [self.audioRecorder stop]; /** 錄音地址*/ NSURL *url = [self getPlayPath:dateName]; /** 加載數(shù)據(jù)*/ AVAudioPlayer *audioPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; Model *model = [[Model alloc]init]; model.duration = [NSString stringWithFormat:@"%.f",audioPlayer1.duration]; model.spacePath = dateName; /** table 刷新*/ [self.spaceData addObject:model]; [self.table reloadData]; /** table 滾動(dòng)到當(dāng)前row*/ [self.table selectRowAtIndexPath:[NSIndexPath indexPathForRow:(self.spaceData.count - 1) inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop]; } }
點(diǎn)擊table 播放
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ Model *model = self.spaceData[indexPath.row]; /** 播放錄音*/ NSURL *url=[self getPlayPath:model.spacePath]; NSError *error=nil; _audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error]; _audioPlayer.numberOfLoops=0; [_audioPlayer prepareToPlay]; [self.audioPlayer play]; NSLog(@"%.0f---aaaa",_audioPlayer.duration); /** UIImage動(dòng)畫數(shù)組*/ NSMutableArray *imgData = [NSMutableArray array]; for(int i=0;i<4;i++) { UIImage *aImage = [UIImage imageNamed:[NSString stringWithFormat:@"chat_receiver_audio_playing00%d",i]]; [imgData addObject:aImage]; } TwoTableViewCell *twoCell = [self.table cellForRowAtIndexPath:indexPath]; /** 點(diǎn)擊動(dòng)畫*/ [twoCell.speak setAnimationImages:imgData]; // [twoCell.speak setAnimationRepeatCount:1]; [twoCell.speak setAnimationDuration:1]; [twoCell.speak startAnimating]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)([model.duration intValue] * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [twoCell.speak stopAnimating]; }); }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS中Label實(shí)現(xiàn)顯示不同顏色與字體的方法
這篇文章主要給大家介紹了關(guān)于在iOS中Label實(shí)現(xiàn)顯示不同顏色與字體的相關(guān)資料,文中分別介紹了利用range或者文字兩種實(shí)現(xiàn)的方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-11-11上傳IPA出現(xiàn)的錯(cuò)誤提示“application loader“上傳出錯(cuò)解決方法
這篇文章主要介紹了上傳IPA出現(xiàn)的錯(cuò)誤提示“application loader“上傳出錯(cuò)解決方法的相關(guān)資料,需要的朋友可以參考下2017-06-06講解iOS開發(fā)中UITableView列表設(shè)計(jì)的基本要點(diǎn)
這篇文章主要介紹了講解iOS開發(fā)中UITableView列表設(shè)計(jì)的基本要點(diǎn),其中對(duì)列表行操作的常用操作舉例是iOS開發(fā)中經(jīng)常用到的基礎(chǔ),需要的朋友可以參考下2016-01-01