首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >AVSpeechSynthesizer的问题,有什么解决办法吗?

AVSpeechSynthesizer的问题,有什么解决办法吗?
EN

Stack Overflow用户
提问于 2013-10-30 02:34:10
回答 5查看 10.8K关注 0票数 10

我正在使用AVSpeechSynthesizer播放文本。我有一大堆的话要弹。

代码语言:javascript
运行
复制
    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];
    }

我有个取消按钮要停止讲话。当我在第一次发言时单击“取消”按钮时,该演讲停止,它将清除队列中的所有语句。如果我在第一次发言(即第二次发言)之后按下“取消”按钮,那么停止讲话并不会刷新语音队列。我为此使用的代码是:

代码语言:javascript
运行
复制
  [speech stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];

是否有人能确认这是API中的错误,还是我使用了错误的API?如果它是一个bug,有什么解决办法来解决这个问题吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-11-18 17:32:19

很可能是一个错误,因为委托方法合成器didCancelSpeechUtterance不会在第一次发言之后调用;

一种解决办法是将话语串起来,而不是将它们放在一个数组中,然后立即排队。

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

例如:

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

代码语言:javascript
运行
复制
#import <UIKit/UIKit.h>
@import AVFoundation;
@interface ViewController : UIViewController <AVSpeechSynthesizerDelegate>

@end

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

代码语言:javascript
运行
复制
speechSynthesizer   = [AVSpeechSynthesizer new];
speechSynthesizer.delegate = self;

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

4)使用一系列的文本来发言。

代码语言:javascript
运行
复制
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,从文本数组中发出下一个语句,并增加话语计数器。

代码语言:javascript
运行
复制
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{
    if(utteranceCounter < utterances.count){
        AVSpeechUtterance *utterance = utterances[utteranceCounter];
        [synthesizer speakUtterance:utterance];
        utteranceCounter++;
    }
}

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

代码语言:javascript
运行
复制
utteranceCounter = utterances.count;

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

6)当再次发言时,将话语计数器重置为零。

票数 5
EN

Stack Overflow用户

发布于 2014-03-06 15:40:02

我找到了一个解决办法:

代码语言:javascript
运行
复制
- (void)stopSpeech
{
    if([_speechSynthesizer isSpeaking]) {
        [_speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
        AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:@""];
        [_speechSynthesizer speakUtterance:utterance];
        [_speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];    
    }
}

调用stopSpeakingAtBoundary:,对空语句进行排队,并再次调用stopSpeakingAtBoundary:来停止和清理队列。

票数 24
EN

Stack Overflow用户

发布于 2016-09-10 03:24:13

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

代码语言:javascript
运行
复制
- (void)stopSpeech
{
    if([_speechSynthesizer isSpeaking]) {
        [_speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
        _speechSynthesizer = [AVSpeechSynthesizer new];
        _speechSynthesizer.delegate = self;
    }
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19672814

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档