diff --git a/samples/snippets/resources/example.ssml b/samples/snippets/resources/example.ssml new file mode 100644 index 00000000..1e20716f --- /dev/null +++ b/samples/snippets/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/samples/snippets/resources/example.txt b/samples/snippets/resources/example.txt new file mode 100644 index 00000000..9cd7d74d --- /dev/null +++ b/samples/snippets/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/samples/snippets/ssml_addresses.py b/samples/snippets/ssml_addresses.py new file mode 100644 index 00000000..b30cfce0 --- /dev/null +++ b/samples/snippets/ssml_addresses.py @@ -0,0 +1,112 @@ +# Copyright 2019 Google LLC +# +# 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. + + +# [START tts_ssml_address_imports] +from google.cloud import texttospeech + +import html +# [END tts_ssml_address_imports] + + +# [START tts_ssml_address_audio] +def ssml_to_audio(ssml_text, outfile): + # Generates SSML text from plaintext. + # + # 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. + # + # Args: + # ssml_text: string of SSML text + # outfile: string name of file under which to save audio output + # + # Returns: + # nothing + + # Instantiates a client + client = texttospeech.TextToSpeechClient() + + # Sets the text input to be synthesized + synthesis_input = texttospeech.types.SynthesisInput(ssml=ssml_text) + + # Builds the voice request, selects the language code ("en-US") and + # the SSML voice gender ("MALE") + voice = texttospeech.types.VoiceSelectionParams( + language_code='en-US', + ssml_gender=texttospeech.enums.SsmlVoiceGender.MALE) + + # Selects the type of audio file to return + audio_config = texttospeech.types.AudioConfig( + audio_encoding=texttospeech.enums.AudioEncoding.MP3) + + # Performs the text-to-speech request on the text input with the selected + # voice parameters and audio file type + response = client.synthesize_speech(synthesis_input, voice, audio_config) + + # Writes the synthetic audio to the output file. + with open(outfile, 'wb') as out: + out.write(response.audio_content) + print('Audio content written to file ' + outfile) + # [END tts_ssml_address_audio] + + +# [START tts_ssml_address_ssml] +def text_to_ssml(inputfile): + # Generates SSML text from plaintext. + # Given an input filename, this function converts the contents of the text + # file into a string of formatted 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. + # + # Args: + # inputfile: string name of plaintext file + # + # Returns: + # A string of SSML text based on plaintext input + + # Parses lines of input file + with open(inputfile, 'r') as f: + raw_lines = f.read() + + # Replace special characters with HTML Ampersand Character Codes + # These Codes prevent the API from confusing text with + # SSML commands + # For example, '<' --> '<' and '&' --> '&' + + escaped_lines = html.escape(raw_lines) + + # Convert plaintext to SSML + # Wait two seconds between each address + ssml = '{}'.format( + escaped_lines.replace('\n', '\n')) + + # Return the concatenated string of ssml script + return ssml +# [END tts_ssml_address_ssml] + + +# [START tts_ssml_address_test] +def main(): + # test example address file + plaintext = 'resources/example.txt' + ssml_text = text_to_ssml(plaintext) + ssml_to_audio(ssml_text, 'resources/example.mp3') + # [END tts_ssml_address_test] + + +if __name__ == '__main__': + main() diff --git a/samples/snippets/ssml_addresses_test.py b/samples/snippets/ssml_addresses_test.py new file mode 100644 index 00000000..0c4e810e --- /dev/null +++ b/samples/snippets/ssml_addresses_test.py @@ -0,0 +1,49 @@ +# Copyright 2019 Google LLC +# +# 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. + +from ssml_addresses import text_to_ssml +from ssml_addresses import ssml_to_audio + +import filecmp +import os + + +def test_text_to_ssml(capsys): + + # Read expected SSML output from resources + with open('resources/example.ssml', 'r') as f: + expected_ssml = f.read() + + # Assert plaintext converted to SSML + input_text = 'resources/example.txt' + tested_ssml = text_to_ssml(input_text) + assert expected_ssml == tested_ssml + + +def test_ssml_to_audio(capsys): + + # Read SSML input from resources + with open('resources/example.ssml', 'r') as f: + input_ssml = f.read() + + # Assert audio file generated + ssml_to_audio(input_ssml, 'test_example.mp3') + out, err = capsys.readouterr() + + # Assert MP3 file created + assert os.path.isfile('test_example.mp3') + assert "Audio content written to file test_example.mp3" in out + + # Delete MP3 test file + os.remove("test_example.mp3")