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

vij*_*yst 9 xcode cocoa-touch ios

我正在使用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];
    }
Run Code Online (Sandbox Code Playgroud)

我有一个取消按钮停止说话.当我说出第一个话语时单击取消按钮时,语音停止并清除队列中的所有话语.如果我在说出第一个话语(即第二个话语)后按下取消按钮,则停止讲话不会刷新话语队列.我正在使用的代码是:

  [speech stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
Run Code Online (Sandbox Code Playgroud)

有人可以确认这是API中的错误还是我错误地使用了API?如果是错误,是否有解决此问题的解决方法?

小智 23

我找到了一个解决方法:

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

呼叫stopSpeakingAtBoundary:,排空空话,然后stopSpeakingAtBoundary:再次呼叫停止并清理队列.

  • 这真是这个问题的最佳答案. (2认同)

SPA*_*SPA 5

很可能是一个错误,因为委托方法合成器didCancelSpeechUtterance在第一次发声后没有被调用;

解决方法是链接话语而不是将它们放在一个数组中并立即排队.

使用委托方法syntizer didFinishSpeechUtterance来递增数组指针并说出该数组中的下一个文本.然后,在尝试停止语音时,在尝试说出下一个文本之前设置在此委托方法中检查的BOOL.

例如:

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

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

@end
Run Code Online (Sandbox Code Playgroud)

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

speechSynthesizer   = [AVSpeechSynthesizer new];
speechSynthesizer.delegate = self;
Run Code Online (Sandbox Code Playgroud)

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"];
Run Code Online (Sandbox Code Playgroud)

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

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

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

utteranceCounter = utterances.count;

BOOL speechStopped =  [speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
if(!speechStopped){
    [speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryWord];
}
Run Code Online (Sandbox Code Playgroud)

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


tec*_*yle 5

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

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

  • 太感谢了 !这个解决方案绝对对我有用! (3认同)