Text-to-speech em um script

2

Atualmente, estou usando o aplicativo wine e Windows TTSApp.exe para text-to-speech.

É uma aplicação GUI e funciona bem com as vozes do SAPI-5. Eu escolherei um arquivo de texto com alguns cliques e convertê-lo em WAV file.

Mas eu também gostaria de fazer algo diferente.

Gostaria de escrever um script de linha de comando para conversão e executá-lo algo como segue:

wine ttsUtil.exe text.txt -voice=nick -output=speech.wav

Isso é possível sob o vinho? Eu preciso usar vinho porque minhas vozes favoritas executar apenas no Windows. Eu gostaria de usar alguns ttsUtil.exe (nome não importa) em vez do meu GUI TTSApp.exe.

Eu realmente preciso automatizar essa tarefa porque não tenho tempo para que cada pequeno arquivo de texto faça tanto clique para a conversão.

    
por xralf 15.02.2015 / 22:03

5 respostas

1

Minha recomendação é eliminar o vinho e usar o programa pico2wave do Linux.

No Ubuntu 14.04 pico2wave faz parte do libttspico-utils

O comando seria parecido com:

pico2wave --wave=test.wav "$(cat filename.txt)"
    
por 16.02.2015 / 04:30
1

Se você está dizendo que o comando que você tem funciona, você só precisa automatizá-lo, então você tem algumas opções:

Se você tiver um diretório de arquivos que deseja converter, poderá fazer algo assim:


#!/bin/bash
ARG=$1

