Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[googletts] Missing service configuration #15746

Closed
Artur-Fedjukevits opened this issue Oct 13, 2023 · 5 comments · Fixed by #15747
Closed

[googletts] Missing service configuration #15746

Artur-Fedjukevits opened this issue Oct 13, 2023 · 5 comments · Fixed by #15747
Labels
bug An unexpected problem or unintended behavior of an add-on

Comments

@Artur-Fedjukevits
Copy link
Contributor

Artur-Fedjukevits commented Oct 13, 2023

Expected Behavior

Some CommunicationException should not reset the oAuthService variable.

Current Behavior

After some WARN like

2023-10-13 06:15:16.652 [WARN ] [ce.googletts.internal.GoogleCloudAPI] - Error initializing Google Cloud TTS service: An unexpected IOException occurred: java.util.concurrent.TimeoutException: Total timeout 5000 ms elapsed

or

2023-10-05 09:08:16.316 [WARN ] [ce.googletts.internal.GoogleCloudAPI] - Error initializing Google Cloud TTS service: An unexpected IOException occurred: java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Buffering capacity 2097152 exceeded

the oAuthService variable is reset to null and Google TTS returns the Missing service configuration until openHAB is restarted.

Possible Solution

public byte[] synthesizeSpeech(String text, GoogleTTSVoice voice, String codec) {
        String format = getFormatForCodec(codec);
        try {
            return synthesizeSpeechByGoogle(text, voice, format);
        } catch (AuthenticationException e  ̶|̶ ̶C̶o̶m̶m̶u̶n̶i̶c̶a̶t̶i̶o̶n̶E̶x̶c̶e̶p̶t̶i̶o̶n̶ ̶e̶) {
            logger.warn("Error initializing Google Cloud TTS service: {}", e.getMessage());
            if (oAuthService != null) {
                oAuthFactory.ungetOAuthService(GoogleTTSService.SERVICE_PID);
                oAuthService = null;
            }
            voices.clear();
        } catch (CommunicationException e) {
            logger.warn("Error initializing Google Cloud TTS service: {}", e.getMessage());
            voices.clear();
        }
        return null;
    }

Probably like this, but I'm not sure.

Your Environment

Version used: openHAB 4.0.3
Environment name and version: OpenJDK Runtime Environment Zulu17
Operating System: Ubuntu 20.04.3

@Artur-Fedjukevits Artur-Fedjukevits added the bug An unexpected problem or unintended behavior of an add-on label Oct 13, 2023
@openhab-bot
Copy link
Collaborator

This issue has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/google-tts-missing-service-configuration/149498/13

@jlaur jlaur changed the title [google tts] Missing service configuration [googletts] Missing service configuration Oct 13, 2023
@jlaur
Copy link
Contributor

jlaur commented Oct 13, 2023

I checked #14937, but actually this seems to be a long-standing bug:

} catch (AuthenticationException | CommunicationException e) {
logger.warn("Error initializing Google Cloud TTS service: {}", e.getMessage());
if (oAuthService != null) {
oAuthFactory.ungetOAuthService(GoogleTTSService.SERVICE_PID);
oAuthService = null;
}
voices.clear();
}

I would suspect that CommunicationException should be handled differently, i.e. only AuthenticationException should reset OAuth2. @lolodomo, do you agree?

EDIT: And only now do I read your suggestion, @Artur-Fedjukevits, which is exactly the same as my suggestion. So we are probably right. 😉

@jlaur
Copy link
Contributor

jlaur commented Oct 13, 2023

@Artur-Fedjukevits - is anything else logged after that? E.g. "Could not synthesize text via Google Cloud TTS Service"?

jlaur added a commit to jlaur/openhab-addons that referenced this issue Oct 13, 2023
Fixes openhab#15746

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
@jlaur
Copy link
Contributor

jlaur commented Oct 13, 2023

@jlaur
Copy link
Contributor

jlaur commented Oct 13, 2023

Some notes for future refactoring improvements:

