diff --git a/texttospeech/cloud-client/resources/example.ssml b/texttospeech/cloud-client/resources/example.ssml new file mode 100644 index 00000000000..c27fd399967 --- /dev/null +++ b/texttospeech/cloud-client/resources/example.ssml @@ -0,0 +1,4 @@ +123 Street Ln, Small Town, IL 12345 USA +1 Jenny St & Number St, Tutone City, CA 86753 +1 Piazza del Fibonacci, 12358 Pisa, Italy + \ No newline at end of file diff --git a/texttospeech/cloud-client/resources/example.txt b/texttospeech/cloud-client/resources/example.txt new file mode 100644 index 00000000000..9cd7d74db36 --- /dev/null +++ b/texttospeech/cloud-client/resources/example.txt @@ -0,0 +1,3 @@ +123 Street Ln, Small Town, IL 12345 USA +1 Jenny St & Number St, Tutone City, CA 86753 +1 Piazza del Fibonacci, 12358 Pisa, Italy diff --git a/texttospeech/cloud-client/resources/expected_example.mp3 b/texttospeech/cloud-client/resources/expected_example.mp3 new file mode 100644 index 00000000000..407b85f7f5d Binary files /dev/null and b/texttospeech/cloud-client/resources/expected_example.mp3 differ diff --git a/texttospeech/cloud-client/src/main/java/com/example/texttospeech/SsmlAddresses.java b/texttospeech/cloud-client/src/main/java/com/example/texttospeech/SsmlAddresses.java new file mode 100644 index 00000000000..bb04ce39624 --- /dev/null +++ b/texttospeech/cloud-client/src/main/java/com/example/texttospeech/SsmlAddresses.java @@ -0,0 +1,143 @@ +/* + * Copyright 2019 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.texttospeech; + +// [START tts_ssml_address_imports] +// Imports the Google Cloud client library +import com.google.cloud.texttospeech.v1.AudioConfig; +import com.google.cloud.texttospeech.v1.AudioEncoding; +import com.google.cloud.texttospeech.v1.SsmlVoiceGender; +import com.google.cloud.texttospeech.v1.SynthesisInput; +import com.google.cloud.texttospeech.v1.SynthesizeSpeechResponse; +import com.google.cloud.texttospeech.v1.TextToSpeechClient; +import com.google.cloud.texttospeech.v1.VoiceSelectionParams; +import com.google.common.html.HtmlEscapers; +import com.google.protobuf.ByteString; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +// [END tts_ssml_address_imports] + + +/** + * Google Cloud TextToSpeech API sample application. + * Example usage: mvn package exec:java + * -Dexec.mainClass='com.example.texttospeech.SsmlAddresses + */ +public class SsmlAddresses { + + // [START tts_ssml_address_audio] + /** + * Generates synthetic audio from a String of SSML text. + * + * Given a string of SSML text and an output file name, this function + * calls the Text-to-Speech API. The API returns a synthetic audio + * version of the text, formatted according to the SSML commands. This + * function saves the synthetic audio to the designated output file. + * + * @param ssmlText: String of tagged SSML text + * @param outfile: String name of file under which to save audio output + * @throws Exception on errors while closing the client + * + */ + public static void ssmlToAudio(String ssmlText, String outFile) + throws Exception { + // Instantiates a client + try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()) { + // Set the ssml text input to synthesize + SynthesisInput input = SynthesisInput.newBuilder() + .setSsml(ssmlText) + .build(); + + // Build the voice request, select the language code ("en-US") and + // the ssml voice gender ("male") + VoiceSelectionParams voice = VoiceSelectionParams.newBuilder() + .setLanguageCode("en-US") + .setSsmlGender(SsmlVoiceGender.MALE) + .build(); + + // Select the audio file type + AudioConfig audioConfig = AudioConfig.newBuilder() + .setAudioEncoding(AudioEncoding.MP3) + .build(); + + // Perform the text-to-speech request on the text input with the selected voice parameters and + // audio file type + SynthesizeSpeechResponse response = textToSpeechClient.synthesizeSpeech(input, voice, + audioConfig); + + // Get the audio contents from the response + ByteString audioContents = response.getAudioContent(); + + // Write the response to the output file + try (OutputStream out = new FileOutputStream(outFile)) { + out.write(audioContents.toByteArray()); + System.out.println("Audio content written to file " + outFile); + } + } + } + // [END tts_ssml_address_audio] + + // [START tts_ssml_address_ssml] + /** + * Generates SSML text from plaintext. + * + * Given an input filename, this function converts the contents of the input text file + * into a String of tagged SSML text. This function formats the SSML String so that, + * when synthesized, the synthetic audio will pause for two seconds between each line + * of the text file. This function also handles special text characters which might + * interfere with SSML commands. + * + * @param inputfile: String name of plaintext file + * @throws IOException on files that don't exist + * @return a String of SSML text based on plaintext input. + * + */ + public static String textToSsml(String inputFile) + throws Exception { + + // Read lines of input file + String rawLines = new String(Files.readAllBytes(Paths.get(inputFile))); + + // Replace special characters with HTML Ampersand Character Codes + // These codes prevent the API from confusing text with SSML tags + // For example, '<' --> '<' and '&' --> '&' + String escapedLines = HtmlEscapers.htmlEscaper().escape(rawLines); + + // Convert plaintext to SSML + // Tag SSML so that there is a 2 second pause between each address + String expandedNewline = escapedLines.replaceAll("\\n","\n"); + String ssml = "" + expandedNewline + ""; + + // Return the concatenated String of SSML + return ssml; + } + // [START tts_ssml_address_ssml] + + // [START tts_ssml_address_test] + public static void main(String... args) throws Exception { + // test example address file + String inputFile = "resources/example.txt"; + String outFile = "resources/example.mp3"; + + String ssml = textToSsml(inputFile); + ssmlToAudio(ssml, outFile); + } + // [END tts_ssml_address_test] +} \ No newline at end of file diff --git a/texttospeech/cloud-client/src/test/java/com/example/texttospeech/SsmlAddressesIT.java b/texttospeech/cloud-client/src/test/java/com/example/texttospeech/SsmlAddressesIT.java new file mode 100644 index 00000000000..e9d0d34a4c4 --- /dev/null +++ b/texttospeech/cloud-client/src/test/java/com/example/texttospeech/SsmlAddressesIT.java @@ -0,0 +1,80 @@ +/* + * Copyright 2019 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.texttospeech; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.protobuf.ByteString; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests for SsmlAddresses sample. + */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class SsmlAddressesIT { + + private static String OUTPUT = "output.mp3"; + private static String TEXT_FILE = "resources/example.txt"; + private static String SSML_FILE = "resources/example.ssml"; + + private ByteArrayOutputStream bout; + private PrintStream out; + private File outputFile; + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @Test + public void testTextToSsml() throws Exception { + // Act + String ssml = SsmlAddresses.textToSsml(TEXT_FILE); + String expectedSsml = new String(Files.readAllBytes(Paths.get(SSML_FILE))); + + // Assert + assertThat(ssml).contains(expectedSsml); + } + + @Test + public void testSsmlToAudio() throws Exception { + // Act + String ssml = new String(Files.readAllBytes(Paths.get(SSML_FILE))); + SsmlAddresses.ssmlToAudio(ssml, OUTPUT); + + // Assert + outputFile = new File(OUTPUT); + assertThat(outputFile.isFile()).isTrue(); + String got = bout.toString(); + assertThat(got).contains("Audio content written to file output.mp3"); + + // After + outputFile.delete(); + } +} \ No newline at end of file