for i in "${ARG}"/* ;
do
wine ttsUtil.exe "${i}" -voice=nick -output="${i}".wav
done

Salve como um arquivo (talvez chame de ttsconvert.sh) e torne-o executável:

chmod +x ttsconvert.sh

Agora você pode executar o script fornecendo o caminho para o diretório de arquivos que deseja converter:

./ttsconvert.sh ~/path/to/stash/of/files

Se você quiser em uma base arquivo por arquivo, você pode criar seu próprio lançador usando arquivos .desktop.

Por exemplo, crie um arquivo chamado ttsconvert.desktop:


[Desktop Entry]
Version=0.1
Name=TTSConvert
Exec=wine ttsUtil.exe %U -voice=nick -output=speech.wav
Icon=multimedia-volume-control
MimeType=text/plain;

Como root, coloque este arquivo em / usr / share / applications e você poderá usar a opção Open With do menu do botão direito para abrir um arquivo de texto com o novo conversor . Não lhe dará qualquer aviso de que está funcionando; um script mais elaborado poderia ser escrito para usar uma notificação de GUI, mas este não é o lugar para tudo isso ainda.

    
por 18.02.2015 / 04:08
1

Eu tentaria usar um utilitário de linha de comando SAPI5 como: link

Experimente também: link

    
por 18.02.2015 / 07:09
1

Você viu este ? É um programa de linha de comando e parece rodar no windows, então será fácil de lançá-lo em lote.

    
por 18.02.2015 / 16:31
1

Este é um kludge, mas eu consegui trabalhar de forma confiável. Ele scripts TTSApp.exe em uma janela Xephyr e simula a entrada do mouse e teclado.

Instalar pacotes do Ubuntu: xserver-xephyr metacity xdotool libav-tools

Se você quiser algo diferente da taxa de fala padrão, adicione isso ao início de cada arquivo de texto: <prosody rate="medium"><prosody rate="+36%"> e o fechamento correspondente no final: </prosody></prosody> (muitas outras opções de XML nos capítulos 8-9 de < a href="http://www.wizzardsoftware.com/docs/attnaturalvoicestts14.pdf"> Guia para desenvolvedores de sistemas da AT & T Natural Voices .

Substitua i em key --delay 100 i no script pelas chaves necessárias no TTSApp.exe para selecionar sua voz preferida.

Se você quiser excluir o arquivo de origem após uma conversão bem-sucedida, remova o comentário do unlink () no final do script.

Execute este script por meio de algo como:

find . -name 'chapter*.txt' -print0 |xargs -0 txt2ogg

Aqui está o script Perl txt2ogg (não se esqueça de chmod +x ):

#!/usr/bin/perl -CS -w
#
use strict;
use warnings;
use utf8;
#

my $homeDir=$ENV{HOME};
$homeDir .= '/' if(substr($homeDir,length($homeDir)-1,1) ne '/');

my $oldDir = 'pwd';
chomp($oldDir);
$oldDir .= '/' if(substr($oldDir,length($oldDir)-1,1) ne '/');
chdir($homeDir) or die($!);
system( q(Xephyr :4 -screen 600x480 >/dev/null 2>/dev/null &) ); # using the user's display works until you try to get other work done or the screensaver starts
system( q(DISPLAY=:4 metacity >/dev/null 2>/dev/null &) ); # xdotool needs a window manager
foreach(@ARGV) {
  s|^\./||;
  my $thisArg = $_;
  my $ttsIn = $oldDir.$thisArg; # make path absolute
  (my $ttsOut = $ttsIn) =~ s|\.[^\./]*$||; # strip file extension
  $ttsOut .= '.ogg';
  my $attempt = 0;
  my $errorCodes = ""; # list of codes for recoverable errors
  my $closeDialogCmd = q(export DISPLAY=:4; xdotool search --name "File Saved" windowactivate --sync %@ key space 2>/dev/null);
  my $ExitCmd = q(export DISPLAY=:4; xdotool search --name "SAPI5 TTSAPP" windowactivate --sync %@ windowkill 2>/dev/null);
  while(1) {
    print("\r$thisArg ... ");
    unlink("ttsin");
    unlink("ttsout.wav");
    unlink("ttsout.ogg");
    symlink($ttsIn,"ttsin") or die($!);
    #xdotool is sometimes too fast, even with ''--delay 100'', so BackSpace makes sure the full name gets entered
    my $stallLimit = 10;
    my $seconds = 0;
    my $priorWavSize = 0;
    my $stalledTime = 0;
    my $wavSize = 0;
    #start TTSApp.exe in the background
    system( q(DISPLAY=:4 wine "C:\Program Files\eSpeak\TTSApp.exe" 2>/dev/null >/dev/null &) );
    #in TTSApp.exe, enable XML; select proper voice; open "ttsin"; and save as "ttsout.wav"
    system( q(export DISPLAY=:4; xdotool search --sync --name "SAPI5 TTSAPP" windowactivate --sync %@ mousemove --window %@ 36 339 click 1 mousemove --window %@ 426 233 click 1 key --delay 100 i mousemove --window %@ 500 37 click 1 key --delay 100 BackSpace BackSpace t t s i n Return mousemove --window %@ 500 288 click 1 key --delay 100 BackSpace BackSpace t t s o u t Return 2>/dev/null >/dev/null) );
    while(1) { # wait for "File Saved" dialog
      sleep(2);
      $seconds += 2;
      #check if "File Saved" dialog exists yet
      last if(system( q(export DISPLAY=:4; xdotool search --name "File Saved" >/dev/null) ) == 0);
      my $wavSizeCmd = q(stat --printf '%s' ttsout.wav 2>/dev/null);
      $wavSize = '$wavSizeCmd';
      $wavSize = 0 if(!defined($wavSize) or length($wavSize) == 0);
      if($wavSize <= $priorWavSize) {
        $stalledTime += 2;
        if($stalledTime >= $stallLimit) {
          $errorCodes .= " 282"; # TTSApp.exe not responding
          if(system($ExitCmd) != 0) { # kill TTSApp.exe and try again
            $errorCodes .= " 443"; # TTSApp.exe still not responding
            sleep(2);
            system($ExitCmd);
          }
          last;
        }
      } else {
        $stalledTime = 0;
      }
      $priorWavSize = $wavSize;
      print("\r$thisArg ...$wavSize bytes");
    }
    if(($stalledTime < $stallLimit)) { # above loop not stalled
      if($wavSize == 11639) {
        $errorCodes .= " 639"; # size of .wav is exactly the size for "Enter text you whish spoken here" in the default voice
      } else {
        last; # success
      }
    }
    if($attempt++ >= 5) {
      die("unable to process file with TTSApp.exe");
    }
  }
  #close "File Saved" dialog and exit TTSApp.exe
  if(system($closeDialogCmd) != 0) {
    $errorCodes .= " 934"; # closing dialog failed
    sleep(2);
    if(system($closeDialogCmd) != 0) {
      $errorCodes .= " 818"; # closing dialog failed again
      sleep(2);
      system($closeDialogCmd);
    }
  }
  if(system($ExitCmd) != 0) {
    $errorCodes .= " 245"; # closing TTSApp.exe failed
    sleep(2);
    if(system($ExitCmd) != 0) {
      $errorCodes .= " 871"; # closing TTSApp.exe failed again
      sleep(2);
      system($ExitCmd);
    }
  }
  print("\r$thisArg ... converting to .ogg  ");
  #''-qscale 0'' (24Kbps) has noticable whisper-like overtones and ''1'' (30Kbps) and ''2'' (35Kbps) are quite close, so I decided on ''-qscale 1''
  system('cat ttsout.wav |avconv -i pipe:0 -codec:a libvorbis -qscale 1 ttsout.ogg 2>/dev/null >/dev/null') == 0 or die($!);
  unlink("ttsin");
  unlink("ttsout.wav");
  rename("ttsout.ogg",$ttsOut) or die($!);
  if(length($errorCodes) == 0) {
    print("\r$thisArg ... done                \n");
  } else {
    print("\r$thisArg ... done (recovered from: $errorCodes)            \n");
  }
  #unlink($ttsIn); # delete original only after .ogg is in place
}
    
por 15.12.2015 / 17:51