Reputation: 21
I have created an AVSpeechSynthesizer
and started playing an AVSpeechUtterance
. This works fine. If the user presses a button I pause the synthesizer. This also works. However, when I try to restart the synthesizer with the continueSpeaking
method, nothing happens. If I check the isSpeaking
property it is still NO
. How can I get the audio to start playing again from where it left off?
AVSpeechSynthesizer *synthesizer_;
synthesizer_ = [[AVSpeechSynthesizer alloc] init];
synthesizer_.delegate = self;
- (void)textToSpeech{
AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc]initWithString:itemText];
utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:localeCode];
utterance.rate = UTTERANCE_RATE;
utterance.preUtteranceDelay = itemDelayTimeInterval;
[synthesizer_ speakUtterance:utterance];
}
- (IBAction)pauseButtonPressed:(id)sender {
if (synthesizer_.isSpeaking) {
[synthesizer_ pauseSpeakingAtBoundary:AVSpeechBoundaryWord];
}
else{
[synthesizer_ continueSpeaking];
}
}
Upvotes: 2
Views: 2403
Reputation: 1144
I found this very nice and easy to use AVSpeechSynthesizer library on GitHub.
It manages multiple utterances properly using a NSMutableArray. As well as implementing pausing, stopping and continuing properly.
https://github.com/quentinhayot/QHSpeechSynthesizerQueue
I updated the -(void)next function to correct an issue when isSpeaking:
-(void)next{
if (_play && [_queue count] > 0 && ![_synthesizer isSpeaking]){
AVSpeechUtterance *utterance = [_queue firstObject];
[_queue removeObjectAtIndex:0];
[_synthesizer speakUtterance:utterance];
}
//added this to fix issue when already speaking
else if ([_synthesizer isSpeaking]) {
NSLog(@"AVSpeech isSpeaking");
[NSTimer scheduledTimerWithTimeInterval:0.5f target:self selector:@selector(tmrNextDelay_Method:) userInfo:nil repeats:NO];
}
}
-(void)tmrNextDelay_Method:(NSTimer *)timer{
[self next];
}
Upvotes: 0
Reputation: 288
Just start with isPaused and it will works fine:
NOTE: Use AVSpeechBoundaryImmediate instead of AVSpeechBoundaryWord for better results.
- (IBAction)pauseButtonPressed:(id)sender {
if (synthesizer_.isPaused) {
[synthesizer_ continueSpeaking];
}
else{
[synthesizer_ pauseSpeakingAtBoundary: AVSpeechBoundaryImmediate];
}
}
Upvotes: 1
Reputation: 2396
Try to use follow code
-(void)stopSpeechReading
{
if([synthesize isSpeaking]) {
NSLog(@"Reading has been stopped");
[synthesize stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:@""];
[synthesize speakUtterance:utterance];
[synthesize stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
}
}
-(void)pauseSpeechReading
{
if([synthesize isSpeaking]) {
NSLog(@"Reading paused");
[synthesize pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:@""];
[synthesize speakUtterance:utterance];
[synthesize pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
}
}
-(void)resumeSpeechReading
{
NSLog(@"Reading resumed");
[synthesize continueSpeaking];
}
Upvotes: 0
Reputation: 11
Your original code is:
if (synthesizer_.isSpeaking) {
Try this instead:
if (![synthesizer_ isPaused])
Reason:
From the docs: speaking A Boolean value that indicates whether the synthesizer is speaking. (read-only)
@property(nonatomic, readonly, getter=isSpeaking) BOOL speaking
Discussion
Returns YES
if the synthesizer is speaking or has utterances enqueued to speak, even if it is currently paused. Returns NO
if the synthesizer has finished speaking all utterances in its queue or if it has not yet been given an utterance to speak.
Availability
Available in iOS 7.0 and later.
Declared In
AVSpeechSynthesis.h
So, if you use this property, and the speech is paused, this property can be true and your speech continue code will not run.
Upvotes: 1