前言
為了滿足需求, 關(guān)愛老年人, 在文章詳情頁添加字體放大縮小功能之后, 又要增加語音報告功能。在中國人口老年化的大背景下, 總結(jié) iOS 語音播報功能, 寫下了這篇文章。

正文
文本轉(zhuǎn)語音技術(shù), 也叫TTS, 是Text To Speech的縮寫.
一、語音播報相關(guān)屬性介紹
內(nèi)容文本轉(zhuǎn)語音播報, 需要使用到AVFoundation框架中的 AVSpeechSynthesizer 和 AVSpeechUtterance 這兩個關(guān)鍵類。
// 合成器 控制播放,暫停
@property(nonatomic,strong) AVSpeechSynthesizer * synthesizerAV;
// 實(shí)例化發(fā)聲的對象,及朗讀的內(nèi)容,可以控制說話的語速 等
@property(nonatomic,strong) AVSpeechUtterance *utterance;
按住command點(diǎn)擊AVSpeechSynthesizer可以看到
//將發(fā)聲的對象添加到合成器隊(duì)列中, 開始語音播報
- (void)speakUtterance:(AVSpeechUtterance *)utterance;
//停止結(jié)束語音播報
- (BOOL)stopSpeakingAtBoundary:(AVSpeechBoundary)boundary;
//暫停語音播報
- (BOOL)pauseSpeakingAtBoundary:(AVSpeechBoundary)boundary;
//繼續(xù)語音播報
- (BOOL)continueSpeaking;
AVSpeechSynthesizerDelegate代理方法
#pragma mark - AVSpeechSynthesizerDelegate
//已經(jīng)開始
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance{
}
//已經(jīng)說完
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{
//如果朗讀要循環(huán)朗讀,可以在這里再次調(diào)用朗讀方法
//[_avSpeaker speakUtterance:utterance];
}
//已經(jīng)暫停
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance{
}
//已經(jīng)繼續(xù)說話
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance{
}
//已經(jīng)取消說話
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didCancelSpeechUtterance:(AVSpeechUtterance *)utterance{
}
//將要說某段話
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance{
}
按住command點(diǎn)擊AVSpeechSynthesizer可以看到
//實(shí)例化發(fā)聲的對象,設(shè)置需要發(fā)聲內(nèi)容
+ (instancetype)speechUtteranceWithString:(NSString *)string;
//設(shè)置合成語音的語言 defaults to your system language
@property(nonatomic, retain, nullable) AVSpeechSynthesisVoice *voice;
//設(shè)置語速 0.0f~1.0f
//Values are pinned between AVSpeechUtteranceMinimumSpeechRate and AVSpeechUtteranceMaximumSpeechRate.
@property(nonatomic) float rate;
//聲音的音調(diào) 0.5f~2.0f [0.5 - 2] Default = 1
@property(nonatomic) float pitchMultiplier;
//設(shè)置朗讀的音量 [0-1] Default = 1
@property(nonatomic) float volume;
語言種類 : Language
ar-SA 沙特阿拉伯(阿拉伯文)
en-ZA, 南非(英文)
nl-BE, 比利時(荷蘭文)
en-AU, 澳大利亞(英文)
th-TH, 泰國(泰文)
de-DE, 德國(德文)
en-US, 美國(英文)
pt-BR, 巴西(葡萄牙文)
pl-PL, 波蘭(波蘭文)
en-IE, 愛爾蘭(英文)
el-GR, 希臘(希臘文)
id-ID, 印度尼西亞(印度尼西亞文)
sv-SE, 瑞典(瑞典文)
tr-TR, 土耳其(土耳其文)
pt-PT, 葡萄牙(葡萄牙文)
ja-JP, 日本(日文)
ko-KR, 南朝鮮(朝鮮文)
hu-HU, 匈牙利(匈牙利文)
cs-CZ, 捷克共和國(捷克文)
da-DK, 丹麥(丹麥文)
es-MX, 墨西哥(西班牙文)
fr-CA, 加拿大(法文)
nl-NL, 荷蘭(荷蘭文)
fi-FI, 芬蘭(芬蘭文)
es-ES, 西班牙(西班牙文)
it-IT, 意大利(意大利文)
he-IL, 以色列(希伯萊文,阿拉伯文)
no-NO, 挪威(挪威文)
ro-RO, 羅馬尼亞(羅馬尼亞文)
zh-HK, 香港(中文)
zh-TW, 臺灣(中文)
sk-SK, 斯洛伐克(斯洛伐克文)
zh-CN, 中國(中文)
ru-RU, 俄羅斯(俄文)
en-GB, 英國(英文)
fr-FR, 法國(法文)
hi-IN 印度(印度文)
二、文章詳情H5界面內(nèi)容語音播報使用
①添加框架, 導(dǎo)入頭文件, 設(shè)置代理

