def test_big_db(self):
        from tts.db import DB
        from tts.synthesizer import SpeechSynthesizer
        from tts.srv import SynthesizerRequest
        import uuid

        db = DB()
        speech_synthesizer = SpeechSynthesizer(engine='DUMMY',
                                               max_cache_bytes=401)
        speech_synthesizer.engine.set_file_sizes(100)

        for i in range(20):
            request = SynthesizerRequest(text=uuid.uuid4().hex, metadata={})
            response = speech_synthesizer._node_request_handler(request)

        self.assertEqual(db.get_num_files(), 4)

        speech_synthesizer = SpeechSynthesizer(engine='DUMMY',
                                               max_cache_bytes=40001)
        speech_synthesizer.engine.set_file_sizes(1000)

        for i in range(80):
            request = SynthesizerRequest(text=uuid.uuid4().hex, metadata={})
            response = speech_synthesizer._node_request_handler(request)

        self.assertEqual(db.get_num_files(), 40)
    def test_lost_file(self):
        from tts.db import DB
        from tts.synthesizer import SpeechSynthesizer
        from tts.srv import SynthesizerRequest
        import uuid
        import os
        import json

        db = DB()
        init_num_files = db.get_num_files()
        req_text = uuid.uuid4().hex

        speech_synthesizer = SpeechSynthesizer(engine='DUMMY')

        request = SynthesizerRequest(text=req_text, metadata={})
        response = speech_synthesizer._node_request_handler(request)
        res_dict = json.loads(response.result)
        audio_file1 = res_dict['Audio File']

        self.assertEqual(db.get_num_files(), init_num_files + 1)

        os.remove(audio_file1)

        request = SynthesizerRequest(text=req_text, metadata={})
        response = speech_synthesizer._node_request_handler(request)
        res_dict = json.loads(response.result)
        audio_file2 = res_dict['Audio File']

        self.assertEqual(db.get_num_files(), init_num_files + 1)
        self.assertEqual(audio_file1, audio_file2)
        self.assertTrue(os.path.exists(audio_file2))
    def test_multiple_novel(self):
        from tts.db import DB
        from tts.synthesizer import SpeechSynthesizer
        from tts.srv import SynthesizerRequest
        import uuid

        db = DB()
        init_num_files = db.get_num_files()
        for i in range(4):
            speech_synthesizer = SpeechSynthesizer(engine='DUMMY')
            request = SynthesizerRequest(text=uuid.uuid4().hex, metadata={})
            response = speech_synthesizer._node_request_handler(request)

            self.assertEqual(db.get_num_files(), init_num_files + i + 1)
    def test_no_connection_novel(self):
        from tts.db import DB
        from tts.synthesizer import SpeechSynthesizer
        from tts.srv import SynthesizerRequest
        import uuid

        db = DB()
        init_num_files = db.get_num_files()

        speech_synthesizer = SpeechSynthesizer(engine='DUMMY')
        speech_synthesizer.engine.set_connection(False)

        request = SynthesizerRequest(text=uuid.uuid4().hex, metadata={})
        response = speech_synthesizer._node_request_handler(request)

        self.assertEqual(db.get_num_files(), init_num_files)
    def test_file_cleanup_priority(self):
        from tts.db import DB
        from tts.synthesizer import SpeechSynthesizer
        from tts.srv import SynthesizerRequest
        import uuid
        import json
        import os

        db = DB()
        speech_synthesizer = SpeechSynthesizer(engine='DUMMY',
                                               max_cache_bytes=401)
        speech_synthesizer.engine.set_file_sizes(100)

        special_text = uuid.uuid4().hex
        request = SynthesizerRequest(text=special_text, metadata={})
        response = speech_synthesizer._node_request_handler(request)
        res_dict = json.loads(response.result)
        audio_file1 = res_dict['Audio File']
        self.assertTrue(os.path.exists(audio_file1))

        special_text2 = uuid.uuid4().hex
        request = SynthesizerRequest(text=special_text2, metadata={})
        response = speech_synthesizer._node_request_handler(request)
        res_dict = json.loads(response.result)
        audio_file2 = res_dict['Audio File']
        self.assertTrue(os.path.exists(audio_file2))

        for z in range(2):
            for i in range(2):
                request = SynthesizerRequest(text=uuid.uuid4().hex,
                                             metadata={})
                response = speech_synthesizer._node_request_handler(request)
            request = SynthesizerRequest(text=special_text, metadata={})
            response = speech_synthesizer._node_request_handler(request)
            res_dict = json.loads(response.result)
            audio_file1 = res_dict['Audio File']

        self.assertFalse(os.path.exists(audio_file2))
        self.assertTrue(os.path.exists(audio_file1))
