소스 검색

Merged branch voxygen into dev

Nicolas Marcq 8 년 전
부모
커밋
c964cac8e1
2개의 변경된 파일145개의 추가작업 그리고 0개의 파일을 삭제
  1. 1 0
      tts/voxygen/__init__.py
  2. 144 0
      tts/voxygen/voxygen.py

+ 1 - 0
tts/voxygen/__init__.py

@@ -0,0 +1 @@
+from voxygen import *

+ 144 - 0
tts/voxygen/voxygen.py

@@ -0,0 +1,144 @@
+import hashlib
+import os
+import shutil
+
+import pygame
+import requests
+import logging
+
+VOXYGEN_LANGUAGES = dict(
+    fr=dict(electra="Electra", emma="Emma", becool="Becool", agnes="Agnes", loic="Loic", fabienne="Fabienne", helene="Helene", marion="Marion", matteo="Matteo",
+            melodine="Melodine", mendoo="Mendoo", michel="Michel", moussa="Moussa", philippe="Philippe", sorciere="Sorciere"),
+    ar=dict(adel="Adel"),
+    de=dict(matthias="Matthias", jylvia="Sylvia"),
+    uk=dict(bronwen="Bronwen", elizabeth="elizabeth", judith="Judith", paul="Paul", witch="Witch"),
+    us=dict(bruce="Bruce", jenny="Jenny"),
+    es=dict(martha="Martha"),
+    it=dict(sonia="Sonia"))
+
+VOXYGEN_VOICE_DEFAULT = "Michel"
+VOXYGEN_LANGUAGES_DEFAULT = "default"
+VOXYGEN_URL = "https://www.voxygen.fr/sites/all/modules/voxygen_voices/assets/proxy/index.php"
+VOXYGEN_CONTENT_TYPE = "audio/mpeg"
+VOXYGEN_TIMEOUT_SEC = 30
+
+CACHE_PATH = "/tmp/jarvis/tts/voxygen"
+CACHE_EXTENSION = ".tts"
+
+AUDIO_FREQUENCY = 16000
+AUDIO_SIZE = -16
+AUDIO_CHANNEL = 1
+AUDIO_BUFFER = 2048
+
+
+def say(words=None, voice=None, language=VOXYGEN_LANGUAGES_DEFAULT, cache=None):
+    voice = get_voice(voice, language)
+
+    file_path = get_file_path(words, voice, language)
+
+    if get_audio(voice, words, file_path, cache):
+        play_audio(file_path)
+        remove_temp_file(file_path, cache)
+
+
+def get_file_path(words, voice, language):
+    md5 = hashlib.md5(words).hexdigest()
+    filename = voice + "." + md5 + CACHE_EXTENSION
+    cache_directory = os.path.join(CACHE_PATH, language)
+    file_path = os.path.join(cache_directory, filename)
+    create_directory(cache_directory)
+    logging.debug("Cache directory %s exists and File path for audio is: %s", cache_directory, file_path)
+    return file_path
+
+
+def get_voice(voice, language):
+    if language in VOXYGEN_LANGUAGES and voice in VOXYGEN_LANGUAGES[language]:
+        return VOXYGEN_LANGUAGES[language][voice]
+
+    logging.warn("Cannot find language matching language: %s voice: %s replace by default voice: %s", language, voice, VOXYGEN_VOICE_DEFAULT)
+    return VOXYGEN_VOICE_DEFAULT
+
+
+def get_audio(voice, text, file_path, cache):
+    if not cache or not os.path.exists(file_path) or file_is_empty(file_path):
+        payload = {
+            "method": "redirect",
+            "text": text.encode('utf8'),
+            "voice": voice
+        }
+
+        r = requests.get(VOXYGEN_URL, params=payload, stream=True, timeout=VOXYGEN_TIMEOUT_SEC)
+
+        content_type = r.headers['Content-Type']
+        logging.debug("Trying to get url: %s response code: %s and content-type: %s", r.url, r.status_code, content_type)
+
+        try:
+            if r.status_code == requests.codes.ok and content_type == VOXYGEN_CONTENT_TYPE:
+                return write_in_file(file_path, r.content)
+            else:
+                return False
+        except IOError as e:
+            logging.error("I/O error(%s): %s", e.errno, e.strerror)
+        except ValueError:
+            logging.error("Could not convert data to an integer.")
+        except:
+            logging.error("Unexpected error: %s", sys.exc_info()[0])
+    else:
+        return True
+
+
+def play_audio(music_file, volume=0.8):
+    try:
+        init_player_audio(music_file, volume)
+        logging.debug("Music file %s loaded!", music_file)
+    except pygame.error:
+        remove_file(music_file)
+        logging.error("File %s not found! (%s)", music_file, pygame.get_error())
+        return
+
+    start_player_audio()
+
+
+def init_player_audio(music_file, volume):
+    pygame.mixer.init(AUDIO_FREQUENCY, AUDIO_SIZE, AUDIO_CHANNEL, AUDIO_BUFFER)
+    pygame.mixer.music.set_volume(volume)
+    pygame.mixer.music.load(music_file)
+
+
+def start_player_audio():
+    pygame.mixer.music.play()
+    clock = pygame.time.Clock()
+    while pygame.mixer.music.get_busy():
+        clock.tick(10)
+    return
+
+
+def remove_temp_file(file_path, cache):
+    if not cache:
+        remove_file(file_path)
+
+
+def remove_file(file_path):
+    if os.path.exists(file_path):
+        os.remove(file_path)
+
+
+def write_in_file(file_path, content):
+    with open(file_path, "wb") as file_open:
+        file_open.write(content)
+        file_open.close()
+    return not file_is_empty(file_path)
+
+
+def file_is_empty(file_path):
+    return os.path.getsize(file_path) == 0
+
+
+def create_directory(cache_path):
+    if not os.path.exists(cache_path):
+        os.makedirs(cache_path)
+
+
+def wipe_cache():
+    shutil.rmtree(CACHE_PATH)
+