2016-11-06 6 views
0

Я использую существующую программу, которая читает xml из сокета, преобразует текст в wav-файл и затем воспроизводит его через устройство вывода звука.Преобразование python espeak + код подпроцесса для непосредственного воспроизведения выходного аудиосигнала

Я хотел бы снять его, чтобы он просто воспроизводил текст прямо на аудио.

Прямо сейчас мне сложно определить, есть ли у меня правильный код и понять, действительно ли он создает wav-файл.

Функция, которая вызывает называет текст речи функции

def generate_audio(self, language, voice=None): 
    info = self.get_first_info(language, bestmatch=False) 
    if info is None: 
     self.media_info[language] = None 
     return False 

    truncate = not self.broadcast_immediately() and bcastplayer.Config.setting('alerts_truncate') 
    message_text = info.get_message_text(truncate) 

    location = bcastplayer.ObData.get_datadir() + "/alerts" 
    if os.access(location, os.F_OK) == False: 
     os.mkdir(location) 
    filename = self.reference(self.sent, self.identifier) + "-" + language + ".wav" 

    resources = info.get_resources('audio') 
    if resources: 
     if resources[0].write_file(os.path.join(location, filename)) is False: 
      return False 

    elif message_text: 
     self.write_tts_file(os.path.join(location, filename), message_text, voice) 

    else: 
     return False 

Может ли это быть модифицирован для воспроизведения звука напрямую?

def write_tts_file(self, path, message_text, voice=None): 
    if not voice: 
     voice = 'en' 
    proc = subprocess.Popen([ 'espeak', '-m', '-v', voice, '-s', '130', '--stdout' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True) 
    (stdout, stderr) = proc.communicate(message_text.encode('utf-8') + b" <break time=\"2s\" /> " + message_text.encode('utf-8') + b" <break time=\"3s\" /> ") 
    proc.wait() 

    with open(path, 'wb') as f: 
     f.write(stdout) 

Я никогда не видел такой код с помощью process, subprocess, stdout, PIPE.

Легко ли изменить код подпроцесса на то, что просто передает или перенаправляет вывод на aplay без создания wav-файла?

Был еще один ответ, который может дать ключ - но опять же, мое понимание новичку не уверен, как преобразовать этот код в этот ответ

How to use python Popen with a espeak and aplay

ответ

2

Вы можете связать эти два процесса вместе с помощью subprocess.PIPE , Вот модифицированная версия функции write_tts_file:

def write_tts_file(self, path, message_text, voice=None): 
    if not voice: 
     voice = 'en' 
    proc = subprocess.Popen(['espeak', '-m', '-v', voice, '-s', '130', '--stdout' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True) 
    aplay = subprocess.Popen(['aplay', '-D', 'sysdefault'], stdin=proc.stdout) 
    proc.stdin.write(message_text.encode('utf-8') + b" <break time=\"2s\" /> " + message_text.encode('utf-8') + b" <break time=\"3s\" /> \n") 
    proc.stdin.close() 
    proc.wait() 

Важно, чтобы закрыть proc «s stdin после того, как вы отправили сообщение, которое должно говориться. Это приведет к тому, что proc уйдет, когда он отправит свои данные, и закроет его вывод aplay, который, в свою очередь, выйдет, когда он закончит игру. Если вход proc не закрыт, ни один из них не будет закрыт.

+0

Спасибо, я попробую. Мне действительно трудно понять espeak и подпроцессы – dbmitch