iOS语音合成,语音阅读《AVFoundation》->AVSpeechSynthesizer使用方法介绍

iOS语音合成,语音阅读《AVFoundation》 - 图1

效果图,图片找的网上的

我们有时候在读书软件上可以发现语音朗读功能(读起来好像没什么感情)。其实这个利用iOS系统api就可以实现。下面就通过一个语音朗读文字的demo来讲解该功能的实现步骤。

1:AVSpeechSynthesizer介绍

实现该功能核心的部件就是AVSpeechSynthesizer。

  1. NS_CLASS_AVAILABLE_IOS(7_0)
  2. @interface AVSpeechSynthesizer : NSObject

大家看到了么,iOS7.0之后才出现了AVSpeechSynthesizer。AVSpeechSynthesizer具有以下属性:

  1. //代理方法
  2. @property(nonatomic, weak, nullable) id<AVSpeechSynthesizerDelegate> delegate;
  3. //是否正在朗读(只读)
  4. @property(nonatomic, readonly, getter=isSpeaking) BOOL speaking;
  5. //是否已经暂停(只读)
  6. @property(nonatomic, readonly, getter=isPaused) BOOL paused;

支持的方法如下:

  1. //朗读方法,需要一个AVSpeechUtterance类型参数
  2. - (void)speakUtterance:(AVSpeechUtterance *)utterance;
  3. //停止朗读,会清理掉当前正在执行朗读操作的队列
  4. - (BOOL)stopSpeakingAtBoundary:(AVSpeechBoundary)boundary;
  5. //暂停朗读,这里面需要传递一个AVSpeechBoundary类型参数,两种选择,是立即停止还是读完这个单词再停止。
  6. - (BOOL)pauseSpeakingAtBoundary:(AVSpeechBoundary)boundary;
  7. //继续朗读
  8. - (BOOL)continueSpeaking;

上面提到代理方法,还记得不?下面就是相关的代理方法:

  1. //开始朗读的代理方法
  2. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance;
  3. //结束朗读的代理方法
  4. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance;
  5. //暂停朗读的代理方法
  6. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance;
  7. //继续朗读的代理方法
  8. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance;
  9. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didCancelSpeechUtterance:(AVSpeechUtterance *)utterance;
  10. ////将要播放的语音文字代理方法
  11. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance;

2:AVSpeechUtterance介绍

除了核心的AVSpeechSynthesizer,还有一个非常关键的成员就是AVSpeechUtterance,要是想把声音读出来并且设置和声音有关的一些属性,你离不开它。AVSpeechUtterance主要包含以下属性:

  1. //需要用什么语言来朗读,系统提供了很多语言选项,如果有中文,一定要选择中文语言,要不然读不出来。
  2. @property(nonatomic, retain, nullable) AVSpeechSynthesisVoice *voice;
  3. //朗读的内容
  4. @property(nonatomic, readonly) NSString *speechString;
  5. //朗读的内容NSAttributedString 格式
  6. @property(nonatomic, readonly) NSAttributedString *attributedSpeechString API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));
  7. /* Setting these values after a speech utterance has been enqueued will have no effect. */
  8. ////语速0.0f~1.0f
  9. @property(nonatomic) float rate; // Values are pinned between AVSpeechUtteranceMinimumSpeechRate and AVSpeechUtteranceMaximumSpeechRate.
  10. //声音的音调0.5f~2.0f
  11. @property(nonatomic) float pitchMultiplier; // [0.5 - 2] Default = 1
  12. @property(nonatomic) float volume; // [0-1] Default = 1
  13. //播放下下一句话的时候有多长时间的延迟
  14. @property(nonatomic) NSTimeInterval preUtteranceDelay; // Default is 0.0
  15. //开始播放之前需要等待多久
  16. @property(nonatomic) NSTimeInterval postUtteranceDelay; // Default is 0.0

支持的方法如下:

  1. //初始化类方法,需要传一个字符串进去
  2. + (instancetype)speechUtteranceWithString:(NSString *)string;
  3. //初始化类方法,需要一个NSAttributedString类型字符串
  4. + (instancetype)speechUtteranceWithAttributedString:(NSAttributedString *)string API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));
  5. //初始化对象方法,需要一个字符串作为参数
  6. - (instancetype)initWithString:(NSString *)string;
  7. //初始化对象方法,需要一个NSAttributedString类型字符串
  8. - (instancetype)initWithAttributedString:(NSAttributedString *)string API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));

上面提到的语言类型,主要由以下几种:

  1. Arabic (ar-SA)
  2. Chinese (zh-CN, zh-HK, zh-TW)
  3. Czech (cs-CZ)
  4. Danish (da-DK)
  5. Dutch (nl-BE, nl-NL)
  6. English (en-AU, en-GB, en-IE, en-US, en-ZA)
  7. Finnish (fi-FI)
  8. French (fr-CA, fr-FR)
  9. German (de-DE)
  10. Greek (el-GR)
  11. Hebrew (he-IL)
  12. Hindi (hi-IN)
  13. Hungarian (hu-HU)
  14. Indonesian (id-ID)
  15. Italian (it-IT)
  16. Japanese (ja-JP)
  17. Korean (ko-KR)
  18. Norwegian (no-NO)
  19. Polish (pl-PL)
  20. Portuguese (pt-BR, pt-PT)
  21. Romanian (ro-RO)
  22. Russian (ru-RU)
  23. Slovak (sk-SK)
  24. Spanish (es-ES, es-MX)
  25. Swedish (sv-SE)
  26. Thai (th-TH)
  27. Turkish (tr-TR)