示例#6
0
    def _call_engine(self, **kw):
        """Call engine to do the job.

        If no output path is found from input, the audio
        file will be put into /tmp and the file name will have
        a prefix of the md5 hash of the text. If a filename is
        not given, the utterance is added to the cache. If a
        filename is specified, then we will assume that the
        file is being managed by the user and it will not
        be added to the cache.

        :param kw: what AmazonPolly needs to synthesize
        :return: response from AmazonPolly
        """
        if 'output_path' not in kw:
            tmp_filename = hashlib.md5(json.dumps(kw,
                                                  sort_keys=True)).hexdigest()
            tmp_filepath = os.path.join(os.sep, 'tmp',
                                        'voice_{}'.format(tmp_filename))
            kw['output_path'] = os.path.abspath(tmp_filepath)
            rospy.loginfo('managing file with name: {}'.format(tmp_filename))

            # because the hash will include information about any file ending choices, we only
            # need to look at the hash itself.
            db = DB()
            db_search_result = db.ex(
                'SELECT file, audio_type FROM cache WHERE hash=?',
                tmp_filename).fetchone()
            current_time = time.time()
            file_found = False
            if db_search_result:  # then there is data
                # check if the file exists, if not, remove from db
                # TODO: add a test that deletes a file without telling the db and tries to synthesize it
                if os.path.exists(db_search_result['file']):
                    file_found = True
                    db.ex('update  cache set last_accessed=? where hash=?',
                          current_time, tmp_filename)
                    synth_result = PollyResponse(
                        json.dumps({
                            'Audio File': db_search_result['file'],
                            'Audio Type': db_search_result['audio_type'],
                            'Amazon Polly Response Metadata': ''
                        }))
                    rospy.loginfo('audio file was already cached at: %s',
                                  db_search_result['file'])
                else:
                    rospy.logwarn(
                        'A file in the database did not exist on the disk, removing from db'
                    )
                    db.remove_file(db_search_result['file'])
            if not file_found:  # havent cached this yet
                rospy.loginfo('Caching file')
                synth_result = self.engine(**kw)
                res_dict = json.loads(synth_result.result)
                if 'Exception' not in res_dict:
                    file_name = res_dict['Audio File']
                    if file_name:
                        file_size = os.path.getsize(file_name)
                        db.ex(
                            '''insert into cache(
                            hash, file, audio_type, last_accessed,size)
                            values (?,?,?,?,?)''', tmp_filename, file_name,
                            res_dict['Audio Type'], current_time, file_size)
                        rospy.loginfo(
                            'generated new file, saved to %s and cached',
                            file_name)
                        # make sure the cache hasn't grown too big
                        while db.get_size(
                        ) > self.max_cache_bytes and db.get_num_files() > 1:
                            remove_res = db.ex(
                                'select file, min(last_accessed), size from cache'
                            ).fetchone()
                            db.remove_file(remove_res['file'])
                            rospy.loginfo(
                                'removing %s to maintain cache size, new size: %i',
                                remove_res['file'], db.get_size())
        else:
            synth_result = self.engine(**kw)

        return synth_result