Эх сурвалжийг харах

[Feature] Acapela TTS first draft

monf 8 жил өмнө
parent
commit
631e2aa640

+ 2 - 0
core/TTS/TTSModule.py

@@ -14,6 +14,8 @@ logger = logging.getLogger("kalliope")
 class TtsGenerateAudioFunctionNotFound(Exception):
     pass
 
+class FailToLoadSoundFile(Exception):
+    pass
 
 class TTSModule(object):
 

+ 2 - 0
tts/TTS.py

@@ -36,6 +36,8 @@ class TTS:
 
     @staticmethod
     def get_audio(file_path, cache, payload, url, content_type_expected=TTS_CONTENT_TYPE, timeout_expected=TTS_TIMEOUT_SEC):
+
+
         if not cache or not os.path.exists(file_path) or FileManager.file_is_empty(file_path):
 
             r = requests.get(url, params=payload, stream=True, timeout=timeout_expected)

+ 50 - 0
tts/acapela/README.md

@@ -0,0 +1,50 @@
+### Acapela
+
+this TTS is based on the [Acapela engine](http://www.acapela-group.com/)
+
+| Parameters | Required | Default | Choices                                                        | Comment                                                                     |
+|------------|----------|---------|----------------------------------------------------------------|-----------------------------------------------------------------------------|
+| language   | YES      |         | 34 languages (http://www.acapela-group.com/voices/repertoire/) | Language are corresponding to an id plz check the note beside to find yours |
+| voice      | YES      |         | multiple and depending of the language                         | Check available names on the web site                                       |
+| cache      | No       | TRUE    | True / False                                                   | True if you want to use the cache with this TTS                             |
+
+#### Notes
+
+Corresponding languages to id :
+
+Arabic="sonid0"
+Catalan="sonid1"
+Czech="sonid2" 
+Danish="sonid3" 
+Dutch (Belgium)="sonid4" 
+Dutch (Netherlands)="sonid5" 
+English (AU)="sonid6" 
+English (India)="sonid7"
+English (Scottish)="sonid8"
+English (UK)="sonid9" 
+English (USA)="sonid10" 
+Faroese="sonid11"
+Finnish="sonid12"
+French (Belgium)="sonid13" 
+French (Canada) ="sonid14" 
+French (France)="sonid15"
+German="sonid16"
+Greek="sonid17" 
+Italian="sonid18"
+Japanese="sonid19"
+Korean="sonid20"
+Mandarin="sonid21"
+Norwegian="sonid22" 
+Polish="sonid23" 
+Portuguese (Brazil)="sonid24" 
+Portuguese (Portugal)="sonid25" 
+Russian="sonid26" 
+Sami (North)="sonid27"
+Spanish (Spain)="sonid28" 
+Spanish (US)="sonid29" 
+Swedish="sonid30" 
+Swedish (Finland) ="sonid31"
+Swedish (Gothenburg)  ="sonid32"
+Swedish (Scanian) ="sonid33" 
+Turkish ="sonid34"  
+                  

+ 44 - 35
tts/acapela/acapela.py

@@ -1,52 +1,61 @@
+import requests
+import re
+from core import FileManager
+from core.TTS.TTSModule import TTSModule, FailToLoadSoundFile
 import logging
 
-import re
+logging.basicConfig()
+logger = logging.getLogger("kalliope")
 
-import requests
+TTS_URL = "http://www.acapela-group.com/demo-tts/DemoHTML5Form_V2_fr.php"
+TTS_CONTENT_TYPE = "audio/mpeg"
+TTS_TIMEOUT_SEC = 30
 
-from core import AudioPlayer
-from tts import TTS
 
-logging.basicConfig()
-logger = logging.getLogger("kalliope")
+class Acapela(TTSModule):
+    def __init__(self, **kwargs):
+        super(Acapela, self).__init__(**kwargs)
 
+    def say(self, words):
 
-class Acapela(TTS):
-    TTS_LANGUAGES_DEFAULT = 'sonid15'
-    TTS_VOICE_DEFAULT = 'Manon'
-    TTS_URL = "http://www.acapela-group.com/demo-tts/DemoHTML5Form_V2_fr.php"
-    TTS_CONTENT_TYPE = "audio/mpeg"
-    TTS_TIMEOUT_SEC = 30
+        self.generate_and_play(words, self._generate_audio_file)
 
-    def __init__(self):
-        TTS.__init__(self)
+    @classmethod
+    def _generate_audio_file(cls):
 
-    def say(self, words=None, language=TTS_LANGUAGES_DEFAULT, voice=TTS_VOICE_DEFAULT, cache=True):
-        self.say_generic(cache, language, words, self.get_audio_acapela, AudioPlayer.PLAYER_MP3, AudioPlayer.AUDIO_MP3_22050_FREQUENCY, voice)
+        # Prepare payload
+        payload = cls.get_payload()
 
-    def get_audio_acapela(self, **kwargs):
-        language = kwargs.get('language', None)
-        words = kwargs.get('words', None)
-        cache = kwargs.get('cache', None)
-        file_path = kwargs.get('file_path', None)
-        voice = kwargs.get('voice', None)
-        payload = Acapela.get_payload(language, voice, words)
-        url = Acapela.get_audio_link(self.TTS_URL, payload)
+        # Get the mp3 URL from the page
+        url = Acapela.get_audio_link(cls.TTS_URL, payload)
 
-        return TTS.get_audio(file_path, cache, payload, url)
+        # getting the mp3
+        r = requests.get(url, params=payload, stream=True, timeout=TTS_TIMEOUT_SEC)
+        content_type = r.headers['Content-Type']
 
-    @staticmethod
-    def get_audio_link(url, payload, timeout_expected=30):
-        r = requests.post(url, payload, timeout=timeout_expected)
-        data = r.content
-        return re.search("(?P<url>https?://[^\s]+).mp3", data).group(0)
+        logger.debug("Trying to get url: %s response code: %s and content-type: %s",
+                     r.url,
+                     r.status_code,
+                     content_type)
+        # Verify the response status code and the response content type
+        if r.status_code != requests.codes.ok or content_type != TTS_CONTENT_TYPE:
+            raise FailToLoadSoundFile("Fail while trying to remotely access the audio file")
 
-    @staticmethod
-    def get_payload(language, voice, words):
+        # OK we get the audio we can write the sound file
+        FileManager.write_in_file(cls.file_path, r.content)
+
+    @classmethod
+    def get_payload(cls):
         return {
-            "MyLanguages": language,
-            "MySelectedVoice": voice,
-            "MyTextForTTS": words,
+            "MyLanguages": cls.language,
+            "MySelectedVoice": cls.voice,
+            "MyTextForTTS": cls.words,
             "t": "1",
             "SendToVaaS": ""
         }
+
+    @staticmethod
+    def get_audio_link(url, payload, timeout_expected=TTS_TIMEOUT_SEC):
+        r = requests.post(url, payload, timeout=timeout_expected)
+        data = r.content
+        return re.search("(?P<url>https?://[^\s]+).mp3", data).group(0)