代码实现:

相关知识点介绍完毕之后,下面就是具体的代码实现:

  1. #import "ViewController.h"
  2. #import <AVFoundation/AVFoundation.h>
  3. @interface ViewController ()<AVSpeechSynthesizerDelegate>
  4. @property(nonatomic,strong) NSArray * strArray;
  5. @property(nonatomic,strong) NSArray *voiceArray;
  6. @property(nonatomic,strong) AVSpeechSynthesizer *synthesizer;
  7. @property (weak, nonatomic) IBOutlet UILabel *speechLabel;
  8. @property (weak, nonatomic) IBOutlet UIButton *controlButton;
  9. @property (nonatomic,assign)BOOL isPlay;
  10. @end
  11. @implementation ViewController
  12. - (void)viewDidLoad {
  13. [super viewDidLoad];
  14. self.strArray =@[@"单车欲问边,",
  15. @"属国过居延。",
  16. @"征蓬出汉塞,",
  17. @"归雁入胡天。",
  18. @"大漠孤烟直,",
  19. @"长河落日圆,",
  20. @"萧关逢候骑,",
  21. @"都护在燕然。",
  22. @"A solitary carriage to the frontiers bound,",
  23. @"An envoy with no retinue around,",
  24. @"A drifting leaf from proud Cathy,",
  25. @"With geese back north on a hordish day.",
  26. @"A smoke hangs straight on the desert vast,",
  27. @"A sun sits round on the endless stream.",
  28. @"A horseman bows by a fortress passed:",
  29. @"The general’s at the north extreme!"];
  30. self.voiceArray = @[[AVSpeechSynthesisVoice voiceWithLanguage:@"en-GB"],[AVSpeechSynthesisVoice voiceWithLanguage:@"en-US"]];
  31. self.synthesizer = [[AVSpeechSynthesizer alloc]init];
  32. self.isPlay = NO;
  33. [self.controlButton setTitle:@"pause" forState:UIControlStateNormal];
  34. self.synthesizer.delegate = self;
  35. for (int i = 0; i < self.strArray.count; i ++) {
  36. AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc]initWithString:self.strArray[i]];
  37. //需要读的语言
  38. if (i < 8) {
  39. utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
  40. }
  41. else{
  42. utterance.voice = self.voiceArray[i%2];
  43. }
  44. //语速0.0f~1.0f
  45. utterance.rate = 0.5f;
  46. //声音的音调0.5f~2.0f
  47. utterance.pitchMultiplier = 0.8f;
  48. //播放下下一句话的时候有多长时间的延迟
  49. utterance.postUtteranceDelay = 0.1f;
  50. //上一句之前需要多久
  51. utterance.preUtteranceDelay = 0.5f;
  52. //音量
  53. utterance.volume = 1.0f;
  54. //开始播放
  55. [self.synthesizer speakUtterance:utterance];
  56. }
  57. }
  58. //开始朗读的代理方法
  59. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance{
  60. NSLog(@"didStartSpeechUtterance->%@",utterance.speechString);
  61. }
  62. //结束朗读的代理方法
  63. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{
  64. NSLog(@"didFinishSpeechUtterance->%@",utterance.speechString);
  65. }
  66. //暂停朗读的代理方法
  67. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance{
  68. NSLog(@"didPauseSpeechUtterance->%@",utterance.speechString);
  69. }
  70. //继续朗读的代理方法
  71. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance{
  72. NSLog(@"didContinueSpeechUtterance->%@",utterance.speechString);
  73. }
  74. //取消朗读的代理方法
  75. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didCancelSpeechUtterance:(AVSpeechUtterance *)utterance{
  76. NSLog(@"didCancelSpeechUtterance->%@",utterance.speechString);
  77. }
  78. //将要播放的语音文字
  79. - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance{
  80. NSLog(@"willSpeakRangeOfSpeechString->characterRange.location = %zd->characterRange.length = %zd->utterance.speechString= %@",characterRange.location,characterRange.length,utterance.speechString);
  81. self.speechLabel.text = utterance.speechString;
  82. }
  83. - (IBAction)buttonClick:(id)sender {
  84. self.isPlay = !self.isPlay;
  85. if (self.isPlay) {
  86. [self.controlButton setTitle:@"play" forState:UIControlStateNormal];
  87. [self.synthesizer pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
  88. }
  89. else{
  90. [self.controlButton setTitle:@"pause" forState:UIControlStateNormal];
  91. [self.synthesizer continueSpeaking];
  92. }
  93. }
  94. - (void)didReceiveMemoryWarning {
  95. [super didReceiveMemoryWarning];
  96. // Dispose of any resources that can be recreated.
  97. }
  98. @end