#!/usr/bin/env python # Copyright (c) 2018, Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). # You may not use this file except in compliance with the License. # A copy of the License is located at # # http://aws.amazon.com/apache2.0 # # or in the "license" file accompanying this file. This file 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 __future__ import print_function import sys import json import unittest import rospy import rostest from tts.srv import Polly from tts.srv import PollyResponse from tts.srv import Synthesizer from tts.srv import SynthesizerResponse # import tts which is a relay package, otherwise things don't work # # devel/lib/python2.7/dist-packages/ # +-- tts # | +-- __init__.py # +-- ... # # per http://docs.ros.org/api/catkin/html/user_guide/setup_dot_py.html: # # A relay package is a folder with an __init__.py folder and nothing else. # Importing this folder in python will execute the contents of __init__.py, # which will in turn import the original python modules in the folder in # the sourcespace using the python exec() function. PKG = 'tts' NAME = 'amazonpolly' class TestPlainText(unittest.TestCase): def test_plain_text_to_wav_via_polly_node(self): rospy.wait_for_service('polly') polly = rospy.ServiceProxy('polly', Polly) test_text = 'Mary has a little lamb, little lamb, little lamb.' res = polly(polly_action='SynthesizeSpeech', text=test_text) self.assertIsNotNone(res) self.assertTrue(type(res) is PollyResponse) r = json.loads(res.result) self.assertIn('Audio Type', r, 'result should contain audio type') self.assertIn('Audio File', r, 'result should contain file path') self.assertIn('Amazon Polly Response Metadata', r, 'result should contain metadata') audio_type = r['Audio Type'] audio_file = r['Audio File'] md = r['Amazon Polly Response Metadata'] self.assertTrue("'HTTPStatusCode': 200," in md) self.assertEqual('audio/ogg', audio_type) self.assertTrue(audio_file.endswith('.ogg')) import subprocess o = subprocess.check_output(['file', audio_file], stderr=subprocess.STDOUT) import re m = re.search(r'.*Ogg data, Vorbis audi.*', o, flags=re.MULTILINE) self.assertIsNotNone(m) def test_plain_text_using_polly_class(self): from tts.amazonpolly import AmazonPolly polly = AmazonPolly() test_text = 'Mary has a little lamb, little lamb, little lamb.' res = polly.synthesize(text=test_text) self.assertIsNotNone(res) self.assertTrue(type(res) is PollyResponse) r = json.loads(res.result) self.assertIn('Audio Type', r, 'result should contain audio type') self.assertIn('Audio File', r, 'result should contain file path') self.assertIn('Amazon Polly Response Metadata', r, 'result should contain metadata') audio_type = r['Audio Type'] audio_file = r['Audio File'] md = r['Amazon Polly Response Metadata'] self.assertTrue("'HTTPStatusCode': 200," in md) self.assertEqual('audio/ogg', audio_type) self.assertTrue(audio_file.endswith('.ogg')) import subprocess o = subprocess.check_output(['file', audio_file], stderr=subprocess.STDOUT) import re m = re.search(r'.*Ogg data, Vorbis audi.*', o, flags=re.MULTILINE) self.assertIsNotNone(m) def test_plain_text_via_synthesizer_node(self): rospy.wait_for_service('synthesizer') speech_synthesizer = rospy.ServiceProxy('synthesizer', Synthesizer) text = 'Mary has a little lamb, little lamb, little lamb.' res = speech_synthesizer(text=text) self.assertIsNotNone(res) self.assertTrue(type(res) is SynthesizerResponse) r = json.loads(res.result) self.assertIn('Audio Type', r, 'result should contain audio type') self.assertIn('Audio File', r, 'result should contain file path') self.assertIn('Amazon Polly Response Metadata', r, 'result should contain metadata') audio_type = r['Audio Type'] audio_file = r['Audio File'] md = r['Amazon Polly Response Metadata'] self.assertTrue("'HTTPStatusCode': 200," in md) self.assertEqual('audio/ogg', audio_type) self.assertTrue(audio_file.endswith('.ogg')) import subprocess o = subprocess.check_output(['file', audio_file], stderr=subprocess.STDOUT) import re m = re.search(r'.*Ogg data, Vorbis audi.*', o, flags=re.MULTILINE) self.assertIsNotNone(m) def test_plain_text_to_mp3_via_polly_node(self): rospy.wait_for_service('polly') polly = rospy.ServiceProxy('polly', Polly) test_text = 'Mary has a little lamb, little lamb, little lamb.' res = polly(polly_action='SynthesizeSpeech', text=test_text, output_format='mp3') self.assertIsNotNone(res) self.assertTrue(type(res) is PollyResponse) r = json.loads(res.result) self.assertIn('Audio Type', r, 'result should contain audio type') self.assertIn('Audio File', r, 'result should contain file path') self.assertIn('Amazon Polly Response Metadata', r, 'result should contain metadata') audio_type = r['Audio Type'] audio_file = r['Audio File'] md = r['Amazon Polly Response Metadata'] self.assertTrue("'HTTPStatusCode': 200," in md) self.assertEqual('audio/mpeg', audio_type) self.assertTrue(audio_file.endswith('.mp3')) import subprocess o = subprocess.check_output(['file', audio_file], stderr=subprocess.STDOUT) import re m = re.search(r'.*MPEG.*layer III.*', o, flags=re.MULTILINE) self.assertIsNotNone(m) def test_simple_ssml_via_polly_node(self): rospy.wait_for_service('polly') polly = rospy.ServiceProxy('polly', Polly) text = 'Mary has a little lamb, little lamb, little lamb.' res = polly(polly_action='SynthesizeSpeech', text=text, text_type='ssml') self.assertIsNotNone(res) self.assertTrue(type(res) is PollyResponse) r = json.loads(res.result) self.assertIn('Audio Type', r, 'result should contain audio type') self.assertIn('Audio File', r, 'result should contain file path') self.assertIn('Amazon Polly Response Metadata', r, 'result should contain metadata') audio_type = r['Audio Type'] audio_file = r['Audio File'] md = r['Amazon Polly Response Metadata'] self.assertTrue("'HTTPStatusCode': 200," in md) self.assertEqual('audio/ogg', audio_type) self.assertTrue(audio_file.endswith('.ogg')) import subprocess o = subprocess.check_output(['file', audio_file], stderr=subprocess.STDOUT) import re m = re.search(r'.*Ogg data, Vorbis audi.*', o, flags=re.MULTILINE) self.assertIsNotNone(m) def test_simple_ssml_via_synthesizer_node(self): rospy.wait_for_service('synthesizer') speech_synthesizer = rospy.ServiceProxy('synthesizer', Synthesizer) text = 'Mary has a little lamb, little lamb, little lamb.' res = speech_synthesizer(text=text, metadata='''{"text_type":"ssml"}''') self.assertIsNotNone(res) self.assertTrue(type(res) is SynthesizerResponse) r = json.loads(res.result) self.assertIn('Audio Type', r, 'result should contain audio type') self.assertIn('Audio File', r, 'result should contain file path') self.assertIn('Amazon Polly Response Metadata', r, 'result should contain metadata') audio_type = r['Audio Type'] audio_file = r['Audio File'] md = r['Amazon Polly Response Metadata'] self.assertTrue("'HTTPStatusCode': 200," in md) self.assertEqual('audio/ogg', audio_type) self.assertTrue(audio_file.endswith('.ogg')) import subprocess o = subprocess.check_output(['file', audio_file], stderr=subprocess.STDOUT) import re m = re.search(r'.*Ogg data, Vorbis audi.*', o, flags=re.MULTILINE) self.assertIsNotNone(m) if __name__ == '__main__': rostest.rosrun(PKG, NAME, TestPlainText, sys.argv)