前言
最近在做一個翻譯工具请祖,由于項(xiàng)目需要兼容 iOS 8.0订歪,所以語音識別、合成都是用的科大訊飛的肆捕。使用過程中發(fā)現(xiàn)在線轉(zhuǎn)語音不是很好刷晋,受網(wǎng)絡(luò)的影響聲音經(jīng)常斷斷續(xù)續(xù)的,而它的離線轉(zhuǎn)語音價格有太貴慎陵。而且支持的語種較少眼虱,現(xiàn)在換成系統(tǒng)自帶的語音合成、語音識別席纽。一些心得記錄一下方便需要同學(xué)查閱捏悬。
語音識別
優(yōu)點(diǎn)
- 說話時,可以一個一個字識別润梯,科大訊飛是一段話識別一次过牙,這樣的體驗(yàn)很好甥厦,可以及時響應(yīng)到用戶;
- 支持58種語種寇钉,其中包括一些地方方言(例如:粵語)刀疙;
- 識別度非常高;
缺點(diǎn)
- 只支持iOS10以上的系統(tǒng)(iOS 10以下的系統(tǒng)需要做兼容扫倡,我用的是科大訊飛)
框架主要類
#import <Foundation/Foundation.h>
#import <Speech/SFSpeechRecognitionResult.h>
#import <Speech/SFSpeechRecognitionRequest.h>
#import <Speech/SFSpeechRecognitionTask.h>
#import <Speech/SFSpeechRecognitionTaskHint.h>
#import <Speech/SFSpeechRecognizer.h>
#import <Speech/SFTranscriptionSegment.h>
#import <Speech/SFTranscription.h>
如何使用
#import "NFSpeechViewController.h"
#import <Speech/Speech.h>
@interface NFSpeechViewController ()<SFSpeechRecognitionTaskDelegate>
@property (nonatomic ,strong) SFSpeechRecognitionTask *recognitionTask;
@property (nonatomic ,strong) SFSpeechRecognizer *speechRecognizer;
@property (nonatomic ,strong) UILabel *recognizerLabel;
@end
@implementation NFSpeechViewController
- (void)dealloc {
[self.recognitionTask cancel];
self.recognitionTask = nil;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
//0.0獲取權(quán)限
//0.1在info.plist里面配置
/*
typedef NS_ENUM(NSInteger, SFSpeechRecognizerAuthorizationStatus) {
SFSpeechRecognizerAuthorizationStatusNotDetermined,
SFSpeechRecognizerAuthorizationStatusDenied,
SFSpeechRecognizerAuthorizationStatusRestricted,
SFSpeechRecognizerAuthorizationStatusAuthorized,
};
*/
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
switch (status) {
case SFSpeechRecognizerAuthorizationStatusNotDetermined:
NSLog(@"NotDetermined");
break;
case SFSpeechRecognizerAuthorizationStatusDenied:
NSLog(@"Denied");
break;
case SFSpeechRecognizerAuthorizationStatusRestricted:
NSLog(@"Restricted");
break;
case SFSpeechRecognizerAuthorizationStatusAuthorized:
NSLog(@"Authorized");
break;
default:
break;
}
}];
//1.創(chuàng)建SFSpeechRecognizer識別實(shí)例
self.speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
//2.創(chuàng)建識別請求
SFSpeechURLRecognitionRequest *request = [[SFSpeechURLRecognitionRequest alloc] initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"游子吟.mp3" ofType:nil]]];
//3.開始識別任務(wù)
self.recognitionTask = [self recognitionTaskWithRequest1:request];
}
- (SFSpeechRecognitionTask *)recognitionTaskWithRequest0:(SFSpeechURLRecognitionRequest *)request{
return [self.speechRecognizer recognitionTaskWithRequest:request resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
if (!error) {
NSLog(@"語音識別解析正確--%@", result.bestTranscription.formattedString);
}else {
NSLog(@"語音識別解析失敗--%@", error);
}
}];
}
- (SFSpeechRecognitionTask *)recognitionTaskWithRequest1:(SFSpeechURLRecognitionRequest *)request{
return [self.speechRecognizer recognitionTaskWithRequest:request delegate:self];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark- SFSpeechRecognitionTaskDelegate
// Called when the task first detects speech in the source audio
- (void)speechRecognitionDidDetectSpeech:(SFSpeechRecognitionTask *)task {
}
// Called for all recognitions, including non-final hypothesis
- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didHypothesizeTranscription:(SFTranscription *)transcription {
}
// Called only for final recognitions of utterances. No more about the utterance will be reported
- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishRecognition:(SFSpeechRecognitionResult *)recognitionResult {
NSDictionary *attributes = @{
NSFontAttributeName:[UIFont systemFontOfSize:18],
};
CGRect rect = [recognitionResult.bestTranscription.formattedString boundingRectWithSize:CGSizeMake(self.view.bounds.size.width - 100, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
self.recognizerLabel.text = recognitionResult.bestTranscription.formattedString;
self.recognizerLabel.frame = CGRectMake(50, 120, rect.size.width, rect.size.height);
}
// Called when the task is no longer accepting new audio but may be finishing final processing
- (void)speechRecognitionTaskFinishedReadingAudio:(SFSpeechRecognitionTask *)task {
}
// Called when the task has been cancelled, either by client app, the user, or the system
- (void)speechRecognitionTaskWasCancelled:(SFSpeechRecognitionTask *)task {
}
// Called when recognition of all requested utterances is finished.
// If successfully is false, the error property of the task will contain error information
- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishSuccessfully:(BOOL)successfully {
if (successfully) {
NSLog(@"全部解析完畢");
}
}
#pragma mark- getter
- (UILabel *)recognizerLabel {
if (!_recognizerLabel) {
_recognizerLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 120, self.view.bounds.size.width - 100, 100)];
_recognizerLabel.numberOfLines = 0;
_recognizerLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
_recognizerLabel.adjustsFontForContentSizeCategory = YES;
_recognizerLabel.textColor = [UIColor orangeColor];
[self.view addSubview:_recognizerLabel];
}
return _recognizerLabel;
}
@end
上面代碼是一個簡單的列子谦秧,創(chuàng)建NFSpeechViewController
的VC直接拷貝上面代碼,然后info.plist 添加用戶使用權(quán)限
Privacy - Microphone Usage Description
Privacy - Speech Recognition Usage Description
就可以使用了。
這里再重點(diǎn)說下修改本地化語言(需要識別的語言)
[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]
本地化語言的keylocaleIdentifier
可以通過 [SFSpeechRecognizer supportedLocales]
獲取到镊辕,目前一共是58種油够。
for (NSLocale *lacal in [SFSpeechRecognizer supportedLocales]) {
NSLog(@"localeIdentifier = %@,languageCode = %@, countryCode = %@",lacal.localeIdentifier,lacal.languageCode,lacal.countryCode);
}
打印日志如下:
localeIdentifier = nl-NL,languageCode = nl, countryCode = NL(荷蘭)
localeIdentifier = es-MX,languageCode = es, countryCode = MX (墨西哥)
localeIdentifier = zh-TW,languageCode = zh, countryCode = TW(中國臺灣)
localeIdentifier = fr-FR,languageCode = fr, countryCode = FR(法國)
localeIdentifier = it-IT,languageCode = it, countryCode = IT( 意大利)
localeIdentifier = vi-VN,languageCode = vi, countryCode = VN(越南)
localeIdentifier = en-ZA,languageCode = en, countryCode = ZA(南非)
localeIdentifier = ca-ES,languageCode = ca, countryCode = ES(西班牙)
localeIdentifier = es-CL,languageCode = es, countryCode = CL(智利)
localeIdentifier = ko-KR,languageCode = ko, countryCode = KR( 韓國)
localeIdentifier = ro-RO,languageCode = ro, countryCode = RO(羅馬尼亞)
localeIdentifier = fr-CH,languageCode = fr, countryCode = CH(瑞士-法語)
localeIdentifier = en-PH,languageCode = en, countryCode = PH(菲律賓)
localeIdentifier = en-CA,languageCode = en, countryCode = CA(加拿大-英語)
localeIdentifier = en-SG,languageCode = en, countryCode = SG(新加坡)
localeIdentifier = en-IN,languageCode = en, countryCode = IN(印度)
localeIdentifier = en-NZ,languageCode = en, countryCode = NZ(新西蘭)
localeIdentifier = it-CH,languageCode = it, countryCode = CH(瑞士-意大利語)
localeIdentifier = fr-CA,languageCode = fr, countryCode = CA(加拿大-法語)
localeIdentifier = da-DK,languageCode = da, countryCode = DK(丹麥)
localeIdentifier = de-AT,languageCode = de, countryCode = AT(奧地利-德語)
localeIdentifier = pt-BR,languageCode = pt, countryCode = BR(巴西-葡萄牙語)
localeIdentifier = yue-CN,languageCode = yue, countryCode = CN(中國-粵語)
localeIdentifier = zh-CN,languageCode = zh, countryCode = CN(中國-簡文)
localeIdentifier = sv-SE,languageCode = sv, countryCode = SE(瑞典-薩爾瓦多語)
localeIdentifier = es-ES,languageCode = es, countryCode = ES(西班牙-英語)
localeIdentifier = ar-SA,languageCode = ar, countryCode = SA(沙烏地阿拉伯-阿根廷語)
localeIdentifier = hu-HU,languageCode = hu, countryCode = HU(匈牙利)
localeIdentifier = fr-BE,languageCode = fr, countryCode = BE(比利時-法語)
localeIdentifier = en-GB,languageCode = en, countryCode = GB(英式英語)
localeIdentifier = ja-JP,languageCode = ja, countryCode = JP(日本)
localeIdentifier = zh-HK,languageCode = zh, countryCode = HK(中國香港-粵語)
localeIdentifier = fi-FI,languageCode = fi, countryCode = FI(芬蘭)
localeIdentifier = tr-TR,languageCode = tr, countryCode = TR(土耳其)
localeIdentifier = nb-NO,languageCode = nb, countryCode = NO(挪威)
localeIdentifier = en-ID,languageCode = en, countryCode = ID(印度尼西亞-英語)
localeIdentifier = en-SA,languageCode = en, countryCode = SA(沙烏地阿拉伯-英語)
localeIdentifier = pl-PL,languageCode = pl, countryCode = PL(波蘭)
localeIdentifier = id-ID,languageCode = id, countryCode = ID(印度尼西亞)
localeIdentifier = ms-MY,languageCode = ms, countryCode = MY(馬來西亞-蒙特塞拉特語)
localeIdentifier = el-GR,languageCode = el, countryCode = GR(希臘)
localeIdentifier = cs-CZ,languageCode = cs, countryCode = CZ(捷克共和國)
localeIdentifier = hr-HR,languageCode = hr, countryCode = HR(克羅地亞)
localeIdentifier = en-AE,languageCode = en, countryCode = AE(阿拉伯聯(lián)合酋長國-英語)
localeIdentifier = he-IL,languageCode = he, countryCode = IL(以色列)
localeIdentifier = ru-RU,languageCode = ru, countryCode = RU(俄羅斯)
localeIdentifier = de-CH,languageCode = de, countryCode = CH(瑞士-德語)
localeIdentifier = en-AU,languageCode = en, countryCode = AU(澳大利亞-英語)
localeIdentifier = de-DE,languageCode = de, countryCode = DE(德語)
localeIdentifier = nl-BE,languageCode = nl, countryCode = BE(比利時-荷蘭語)
localeIdentifier = th-TH,languageCode = th, countryCode = TH(泰國)
localeIdentifier = pt-PT,languageCode = pt, countryCode = PT(葡萄牙)
localeIdentifier = sk-SK,languageCode = sk, countryCode = SK(斯洛伐克)
localeIdentifier = en-US,languageCode = en, countryCode = US(美式英語)
localeIdentifier = en-IE,languageCode = en, countryCode = IE(愛爾蘭-英語)
localeIdentifier = es-CO,languageCode = es, countryCode = CO(哥倫比亞-西班牙語)
localeIdentifier = uk-UA,languageCode = uk, countryCode = UA(烏克蘭)
localeIdentifier = es-US,languageCode = es, countryCode = US(美國-西班牙語)
語音合成
優(yōu)點(diǎn)
- 支持的30多種語種蚁袭;
- 語速征懈、語調(diào)、音量都可以自己控制揩悄,可以自定義自己喜歡的格式卖哎;
缺點(diǎn)
- 發(fā)音效果一般理想
- 播音員默認(rèn)只有一個(訊飛可以選擇播音員發(fā)音效果很好)
框架主要類
#import<AVFoundation/AVSpeechSynthesis.h>
如何使用
1、初始化設(shè)置AVSpeechSynthesizer
AVSpeechSynthesizer *player = [[AVSpeechSynthesizer alloc]init];
player.delegate = self;
self.player = player;
AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc]initWithString:string];//設(shè)置語音內(nèi)容
utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-TW"];//設(shè)置語言 zh-CN yue-CN
utterance.rate = self.rate; //設(shè)置語速
utterance.volume = self.volume; //設(shè)置音量(0.0~1.0)默認(rèn)為1.0
utterance.pitchMultiplier = self.pitchMultiplier; //設(shè)置語調(diào) (0.5-2.0)
utterance.postUtteranceDelay = 0; //目的是讓語音合成器播放下一語句前有短暫的暫停
[player speakUtterance:utterance];
2删性、控制部分
- 停止
[self.player stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
- 暫停
[self.player pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
- 繼續(xù)播放
[self.player continueSpeaking];
3亏娜、代理部分
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance{
NSLog(@"朗讀開始");
}
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance{
NSLog(@"朗讀暫停");
}
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance{
NSLog(@"朗讀繼續(xù)");
}
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{
NSLog(@"朗讀結(jié)束");
}
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance{
}
設(shè)置聲音效果的方法,注意選英語則讀不了漢語蹬挺,但是漢語可以和英語混用维贺,這個我已經(jīng)試過了。但是讀起來比較生硬巴帮。
avspeech支持的語言種類包括:
"[AVSpeechSynthesisVoice 0x978a0b0] Language: th-TH",(泰國)
"[AVSpeechSynthesisVoice 0x977a450] Language: pt-BR",(巴西-葡萄牙語)
"[AVSpeechSynthesisVoice 0x977a480] Language: sk-SK",(斯洛伐克)
"[AVSpeechSynthesisVoice 0x978ad50] Language: fr-CA",(加拿大-法語)
"[AVSpeechSynthesisVoice 0x978ada0] Language: ro-RO",(羅馬尼亞)
"[AVSpeechSynthesisVoice 0x97823f0] Language: no-NO",(挪威)
"[AVSpeechSynthesisVoice 0x978e7b0] Language: fi-FI",(芬蘭)
"[AVSpeechSynthesisVoice 0x978af50] Language: pl-PL",(波蘭)
"[AVSpeechSynthesisVoice 0x978afa0] Language: de-DE",(德國)
"[AVSpeechSynthesisVoice 0x978e390] Language: nl-NL",(荷蘭)
"[AVSpeechSynthesisVoice 0x978b030] Language: id-ID",(印度尼西亞)
"[AVSpeechSynthesisVoice 0x978b080] Language: tr-TR",(土耳其)
"[AVSpeechSynthesisVoice 0x978b0d0] Language: it-IT",(意大利)
"[AVSpeechSynthesisVoice 0x978b120] Language: pt-PT",(葡萄牙)
"[AVSpeechSynthesisVoice 0x978b170] Language: fr-FR",(法國)
"[AVSpeechSynthesisVoice 0x978b1c0] Language: ru-RU",(俄羅斯)
"[AVSpeechSynthesisVoice 0x978b210] Language: es-MX",(墨西哥-西班牙語)
"[AVSpeechSynthesisVoice 0x978b2d0] Language: zh-HK",中文(香港)粵語
"[AVSpeechSynthesisVoice 0x978b320] Language: sv-SE",(瑞典-薩爾瓦多語)
"[AVSpeechSynthesisVoice 0x978b010] Language: hu-HU",(匈牙利)
"[AVSpeechSynthesisVoice 0x978b440] Language: zh-TW",中文(臺灣)
"[AVSpeechSynthesisVoice 0x978b490] Language: es-ES",(西班牙)
"[AVSpeechSynthesisVoice 0x978b4e0] Language: zh-CN",中文(普通話)
"[AVSpeechSynthesisVoice 0x978b530] Language: nl-BE",(比利時-荷蘭語)
"[AVSpeechSynthesisVoice 0x978b580] Language: en-GB",英語(英國)
"[AVSpeechSynthesisVoice 0x978b5d0] Language: ar-SA",(沙烏地阿拉伯-阿根廷語)
"[AVSpeechSynthesisVoice 0x978b620] Language: ko-KR",(韓國)
"[AVSpeechSynthesisVoice 0x978b670] Language: cs-CZ",(捷克共和國)
"[AVSpeechSynthesisVoice 0x978b6c0] Language: en-ZA",(南非-英語)
"[AVSpeechSynthesisVoice 0x978aed0] Language: en-AU",(澳大利亞-英語)
"[AVSpeechSynthesisVoice 0x978af20] Language: da-DK",(丹麥)
"[AVSpeechSynthesisVoice 0x978b810] Language: en-US",英語(美國)
"[AVSpeechSynthesisVoice 0x978b860] Language: en-IE",(愛爾蘭-英語)
"[AVSpeechSynthesisVoice 0x978b8b0] Language: hi-IN",(印度)
"[AVSpeechSynthesisVoice 0x978b900] Language: el-GR",(希臘)
"[AVSpeechSynthesisVoice 0x978b950] Language: ja-JP"(日本)
先記錄到這里溯泣,后面會再更新,上傳Demo榕茧。