導(dǎo)入頭文件
#import<AVFoundation/AVFoundation.h>
設(shè)置代理(非必需設(shè)置項(xiàng),看需求)
@interface ViewController ()<AVSpeechSynthesizerDelegate>
②創(chuàng)建對象
// 合成器 控制播放,暫停
@property(nonatomic,strong) AVSpeechSynthesizer * synthesizerAV;
// 實(shí)例化發(fā)聲的對象,及朗讀的內(nèi)容,可以控制說話的語速 等
@property(nonatomic,strong) AVSpeechUtterance *utterance;
這地方模擬H5界面文章詳情內(nèi)容
//模擬服務(wù)器返回?cái)?shù)據(jù)
NSString *content = @"<p> 日前,湖北郵政公司黨組對全省郵政企業(yè)30個紅旗支局黨支部開展了示范引領(lǐng)“回頭看”檢查,檢查指標(biāo)涉及黨員“三亮”載體覆蓋率、業(yè)務(wù)收入增幅等10項(xiàng)黨建工作及經(jīng)營管理指標(biāo)。檢查結(jié)果顯示,全省郵政企業(yè)30個紅旗黨支部示范引領(lǐng)作用十分明顯,主要表現(xiàn)為三個方面:一是黨建工作真正落地。全省郵政企業(yè)30個紅旗支局黨支部扎實(shí)開展了“三亮三比三創(chuàng)”活動,充分發(fā)揮了黨員的先鋒模范作用,黨員勞動競賽完成率均在100%以上,黨員“三亮”載體覆蓋率均為100%。同時,各支部明確了特色支部的建設(shè)方向,加強(qiáng)了黨員隊(duì)伍建設(shè)。二是業(yè)務(wù)收入快速增長。全省郵政企業(yè)30個紅旗支局黨支部所在支局共實(shí)現(xiàn)業(yè)務(wù)收入2。15億元,凈增業(yè)務(wù)收入2660萬元,平均增幅16。5%,其中武漢市江夏區(qū)城關(guān)支局黨支部所在支局業(yè)務(wù)收入增幅達(dá)46%、荊門市沙洋縣沈集支局黨支部所在支局業(yè)務(wù)收入增幅達(dá)37。95%、孝感市肖港支局黨支部所在支局業(yè)務(wù)收入增幅達(dá)30。2%,收入增長勢頭喜人;人均勞動生產(chǎn)率達(dá)到37。26萬元,其中孝感市三汊支局黨支部、胡金店支局黨支部、肖港支局黨支部所在支局勞動生產(chǎn)率分別達(dá)到59萬元、58。4萬元、57。5萬元,業(yè)績表現(xiàn)突出。三是儲蓄余額規(guī)??焖贁U(kuò)張。全省郵政企業(yè)30個紅旗支局黨支部所在支局累計(jì)儲蓄余額規(guī)模達(dá)到198。49億元,1-7月份新增儲蓄余額過億的有11個支局,其中武漢市韓家墩支局黨支部、鐘家村支局黨支部以及青山區(qū)鋼花支局黨支部所在支局新增儲蓄余額分別達(dá)到4。89億元、2。51億元和2。12億元,儲蓄余額增長勢頭強(qiáng)勁。<br></p>";
//去除HTML標(biāo)簽處理
NSString *contentStr = [self filterHTML:content];
//將Unicode轉(zhuǎn)變?yōu)樽址畷r"."->"。",需要替換字符
NSString *contentString = [contentStr stringByReplacingOccurrencesOfString:@"。" withString:@"."];
在服務(wù)器返回的內(nèi)容content中有HTML標(biāo)簽需要去除,使用下面方法 :
//處理HTML標(biāo)簽
-(NSString *)filterHTML:(NSString *)html
{
NSScanner * scanner = [NSScanner scannerWithString:html];
NSString * text = nil;
while([scanner isAtEnd]==NO)
{
[scanner scanUpToString:@"<" intoString:nil];
[scanner scanUpToString:@">" intoString:&text];
html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>",text] withString:@""];
}
return html;
}
創(chuàng)建語音播報對象
_synthesizerAV = [[AVSpeechSynthesizer alloc] init];
_utterance = [AVSpeechUtterance speechUtteranceWithString:contentString];
③設(shè)置相關(guān)屬性
// 語速 0.0f~1.0f AVSpeechUtteranceMaximumSpeechRate / 4.0f;
_utterance.rate = 0.45f;
// 聲音的音調(diào) 0.5f~2.0f
_utterance.pitchMultiplier = 0.8f;
//設(shè)置合成語音的語言 defaults to your system language zh-TW zh-CN
_utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
//設(shè)置朗讀的音量 [0-1] Default = 1
_utterance.volume = 0.8;
④開始、暫停/繼續(xù)、結(jié)束
開始文章內(nèi)容朗讀播報
[_synthesizerAV speakUtterance:_utterance];
暫停朗讀播報
//暫停朗讀
//AVSpeechBoundaryImmediate 立即停止
//AVSpeechBoundaryWord 當(dāng)前詞結(jié)束后停止
[_synthesizerAV pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
繼續(xù)朗讀播報
[_synthesizerAV continueSpeaking];
結(jié)束朗讀播報
//AVSpeechBoundaryImmediate 立即停止
//AVSpeechBoundaryWord 當(dāng)前詞結(jié)束后停止
[_synthesizerAV stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
⑤實(shí)現(xiàn)后臺播放
1.在配置里設(shè)置

2.在AppDelegate.m里添加代碼
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error = nil;
[session setCategory:AVAudioSessionCategoryPlayback error:&error];
[session setActive:YES error:&error];
[Bmob registerWithAppKey:BMOB_AppID];
return YES;
}
小知識點(diǎn)
iOS7之后才有該功能, 不過現(xiàn)在Xcode 8最低支持就是iOS 8.0了。
后記
除了選擇系統(tǒng)的語音播報, 當(dāng)然你還可以選擇訊飛的文字轉(zhuǎn)語音技術(shù),不過它受網(wǎng)絡(luò)的影響比較大,而且離線轉(zhuǎn)語音價格比較貴,最便宜的要8000RMB/2000裝機(jī)量。
還有一種是使用 百度語音SDK
①下載離在線合成語音包

②記住這3個key

③查看官方示例Demo, 實(shí)現(xiàn)播放和設(shè)置聲音代碼
-(void)configureSDK{
NSLog(@"TTS version info: %@", [BDSSpeechSynthesizer version]);
[BDSSpeechSynthesizer setLogLevel:BDS_PUBLIC_LOG_VERBOSE];
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerDelegate:self];
[self configureOnlineTTS];
[self configureOfflineTTS];
}
// 配置在線
-(void)configureOnlineTTS{
//#error "Set api key and secret key"
[[BDSSpeechSynthesizer sharedInstance] setApiKey:@"e7QA3FWob8EbzLDP7I6fCtcY" withSecretKey:@"17d90e1974d0bcb31725245f96718e73"];
}
// 配置離線
-(void)configureOfflineTTS{
NSString offlineEngineSpeechData = [[NSBundle mainBundle] pathForResource:@"Chinese_Speech_Female" ofType:@"dat"];
NSString offlineEngineTextData = [[NSBundle mainBundle] pathForResource:@"Chinese_Text" ofType:@"dat"];
NSString offlineEngineEnglishSpeechData = [[NSBundle mainBundle] pathForResource:@"English_Speech_Female" ofType:@"dat"];
NSString offlineEngineEnglishTextData = [[NSBundle mainBundle] pathForResource:@"English_Text" ofType:@"dat"];
NSString offlineEngineLicenseFile = [[NSBundle mainBundle] pathForResource:@"offline_engine_tmp_license" ofType:@"dat"];
//#error "set offline engine license"
NSError err = [[BDSSpeechSynthesizer sharedInstance] loadOfflineEngine:offlineEngineTextData speechDataPath:offlineEngineSpeechData licenseFilePath:offlineEngineLicenseFile withAppCode:@"9353239"]; //
if (err) {
return;
}
err = [[BDSSpeechSynthesizer sharedInstance] loadEnglishDataForOfflineEngine:offlineEngineEnglishTextData speechData:offlineEngineEnglishSpeechData];
if (err) {
return;
}
}
// 播放失敗
-(void)synthesizerErrorOccurred:(NSError *)error speaking:(NSInteger)SpeakSentence synthesizing:(NSInteger)SynthesizeSentence{
[[BDSSpeechSynthesizer sharedInstance] cancel];
}
// 合成參數(shù)設(shè)置
// 聲音
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt:BDS_SYNTHESIZER_SPEAKER_FEMALE] forKey:BDS_SYNTHESIZER_PARAM_SPEAKER ];
// 音量
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt:5] forKey:BDS_SYNTHESIZER_PARAM_VOLUME];
// 音速
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt:5] forKey:BDS_SYNTHESIZER_PARAM_SPEED];
// 音調(diào)
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt:5] forKey:BDS_SYNTHESIZER_PARAM_PITCH];
// 壓縮
[[BDSSpeechSynthesizer sharedInstance] setSynthesizerParam:[NSNumber numberWithInt: BDS_SYNTHESIZER_AUDIO_ENCODE_MP3_16K] forKey:BDS_SYNTHESIZER_PARAM_AUDIO_ENCODING ];

我是楚簡約,感謝您的閱讀,
喜歡就點(diǎn)個贊唄,“?喜歡”,
鼓勵一下,你在看,我就繼續(xù)寫~
非簡書用戶,可以點(diǎn)右上角的三個“...”,然后"在Safari中打開”,就可以點(diǎn)贊咯~