def generate_and_play(self, words, generate_audio_function_from_child=None): """ Generate an audio file from <words> if not already in cache and call the Player to play it :param words: Sentence text from which we want to generate an audio file :type words: String :param generate_audio_function_from_child: The child function to generate a file if necessary :type generate_audio_function_from_child; Callback function .. raises:: TtsGenerateAudioFunctionNotFound """ if generate_audio_function_from_child is None: raise TtsGenerateAudioFunctionNotFound self.words = words # we can generate the file path from info we have self.file_path = self._get_path_to_store_audio() if not self.cache: # no cache, we need to generate the file generate_audio_function_from_child() else: # we check if the file already exist. If not we generate it with the TTS engine if not self._is_file_already_in_cache(self.base_cache_path, self.file_path): generate_audio_function_from_child() # then play the generated audio file self.play_audio() # if the user don't want to keep the cache we remove the file if not self.cache: FileManager.remove_file(self.file_path)
def test_is_file_already_in_cache(self): """ Test if file is already stored in cache """ base_cache_path = "/tmp/kalliope/tests/TTSModule/tests/default/" md5_word = "5c186d1e123be2667fb5fd54640e4fd0" file_path = os.path.join(base_cache_path, "5c186d1e123be2667fb5fd54640e4fd0.tts") if os.path.isfile(file_path): # Remove the file FileManager.remove_file(file_path) # Create a tmp file if not os.path.exists(base_cache_path): os.makedirs(base_cache_path) tmp_path = os.path.join(base_cache_path, md5_word+".tts") FileManager.write_in_file(tmp_path, "[kalliope-test] test_is_file_already_in_cache") # Test true self.assertTrue(TTSModule._is_file_already_in_cache(base_cache_path=base_cache_path, file_path=file_path), "Fail retrieving the cached file. The file does not exist but it should !") # Remove the tmp file FileManager.remove_file(tmp_path) # Test False self.assertFalse(TTSModule._is_file_already_in_cache(base_cache_path=base_cache_path, file_path=file_path), "Fail asserting that the file does not exist.")
def test_is_file_already_in_cache(self): """ Test if file is already stored in cache """ base_cache_path = "/tmp/kalliope/tests/TTSModule/tests/default/" md5_word = "5c186d1e123be2667fb5fd54640e4fd0" file_path = os.path.join(base_cache_path, "5c186d1e123be2667fb5fd54640e4fd0.tts") if os.path.isfile(file_path): # Remove the file FileManager.remove_file(file_path) # Create a tmp file if not os.path.exists(base_cache_path): os.makedirs(base_cache_path) tmp_path = os.path.join(base_cache_path, md5_word + ".tts") FileManager.write_in_file( tmp_path, "[kalliope-test] test_is_file_already_in_cache") # Test true self.assertTrue( TTSModule._is_file_already_in_cache( base_cache_path=base_cache_path, file_path=file_path), "Fail retrieving the cached file. The file does not exist but it should !" ) # Remove the tmp file FileManager.remove_file(tmp_path) # Test False self.assertFalse( TTSModule._is_file_already_in_cache( base_cache_path=base_cache_path, file_path=file_path), "Fail asserting that the file does not exist.")
def test_generate_and_play(self): """ Test to generate and play sound """ def new_play_audio(TTSModule): pass words = "kalliope" with mock.patch.object(TTSModule, 'play_audio', new=new_play_audio): settings = Settings(cache_path="/tmp/kalliope/tests") self.TTSMod.settings = settings # test missing callback with self.assertRaises(TtsGenerateAudioFunctionNotFound): self.TTSMod.generate_and_play(words=words) # Assert Callback is called # no Cache self.TTSMod.cache = False generate_audio_function_from_child = mock.Mock() self.TTSMod.generate_and_play(words=words, generate_audio_function_from_child= generate_audio_function_from_child) generate_audio_function_from_child.assert_called() # with cache True but not existing on system self.TTSMod.cache = True generate_audio_function_from_child = mock.Mock() self.TTSMod.generate_and_play(words=words, generate_audio_function_from_child= generate_audio_function_from_child) generate_audio_function_from_child.assert_called() # with cache True and existing on system # create tmp file tmp_base_path = "/tmp/kalliope/tests/TTSModule/tests/default/" file_path = os.path.join(tmp_base_path, "5c186d1e123be2667fb5fd54640e4fd0.tts") if os.path.isfile(file_path): # Remove the file FileManager.remove_file(file_path) if not os.path.exists(tmp_base_path): os.makedirs(tmp_base_path) FileManager.write_in_file( file_path, "[kalliope-test] test_generate_and_play") self.TTSMod.cache = True generate_audio_function_from_child = mock.Mock() self.TTSMod.generate_and_play(words=words, generate_audio_function_from_child= generate_audio_function_from_child) generate_audio_function_from_child.assert_not_called() # Remove the tmp file FileManager.remove_file(file_path)
def test_generate_and_play(self): """ Test to generate and play sound """ def new_play_audio(TTSModule): pass words = "kalliope" with mock.patch.object(TTSModule, 'play_audio', new=new_play_audio): settings = Settings(cache_path="/tmp/kalliope/tests") self.TTSMod.settings = settings # test missing callback with self.assertRaises(TtsGenerateAudioFunctionNotFound): self.TTSMod.generate_and_play(words=words) # Assert Callback is called # no Cache self.TTSMod.cache = False generate_audio_function_from_child = mock.Mock() self.TTSMod.generate_and_play(words=words, generate_audio_function_from_child=generate_audio_function_from_child) generate_audio_function_from_child.assert_called() # with cache True but not existing on system self.TTSMod.cache = True generate_audio_function_from_child = mock.Mock() self.TTSMod.generate_and_play(words=words, generate_audio_function_from_child=generate_audio_function_from_child) generate_audio_function_from_child.assert_called() # with cache True and existing on system # create tmp file tmp_base_path = "/tmp/kalliope/tests/TTSModule/tests/default/" file_path = os.path.join(tmp_base_path, "5c186d1e123be2667fb5fd54640e4fd0.tts") if os.path.isfile(file_path): # Remove the file FileManager.remove_file(file_path) if not os.path.exists(tmp_base_path): os.makedirs(tmp_base_path) FileManager.write_in_file(file_path, "[kalliope-test] test_generate_and_play") self.TTSMod.cache = True generate_audio_function_from_child = mock.Mock() self.TTSMod.generate_and_play(words=words, generate_audio_function_from_child=generate_audio_function_from_child) generate_audio_function_from_child.assert_not_called() # Remove the tmp file FileManager.remove_file(file_path)
def convert_mp3_to_wav(file_path_mp3): """ PyAudio, AlsaPlayer, sounddevices do not support mp3 files MP3 files must be converted to a wave in order to be played This function assumes ffmpeg is available on the system :param file_path_mp3: the file path to convert from mp3 to wav """ logger.debug("[PlayerModule] Converting mp3 file to wav file: %s" % file_path_mp3) fnull = open(os.devnull, 'w') # temp file tmp_file_wav = file_path_mp3 + ".wav" # Convert mp3 to wave subprocess.call(['avconv', '-y', '-i', file_path_mp3, tmp_file_wav], stdout=fnull, stderr=fnull) # remove the original file FileManager.remove_file(file_path_mp3) # rename the temp file with the same name as the original file os.rename(tmp_file_wav, file_path_mp3)
def convert_mp3_to_wav(file_path_mp3): """ PyAudio, AlsaPlayer, sounddevices do not support mp3 files MP3 files must be converted to a wave in order to be played This function assumes ffmpeg is available on the system :param file_path_mp3: the file path to convert from mp3 to wav """ logger.debug("Converting mp3 file to wav file: %s" % file_path_mp3) fnull = open(os.devnull, 'w') # temp file tmp_file_wav = file_path_mp3 + ".wav" # Convert mp3 to wave subprocess.call(['avconv', '-y', '-i', file_path_mp3, tmp_file_wav], stdout=fnull, stderr=fnull) # remove the original file FileManager.remove_file(file_path_mp3) # rename the temp file with the same name as the original file os.rename(tmp_file_wav, file_path_mp3)
def test_remove_file(self): """ Test to remove a file """ # set up the context dir_path = "/tmp/kalliope/tests/" file_name = "test_FileManager_fileRemove" file_path = os.path.join(dir_path, file_name) if os.path.exists(file_path): os.remove(file_path) if not os.path.exists(dir_path): os.makedirs(dir_path) # Test to remove the file # FileManager.remove_file with open(file_path, "wb") as file_open: file_open.write(b"") file_open.close() FileManager.remove_file(file_path=file_path) self.assertFalse(os.path.exists(file_path), "Fail removing the file")
def convert_to_wav(file_path): """ PyAudio, AlsaPlayer, sounddevices only support wav files. Other files must be converted to a wav in order to be played This function uses ffmpeg (which must be installed) for conversion; python core lib sndhdr is used to check if the provided file is already in wav format (skips conversion). :param file_path: the file path to convert to wav """ filetype = sndhdr.whathdr(file_path) if filetype is None or filetype.filetype != 'wav': logger.debug("[PlayerModule] Converting file to wav file: %s" % file_path) fnull = open(os.devnull, 'w') # temp file tmp_file_wav = file_path+ ".wav" # Convert file to wave subprocess.call(['ffmpeg', '-y', '-i', file_path, tmp_file_wav], stdout=fnull, stderr=fnull) # remove the original file FileManager.remove_file(file_path) # rename the temp file with the same name as the original file os.rename(tmp_file_wav, file_path)