Demo下載地址
最近在項目開發中,需要將語音識別轉換成文本的功能。研究了下科大訊飛,附上Demo分享給大家。
研發前先得做一些准備。
1、注冊科大訊飛開發者帳號(http://www.xfyun.cn)
2、下載開發平台(iOS、或Android,或其他)所需要的SDK(SDK包含:說明文檔、SDK即iflyMSC.framework、Demo)
3、項目中添加SDK(添加時,先將SDK復制粘貼到項目文件,再通過addframe的方法添加到項目引用),及相關聯的framework
添加方法:TARGETS-Build Phases-Link Binary With Libraries-"+"-Choose frameworks and libraries to add-add other,或選擇對應的framework-add
4、使用時要添加對應的頭文件
特別說明:
1、使用SDK關聯的APPID存在於下載的Demo中,如果SDK有替換的話APPID應該跟著一起替換。
2、添加其他framework:
libz.tbd
libc++.tbd
CoreGraphics.framework
QuartzCore.framework
AddressBook.framework
CoreLocation.framework
UIKit.framework
AudioToolbox.framework
Foundation.framework
SystemConfiguration.framework
AVFoundation.framework
CoreTelephoney.framework
3、Bitcode屬性設置為NO(TARGETS-Build Settings-Build Options-Enable Bitcode-NO)
4、在使用前,務必在AppDelegate的方法中"
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {}"進行初始化操作。
5、需要有網絡的情況下才能使用。
如圖
下載的科大訊飛SDK文件
Demo中的APPID
添加SDK,及添加關聯framework
設置Bitcode屬性為 NO
語音轉文件實現代碼
- .h文件
-
- #import
-
- //導入頭文件
- #import"iflyMSC.framework/Headers/IFlyMSC.h"
- #import"iflyMSC.framework/Headers/IFlySpeechUtility.h"
- #import"iflyMSC/IFlySpeechConstant.h"
-
-
- #pragmamark-初始化參數類
-
- /**************************************************************************/
-
- @interfaceIATConfig:NSObject
-
- +(IATConfig*)sharedInstance;
-
- +(NSString*)mandarin;
- +(NSString*)cantonese;
- +(NSString*)henanese;
- +(NSString*)chinese;
- +(NSString*)english;
- +(NSString*)lowSampleRate;
- +(NSString*)highSampleRate;
- +(NSString*)isDot;
- +(NSString*)noDot;
-
-
- /**
- 以下參數,需要通過iFlySpeechRecgonizer進行設置
- */
- @property(nonatomic,strong)NSString*speechTimeout;
- @property(nonatomic,strong)NSString*vadEos;
- @property(nonatomic,strong)NSString*vadBos;
-
- @property(nonatomic,strong)NSString*language;
- @property(nonatomic,strong)NSString*accent;
-
- @property(nonatomic,strong)NSString*dot;
- @property(nonatomic,strong)NSString*sampleRate;
-
-
- /**
- 以下參數無需設置不必關
- */
- @property(nonatomic,assign)BOOLhaveView;
- @property(nonatomic,strong)NSArray*accentIdentifer;
- @property(nonatomic,strong)NSArray*accentNickName;
-
- @end
-
- /**************************************************************************/
-
-
- #pragmamark-語音聽寫類
-
- @interfaceVoiceConversion:NSObject
-
- ///啟動初始化語音程序
- +(void)VoiceInitialize;
-
-
- ///開始錄音
- -(void)voiceStart:(void(^)(BOOLisStart))startListening
- speechBegin:(void(^)(void))begin
- speechEnd:(void(^)(void))end
- speechError:(void(^)(BOOLisSuccess))error
- speechResult:(void(^)(NSString*text))result
- speechVolume:(void(^)(intvolume))volume;
-
- ///取消錄音
- -(void)voiceCancel;
-
- ///停止錄音
- -(void)voiceStop;
-
- @end
- .m文件
-
- #import"VoiceConversion.h"
-
- #pragmamark-初始化參數類
-
- /**************************************************************************/
-
- staticNSString*constPUTONGHUA=@"mandarin";
- staticNSString*constYUEYU=@"cantonese";
- staticNSString*constHENANHUA=@"henanese";
- staticNSString*constENGLISH=@"en_us";
- staticNSString*constCHINESE=@"zh_cn";
-
- @implementationIATConfig
-
- -(id)init
- {
- self=[superinit];
- if(self)
- {
- [selfdefaultSetting];
- returnself;
- }
- returnnil;
- }
-
- +(IATConfig*)sharedInstance
- {
- staticIATConfig*instance=nil;
- staticdispatch_once_tpredict;
- dispatch_once(&predict,^{
- instance=[[IATConfigalloc]init];
- });
- returninstance;
- }
-
- -(void)defaultSetting
- {
- _speechTimeout=@"30000";
- _vadEos=@"3000";
- _vadBos=@"3000";
- _dot=@"1";
- _sampleRate=@"16000";
- _language=CHINESE;
- _accent=PUTONGHUA;
- _haveView=NO;//默認是不dai界面的
- _accentNickName=[[NSArrayalloc]initWithObjects:@"粵語",@"普通話",@"河南話",@"英文",nil];
- }
-
- +(NSString*)mandarin
- {
- returnPUTONGHUA;
- }
-
- +(NSString*)cantonese
- {
- returnYUEYU;
- }
-
- +(NSString*)henanese
- {
- returnHENANHUA;
- }
-
- +(NSString*)chinese
- {
- returnCHINESE;
- }
-
- +(NSString*)english
- {
- returnENGLISH;
- }
-
- +(NSString*)lowSampleRate
- {
- return@"8000";
- }
-
- +(NSString*)highSampleRate
- {
- return@"16000";
- }
-
- +(NSString*)isDot
- {
- return@"1";
- }
-
- +(NSString*)noDot
- {
- return@"0";
- }
-
- @end
-
- /**************************************************************************/
-
- #pragmamark-語音聽寫類
-
- staticNSString*constVoiceAPPID=@"572016e4";
- staticNSString*constVoiceTimeOut=@"20000";
-
- @interfaceVoiceConversion()
-
- @property(nonatomic,strong)NSMutableString*resultText;
- @property(nonatomic,strong)IFlySpeechRecognizer*iFlySpeechRecognizer;
-
- @property(nonatomic,copy)void(^beginSpeech)(void);
- @property(nonatomic,copy)void(^endSpeech)(void);
- @property(nonatomic,copy)void(^errorSpeech)(BOOLisSuccess);
- @property(nonatomic,copy)void(^resultSpeech)(NSString*text);
- @property(nonatomic,copy)void(^volumeSpeech)(intvolume);
-
- @end
-
- @implementationVoiceConversion
-
- #pragmamark初始化------------
-
- ///啟動初始化語音程序
- +(void)VoiceInitialize
- {
- //設置sdk的log等級,log保存在下面設置的工作路徑中
- [IFlySettingsetLogFile:LVL_ALL];
-
- //打開輸出在console的log開關
- [IFlySettingshowLogcat:YES];
-
- //設置sdk的工作路徑
- NSArray*paths=NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
- NSString*cachePath=[pathsobjectAtIndex:0];
- [IFlySettingsetLogFilePath:cachePath];
-
- //Appid是應用的身份信息,具有唯一性,初始化時必須要傳入Appid。初始化是一個異步過程,可放在App啟動時執行初始化,具體代碼可以參照Demo的MSCAppDelegate.m。未初始化時使用服務,一般會返回錯誤碼10111.
- NSString*initString=[[NSStringalloc]initWithFormat:@"appid=%@",VoiceAPPID];
- [IFlySpeechUtilitycreateUtility:initString];
- }
-
- #pragmamark實例化------------
-
- -(void)dealloc
- {
- [selfvoiceCancel];
- }
-
- -(NSMutableString*)resultText
- {
- if(!_resultText)
- {
- _resultText=[[NSMutableStringalloc]init];
- }
-
- return_resultText;
- }
-
- -(IFlySpeechRecognizer*)iFlySpeechRecognizer
- {
- if(_iFlySpeechRecognizer==nil)
- {
- _iFlySpeechRecognizer=[IFlySpeechRecognizersharedInstance];
-
- [_iFlySpeechRecognizersetParameter:@""forKey:[IFlySpeechConstantPARAMS]];
- //設置聽寫模式
- [_iFlySpeechRecognizersetParameter:@"iat"forKey:[IFlySpeechConstantIFLY_DOMAIN]];
- }
-
- return_iFlySpeechRecognizer;
- }
-
- -(void)initializeVoice
- {
- self.iFlySpeechRecognizer.delegate=self;
-
- IATConfig*instance=[IATConfigsharedInstance];
-
- //設置最長錄音時間
- [self.iFlySpeechRecognizersetParameter:instance.speechTimeoutforKey:[IFlySpeechConstantSPEECH_TIMEOUT]];
- //設置後端點
- [self.iFlySpeechRecognizersetParameter:instance.vadEosforKey:[IFlySpeechConstantVAD_EOS]];
- //設置前端點
- [self.iFlySpeechRecognizersetParameter:instance.vadBosforKey:[IFlySpeechConstantVAD_BOS]];
- //網絡等待時間
- [self.iFlySpeechRecognizersetParameter:@"20000"forKey:[IFlySpeechConstantNET_TIMEOUT]];
-
- //設置采樣率,推薦使用16K
- [self.iFlySpeechRecognizersetParameter:instance.sampleRateforKey:[IFlySpeechConstantSAMPLE_RATE]];
-
- if([instance.languageisEqualToString:[IATConfigchinese]])
- {
- //設置語言
- [self.iFlySpeechRecognizersetParameter:instance.languageforKey:[IFlySpeechConstantLANGUAGE]];
- //設置方言
- [self.iFlySpeechRecognizersetParameter:instance.accentforKey:[IFlySpeechConstantACCENT]];
- }
- elseif([instance.languageisEqualToString:[IATConfigenglish]])
- {
- [self.iFlySpeechRecognizersetParameter:instance.languageforKey:[IFlySpeechConstantLANGUAGE]];
- }
-
- //設置是否返回標點符號
- [self.iFlySpeechRecognizersetParameter:instance.dotforKey:[IFlySpeechConstantASR_PTT]];
- }
-
- #pragmamark語音聽寫方法------------
-
- ///開始錄音
- -(void)voiceStart:(void(^)(BOOLisStart))startListening
- speechBegin:(void(^)(void))begin
- speechEnd:(void(^)(void))end
- speechError:(void(^)(BOOLisSuccess))error
- speechResult:(void(^)(NSString*text))result
- speechVolume:(void(^)(intvolume))volume
- {
- [self.resultTextsetString:@""];
-
- //回調設置
- self.beginSpeech=[begincopy];
- self.endSpeech=[endcopy];
- self.errorSpeech=[errorcopy];
- self.resultSpeech=[resultcopy];
- self.volumeSpeech=[volumecopy];
-
-
- //初始化設置
- [selfinitializeVoice];
-
- [self.iFlySpeechRecognizercancel];
-
- //設置音頻來源為麥克風
- [self.iFlySpeechRecognizersetParameter:IFLY_AUDIO_SOURCE_MICforKey:@"audio_source"];
-
- //設置聽寫結果格式為json
- [self.iFlySpeechRecognizersetParameter:@"json"forKey:[IFlySpeechConstantRESULT_TYPE]];
-
- //保存錄音文件,保存在sdk工作路徑中,如未設置工作路徑,則默認保存在library/cache下
- [self.iFlySpeechRecognizersetParameter:@"asr.pcm"forKey:[IFlySpeechConstantASR_AUDIO_PATH]];
-
- BOOLisStart=[self.iFlySpeechRecognizerstartListening];
- if(startListening)
- {
- //如果開始錄音失敗,可能是上次請求未結束,暫不支持多路並發
- startListening(isStart);
- }
- }
-
- ///取消聽寫
- -(void)voiceCancel
- {
- [self.iFlySpeechRecognizercancel];
- }
-
- ///停止錄音
- -(void)voiceStop
- {
- [self.iFlySpeechRecognizerstopListening];
- }
-
- #pragmamarkIFlySpeechRecognizerDelegate------------
-
- /**
- 識別結果返回代理
- @param:results識別結果
- @param:isLast表示是否最後一次結果
- */
- -(void)onResults:(NSArray*)resultsisLast:(BOOL)isLast
- {
- NSMutableString*resultString=[[NSMutableStringalloc]init];
- NSDictionary*dic=results[0];
- for(NSString*keyindic)
- {
- [resultStringappendFormat:@"%@",key];
- }
- NSString*resultFromJson=[[selfclass]stringFromJson:resultString];
- NSString*resultTextTemp=[NSStringstringWithFormat:@"%@%@",self.resultText,resultFromJson];
- [self.resultTextsetString:resultTextTemp];
- if(isLast)
- {
- if(self.resultSpeech)
- {
- //去掉最後一個句號
- NSRangerange=[self.resultTextrangeOfString:@"。"options:NSBackwardsSearch];
- if(range.location!=NSNotFound)
- {
- resultTextTemp=[self.resultTextsubstringToIndex:range.location];
- [self.resultTextsetString:resultTextTemp];
- }
- self.resultSpeech(self.resultText);
- }
- }
-
- [selfvoiceCancel];
- }
-
- /**
- 識別會話結束返回代理
- @paramerror錯誤碼,error.errorCode=0表示正常結束,非0表示發生錯誤。
- */
- -(void)onError:(IFlySpeechError*)error
- {
- if(self.errorSpeech)
- {
- BOOLisSuccess=(0==error.errorCode);
- self.errorSpeech(isSuccess);
- }
- }
-
- /**
- 停止錄音回調
- */
- -(void)onEndOfSpeech
- {
- if(self.endSpeech)
- {
- self.endSpeech();
- }
- }
-
- /**
- 開始識別回調
- */
- -(void)onBeginOfSpeech
- {
- if(self.beginSpeech)
- {
- self.beginSpeech();
- }
- }
-
- /**
- 音量回調函數volume0-30
- */
- -(void)onVolumeChanged:(int)volume
- {
- if(self.volumeSpeech)
- {
- self.volumeSpeech(volume);
- }
- }
-
-
- #pragmamark解析方法------------
-
- /**************************************************************************/
-
- /**
- 解析命令詞返回的結果
- */
- +(NSString*)stringFromAsr:(NSString*)params;
- {
- NSMutableString*resultString=[[NSMutableStringalloc]init];
- NSString*inputString=nil;
-
- NSArray*array=[paramscomponentsSeparatedByString:@"\n"];
-
- for(intindex=0;index {
- NSRangerange;
- NSString*line=[arrayobjectAtIndex:index];
-
- NSRangeidRange=[linerangeOfString:@"id="];
- NSRangenameRange=[linerangeOfString:@"name="];
- NSRangeconfidenceRange=[linerangeOfString:@"confidence="];
- NSRangegrammarRange=[linerangeOfString:@"grammar="];
-
- NSRangeinputRange=[linerangeOfString:@"input="];
-
- if(confidenceRange.length==0||grammarRange.length==0||inputRange.length==0)
- {
- continue;
- }
-
- //checknomatch
- if(idRange.length!=0)
- {
- NSUIntegeridPosX=idRange.location+idRange.length;
- NSUIntegeridLength=nameRange.location-idPosX;
- range=NSMakeRange(idPosX,idLength);
-
- NSString*subString=[linesubstringWithRange:range];
- NSCharacterSet*subSet=[NSCharacterSetwhitespaceAndNewlineCharacterSet];
- NSString*idValue=[subStringstringByTrimmingCharactersInSet:subSet];
- if([idValueisEqualToString:@"nomatch"])
- {
- return@"";
- }
- }
-
- //GetConfidenceValue
- NSUIntegerconfidencePosX=confidenceRange.location+confidenceRange.length;
- NSUIntegerconfidenceLength=grammarRange.location-confidencePosX;
- range=NSMakeRange(confidencePosX,confidenceLength);
-
- NSString*score=[linesubstringWithRange:range];
-
- NSUIntegerinputStringPosX=inputRange.location+inputRange.length;
- NSUIntegerinputStringLength=line.length-inputStringPosX;
-
- range=NSMakeRange(inputStringPosX,inputStringLength);
- inputString=[linesubstringWithRange:range];
-
- [resultStringappendFormat:@"%@置信度%@\n",inputString,score];
- }
-
- returnresultString;
- }
-
- /**
- 解析聽寫json格式的數據
- params例如:
- {"sn":1,"ls":true,"bg":0,"ed":0,"ws":[{"bg":0,"cw":[{"w":"白日","sc":0}]},{"bg":0,"cw":[{"w":"依山","sc":0}]},{"bg":0,"cw":[{"w":"盡","sc":0}]},{"bg":0,"cw":[{"w":"黃河入海流","sc":0}]},{"bg":0,"cw":[{"w":"。","sc":0}]}]}
- */
- +(NSString*)stringFromJson:(NSString*)params
- {
- if(params==NULL)
- {
- returnnil;
- }
-
- NSMutableString*tempStr=[[NSMutableStringalloc]init];
- //返回的格式必須為utf8的,否則發生未知錯誤
- NSData*dataJSON=[paramsdataUsingEncoding:NSUTF8StringEncoding];
- NSDictionary*resultDic=[NSJSONSerializationJSONObjectWithData:dataJSONoptions:kNilOptionserror:nil];
-
- if(resultDic!=nil)
- {
- NSArray*wordArray=[resultDicobjectForKey:@"ws"];
-
- for(inti=0;i<[wordArraycount];i++)
- {
- NSDictionary*wsDic=[wordArrayobjectAtIndex:i];
- NSArray*cwArray=[wsDicobjectForKey:@"cw"];
-
- for(intj=0;j<[cwArraycount];j++)
- {
- NSDictionary*wDic=[cwArrayobjectAtIndex:j];
- NSString*str=[wDicobjectForKey:@"w"];
- [tempStrappendString:str];
- }
- }
- }
-
- returntempStr;
- }
-
-
- /**
- 解析語法識別返回的結果
- */
- +(NSString*)stringFromABNFJson:(NSString*)params
- {
- if(params==NULL)
- {
- returnnil;
- }
- NSMutableString*tempStr=[[NSMutableStringalloc]init];
- NSData*dataJSON=[paramsdataUsingEncoding:NSUTF8StringEncoding];
- NSDictionary*resultDic=[NSJSONSerializationJSONObjectWithData:dataJSONoptions:kNilOptionserror:nil];
-
- NSArray*wordArray=[resultDicobjectForKey:@"ws"];
- for(inti=0;i<[wordArraycount];i++)
- {
- NSDictionary*wsDic=[wordArrayobjectAtIndex:i];
- NSArray*cwArray=[wsDicobjectForKey:@"cw"];
-
- for(intj=0;j<[cwArraycount];j++)
- {
- NSDictionary*wDic=[cwArrayobjectAtIndex:j];
- NSString*str=[wDicobjectForKey:@"w"];
- NSString*score=[wDicobjectForKey:@"sc"];
- [tempStrappendString:str];
- [tempStrappendFormat:@"置信度:%@",score];
- [tempStrappendString:@"\n"];
- }
- }
-
- returntempStr;
- }
-
- /**************************************************************************/
-
- @end
使用
- 初始化方法
- ///啟動初始化語音程序
- +(void)VoiceInitialize
- {
- //設置sdk的log等級,log保存在下面設置的工作路徑中
- [IFlySettingsetLogFile:LVL_ALL];
-
- //打開輸出在console的log開關
- [IFlySettingshowLogcat:YES];
-
- //設置sdk的工作路徑
- NSArray*paths=NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
- NSString*cachePath=[pathsobjectAtIndex:0];
- [IFlySettingsetLogFilePath:cachePath];
-
- //Appid是應用的身份信息,具有唯一性,初始化時必須要傳入Appid。初始化是一個異步過程,可放在App啟動時執行初始化,具體代碼可以參照Demo的MSCAppDelegate.m。未初始化時使用服務,一般會返回錯誤碼10111.
- NSString*initString=[[NSStringalloc]initWithFormat:@"appid=%@",VoiceAPPID];
- [IFlySpeechUtilitycreateUtility:initString];
- }
-
- 初始化調用
- -(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions
- {
- //Overridepointforcustomizationafterapplicationlaunch.
-
- [VoiceConversionVoiceInitialize];
-
- returnYES;
- }
- #import"VoiceConversion.h"
-
- @interfaceViewController()
-
- @property(nonatomic,strong)VoiceConversion*voiceConversion;
- @property(nonatomic,strong)UILabel*messageLabel;
-
- @end
-
- @implementationViewController
-
- -(void)viewDidLoad{
- [superviewDidLoad];
- //Doanyadditionalsetupafterloadingtheview,typicallyfromanib.
-
- UIBarButtonItem*startItem=[[UIBarButtonItemalloc]initWithTitle:@"start"style:UIBarButtonItemStyleDonetarget:selfaction:@selector(startItemClick:)];
- UIBarButtonItem*stopItem=[[UIBarButtonItemalloc]initWithTitle:@"stop"style:UIBarButtonItemStyleDonetarget:selfaction:@selector(stopItemClick:)];
- UIBarButtonItem*cancelItem=[[UIBarButtonItemalloc]initWithTitle:@"cancel"style:UIBarButtonItemStyleDonetarget:selfaction:@selector(cancelItemClick:)];
- self.navigationItem.rightBarButtonItems=@[startItem,stopItem,cancelItem];
-
- self.title=@"科大訊飛語音";
-
- [selfsetUI];
- }
-
- -(void)didReceiveMemoryWarning{
- [superdidReceiveMemoryWarning];
- //Disposeofanyresourcesthatcanberecreated.
- }
-
- #pragmamark-視圖
-
- -(void)setUI
- {
- if([selfrespondsToSelector:@selector(setEdgesForExtendedLayout:)])
- {
- [selfsetEdgesForExtendedLayout:UIRectEdgeNone];
- }
-
- self.messageLabel=[[UILabelalloc]initWithFrame:CGRectMake(10.0,10.0,CGRectGetWidth(self.view.bounds)-10.0*2,40.0)];
- [self.viewaddSubview:self.messageLabel];
- self.messageLabel.backgroundColor=[UIColorcolorWithWhite:0.5alpha:0.3];
- self.messageLabel.textAlignment=NSTextAlignmentCenter;
- }
-
- #pragmamark-響應
-
- -(void)startItemClick:(UIBarButtonItem*)item
- {
- ViewController__weak*weakSelf=self;
- [self.voiceConversionvoiceStart:^(BOOLisStart){
-
- NSLog(@"1start");
-
- if(isStart)
- {
- weakSelf.messageLabel.text=@"正在錄音";
- }
- else
- {
- weakSelf.messageLabel.text=@"啟動識別服務失敗,請稍後重試";
- }
- }speechBegin:^{
- NSLog(@"2begin");
- }speechEnd:^{
- NSLog(@"3end");
- }speechError:^(BOOLisSuccess){
- NSLog(@"4error");
- }speechResult:^(NSString*text){
- NSLog(@"5result");
- weakSelf.messageLabel.text=text;
- }speechVolume:^(intvolume){
- NSLog(@"6volume");
- NSString*volumeString=[NSStringstringWithFormat:@"音量:%d",volume];
- weakSelf.messageLabel.text=volumeString;
- }];
- }
-
- -(void)stopItemClick:(UIBarButtonItem*)item
- {
- [self.voiceConversionvoiceStop];
-
- self.messageLabel.text=@"停止錄音";
- }
-
- -(void)cancelItemClick:(UIBarButtonItem*)item
- {
- [self.voiceConversionvoiceCancel];
-
- self.messageLabel.text=@"取消識別";
- }
-
- #pragmamark-getter
-
- -(VoiceConversion*)voiceConversion
- {
- if(!_voiceConversion)
- {
- _voiceConversion=[[VoiceConversionalloc]init];
- }
-
- return_voiceConversion;
- }
-
- @end