public byte[] synthesizeSpeech(String text, GoogleTTSVoice voice, String codec) {
String format = getFormatForCodec(codec);
try {
return synthesizeSpeechByGoogle(text, voice, format);
} catch (AuthenticationException | CommunicationException e) {
logger.warn("Error initializing Google Cloud TTS service: {}", e.getMessage());
if (oAuthService != null) {
oAuthFactory.ungetOAuthService(GoogleTTSService.SERVICE_PID);
oAuthService = null;
}
voices.clear();
}
return null;
}

This method is basically a wrapper for:

private byte[] synthesizeSpeechByGoogle(String text, GoogleTTSVoice voice, String audioFormat)
throws AuthenticationException, CommunicationException {
AudioConfig audioConfig = new AudioConfig(AudioEncoding.valueOf(audioFormat), config.pitch, config.speakingRate,
config.volumeGainDb);
SynthesisInput synthesisInput = new SynthesisInput(text);
VoiceSelectionParams voiceSelectionParams = new VoiceSelectionParams(voice.getLocale().getLanguage(),
voice.getLabel(), SsmlVoiceGender.valueOf(voice.getSsmlGender()));
SynthesizeSpeechRequest request = new SynthesizeSpeechRequest(audioConfig, synthesisInput,
voiceSelectionParams);
HttpRequestBuilder builder = HttpRequestBuilder.postTo(SYTNHESIZE_SPEECH_URL)
.withHeader(HttpHeader.AUTHORIZATION.name(), getAuthorizationHeader())
.withContent(gson.toJson(request), MimeTypes.Type.APPLICATION_JSON.name());
try {
SynthesizeSpeechResponse synthesizeSpeechResponse = gson.fromJson(builder.getContentAsString(),
SynthesizeSpeechResponse.class);
if (synthesizeSpeechResponse == null) {
return null;
}
byte[] encodedBytes = synthesizeSpeechResponse.getAudioContent().getBytes(StandardCharsets.UTF_8);
return Base64.getDecoder().decode(encodedBytes);
} catch (JsonSyntaxException e) {
// do nothing
} catch (IOException e) {
throw new CommunicationException(String.format("An unexpected IOException occurred: %s", e.getMessage()));
}
return null;
}

Outcomes:

  • Line 365: AuthenticationException
  • Line 375: Return null
  • Line 381: Return null
  • Line 383: CommunicationException

The error handling is inconsistent. The wrapper handles OAuth2 and logging, and converts exceptions into returning null. If already null because of JSON deserialization or missing response, nothing will be logged. In all cases we end throwing here:

byte[] audio = apiImpl.synthesizeSpeech(trimmedText, (GoogleTTSVoice) voice, requestedFormat.getCodec());
if (audio == null) {
throw new TTSException("Could not synthesize text via Google Cloud TTS Service");
}

Suggestions:

  • synthesizeSpeechByGoogle should check response before calling fromJson. If null or empty, don't call. In this case fromJson will never return null.
  • synthesizeSpeechByGoogle should never return null. If response is missing or cannot be deserialized, throw CommunicationException (or custom exception). Chain JsonSyntaxException.
  • The wrapper synthesizeSpeech should only handle OAuth2 and in this case rethrow AuthenticationException. Don't log.
  • In GoogleTTSService catch exceptions and rethrow as TTSException. Log if needed, I don't know if throwing this exception will already be logged by the framework.

lolodomo pushed a commit that referenced this issue Oct 16, 2023
Fixes #15746

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
jlaur added a commit that referenced this issue Oct 16, 2023
Fixes #15746

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
querdenker2k pushed a commit to querdenker2k/openhab-addons that referenced this issue Oct 21, 2023
Fixes openhab#15746

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
querdenker2k pushed a commit to querdenker2k/openhab-addons that referenced this issue Oct 29, 2023
Fixes openhab#15746

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
Signed-off-by: querdenker2k <querdenker2k@gmx.de>
austvik pushed a commit to austvik/openhab-addons that referenced this issue Mar 27, 2024
Fixes openhab#15746

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
Signed-off-by: Jørgen Austvik <jaustvik@acm.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug An unexpected problem or unintended behavior of an add-on
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants