現在私はテキストを音声で使用しwine
て適用しています。Windows
TTSApp.exe
SAPI-5音声とうまく機能するGUIアプリケーションです。テキストファイルを選択し、WAV
数回クリックするだけでファイルに変換します。
しかし、私も別のことをしたかったです。
変換用のコマンドラインスクリプトを作成し、次のように実行したいと思います。
wine ttsUtil.exe text.txt -voice=nick -output=speech.wav
ワインの下でこれは可能ですか?私のお気に入りのサウンドはWindowsでのみ実行されるため、ワインを使用する必要があります。私はGUI TTSApp.exeの代わりにいくつかのttsUtil.exe(名前は重要ではありません)を使用したいと思います。
変換する小さなテキストファイルのそれぞれをクリックする時間がないため、これを自動化する必要があります。
答え1
私の提案は、ワインを取り除き、Linux pico2waveプログラムを使用することです。
Ubuntu 14.04では、pico2waveはlibttspico-utilsの一部です。
コマンドは次のとおりです。
pico2wave --wave=test.wav "$(cat filename.txt)"
答え2
持っているコマンドが機能し、自動化するだけでよいと言えば、いくつかのオプションがあります。
変換したいファイルディレクトリがある場合は、次のことができます。
#!/bin/bash
ARG=$1
for i in "${ARG}"/* ;
do
wine ttsUtil.exe "${i}" -voice=nick -output="${i}".wav
done
ファイルとして保存し(ttsconvert.shとも呼ばれます)、実行可能にします。
chmod +x ttsconvert.sh
これで、変換したいファイルディレクトリへのパスを指定してスクリプトを実行できます。
./ttsconvert.sh ~/path/to/stash/of/files
ファイルごとに使用するには、.desktopファイルを使用して独自のランチャーを作成できます。
たとえば、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;
ルートとして、このファイルを/usr/share/applicationsに配置すると、次のことができます。次に開く右クリックメニューのオプションは、新しいコンバータを使用してテキストファイルを開きます。動作しているという事実を教えてくれません。 GUI通知を使用するための高度なスクリプトを作成できますが、これがすべてのことができる場所ではありません。
答え3
次のSAPI5コマンドラインユーティリティを試してみましょう。http://www.nirsoft.net/articles/speak_from_command_line.html
また、以下を試してください。http://jampal.sourceforge.net/ptts.html
答え4
パッチワークですが安定して動作するようにしました。 XepyrウィンドウでTTSApp.exeをスクリプト化し、マウスとキーボードの入力をシミュレートします。
Ubuntuパッケージをインストールします。 xserver-xephyr metacity xdotool libav-tools
デフォルトのスピード速度以外のものが必要な場合は、各テキストファイルの先頭に次を追加し、 <prosody rate="medium"><prosody rate="+36%">
最後に適切な終了単語を追加します。 ( </prosody></prosody>
第8-9章にはさらにXMLオプションがあります。AT&T Natural 音声システム開発者ガイド)。
i
必要な音声を選択するには、スクリプトをkey --delay 100 i
TTSApp.exeの必須キーに置き換えます。
変換が成功した後にソースファイルを削除するには、スクリプトの末尾のunlink()コメントを削除してください。
以下からこのスクリプトを実行してください。
find . -name 'chapter*.txt' -print0 |xargs -0 txt2ogg
これはPerlスクリプトですtxt2ogg
(忘れないでください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
}