AVSpeechSynthesizer的问题,任何解决方法?

我正在使用AVSpeechSynthesizer播放文本。 我有一系列的发言。

NSMutableArray *utterances = [[NSMutableArray alloc] init]; for (NSString *text in textArray) { AVSpeechUtterance *welcome = [[AVSpeechUtterance alloc] initWithString:text]; welcome.rate = 0.25; welcome.voice = voice; welcome.pitchMultiplier = 1.2; welcome.postUtteranceDelay = 0.25; [utterances addObject:welcome]; } lastUtterance = [utterances lastObject]; for (AVSpeechUtterance *utterance in utterances) { [speech speakUtterance:utterance]; } 

我有一个取消button来停止说话。 当我说第一个话语时点击取消button时,讲话停止,并清除队列中的所有话语。 如果在说出第一个话语(即第二话语)之后按下取消button,则停止话语不会冲洗话语队列。 我正在使用的代码是:

  [speech stopSpeakingAtBoundary:AVSpeechBoundaryImmediate]; 

有人可以确认,如果这是一个错误的API或我使用API​​不正确? 如果这是一个错误,有没有解决这个问题的解决方法?

很可能是一个错误,因为委托方法合成器didCancelSpeechUserrance没有被调用后的第一个话语;

解决方法是链接话语,而不是把它们放在一个数组中,并一次排队。

使用委托方法合成器didFinishSpeechUtterance增加一个数组指针,并说出该数组中的下一个文本。 然后,当试图停止讲话时,在尝试说出下一个文本之前,设置一个在此委托方法中被选中的BOOL。

例如:

1)在正在进行语音合成的视图控制器中实现协议

 #import <UIKit/UIKit.h> @import AVFoundation; @interface ViewController : UIViewController <AVSpeechSynthesizerDelegate> @end 

2)实例化AVSpeechSynthesizer并将其委托设置为self

 speechSynthesizer = [AVSpeechSynthesizer new]; speechSynthesizer.delegate = self; 

3)使用发言计数器,在开始发言时设置为零

4)用一组文本说话

 textArray = @[@"Mary had a little lamb, its fleece", @"was white as snow", @"and everywhere that Mary went", @"that sheep was sure to go"]; 

5)添加委托方法didFinishSpeechUtterance从文本数组中发出下一个话语并增加发言计数器

 - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{ if(utteranceCounter < utterances.count){ AVSpeechUtterance *utterance = utterances[utteranceCounter]; [synthesizer speakUtterance:utterance]; utteranceCounter++; } } 

5)停止发言,将发言计数器设置为文本数组的计数,并尝试让合成器停止

 utteranceCounter = utterances.count; BOOL speechStopped = [speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate]; if(!speechStopped){ [speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryWord]; } 

6)再次说话时,将话语计数器重置为零

我find了一个解决方法:

 - (void)stopSpeech { if([_speechSynthesizer isSpeaking]) { [_speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate]; AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:@""]; [_speechSynthesizer speakUtterance:utterance]; [_speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate]; } } 

调用stopSpeakingAtBoundary:排队一个空的话语并调用stopSpeakingAtBoundary:再次停止并清理队列。

这里的所有答案都失败了,我想到的是停止合成器,然后重新实例化它:

 - (void)stopSpeech { if([_speechSynthesizer isSpeaking]) { [_speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate]; _speechSynthesizer = [AVSpeechSynthesizer new]; _speechSynthesizer.delegate = self; } } 

我做了类似于SPA提到的东西。 从循环中一次一个地发言。 这是主意

 NSMutableArray *arr; //array of NSStrings, declared as property AVSpeechUtterance *currentUtterence; //declared as property AVSpeechSynthesizer *synthesizer; //property - (void) viewDidLoad:(BOOL)anim { [super viewDidLoad:anim]; synthesizer = [[AVSpeechSynthesizer alloc]init]; //EDIT -- Added the line below synthesizer.delegate = self; arr = [self populateArrayWithString]; //generates strings to speak } //assuming one thread will call this - (void) speakNext { if (arr.count > 0) { NSString *str = [arr objectAtIndex:0]; [arr removeObjectAtIndex:0]; currentUtterence = [[AVSpeechUtterance alloc] initWithString:str]; //EDIT -- Commentted out the line below //currentUtterence.delegate = self; [synthesizer speakUtterance:utteranc]; } } - (void)speechSynthesizer:(AVSpeechSynthesizer *)avsSynthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance { if ([synthesizer isEqual:avsSynthesizer] && [utterance isEqual:currentUtterence]) [self speakNext]; } - (IBOutlet) userTappedCancelledButton:(id)sender { //EDIT <- replaced the object the method gets called on. [synthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate]; [arr removeAllObjects]; } 

即使在didFinishSpeechUtterance方法中链接了话语,didCancelSpeechUserrance也不能与相同的AVSpeechSynthesizer对象一起使用。

 -(void)speakInternal { speech = [[AVSpeechSynthesizer alloc] init]; speech.delegate = self; [speech speakUtterance:[utterances objectAtIndex:position++]]; } 

在speakInternal中,我多次创buildAVSpeechSynthesizer对象以确保didCancelSpeechUtterance正常工作。 一种解决方法。