(转载+部分原创)星际译王在gentoo gnome (xfce4 上也可以)上的安装(并可以实现发音,)OtdRealPeopleTTS 不用非得把mp3 转化为wav

http://forum.ubuntu.org.cn/viewtopic.php?f=137&p=1515096  (原文)

 

 

 

今天要用到StarDict的真人发音库,发现有WyabdcRealPeopleTTS 和OtdRealPeopleTTS
两个库。WyabdcRealPeopleTTS的音质太差,不用。那就只有用OtdRealPeopleTTS了,
但OtdRealPeopleTTS是mp3格式的,StarDict只能放wav格式的,还要把mp3转为wav,
本来转换一下不是问题,但转换后150M 的文件变成3G的文件,就算磁盘空间充足也不
是这样浪费的吧!何况这都可以存放很多部片子了~

由于我已经装了mplayer以及mp3解码器,以为在音效设置里面把play改为mplayer,
语音库路径改为/usr/share/OtdRealPeopleTTS就可以了。但修改后发现还是没发声。

/etc/portage/package.use

加入下面一行

app-dicts/stardict -gnome spell   pronounce

# ebuild    stardict-3.0.1-r2.ebuild  fetch   //下载所需的软件,

 

 

决定下开源码来看一下,打开/stardict-3.0.1/src/readword.cpp一看,发现了问题所在

一、
bool ReadWord::RealTts_canRead(const gchar *word)
{
bool return_val = false;
if (!ttspath.empty() && word && g_ascii_isalpha(word[0])) {
std::string lowerword;
const gchar *p = word;
while (*p) {
if (*p!=' ')
lowerword+=g_ascii_tolower(*p);
p++;
}
std::string filename;
std::list<std::string>::const_iterator it;
for (it=ttspath.begin(); it!=ttspath.end(); ++it) {
filename = *it + G_DIR_SEPARATOR_S + lowerword[0] + G_DIR_SEPARATOR_S + lowerword + ".wav"; #1
return_val = g_file_test(filename.c_str(), G_FILE_TEST_EXISTS); #2

if (return_val)
break;
}
}
return return_val;
}

红色标记第一句是找到wav文件的全路径,第二句是判断文件是否存在。由于是硬编定为wav,
所以前面修改音效设置是没有用的。

改为:
bool ReadWord::RealTts_canRead(const gchar *word)
{
bool return_val = false;
if (!ttspath.empty() && word && g_ascii_isalpha(word[0])) {
std::string lowerword;
const gchar *p = word;
while (*p) {
if (*p!=' ')
lowerword+=g_ascii_tolower(*p);
p++;
}
std::string filename;
std::list<std::string>::const_iterator it;
for (it=ttspath.begin(); it!=ttspath.end(); ++it) {
std::string suffix, aword;
aword = *it + G_DIR_SEPARATOR_S + "a" + G_DIR_SEPARATOR_S + "a.mp3";
if (g_file_test(aword.c_str(), G_FILE_TEST_EXISTS))
suffix = ".mp3";
else
suffix = ".wav";
filename = *it + G_DIR_SEPARATOR_S + lowerword[0] + G_DIR_SEPARATOR_S + lowerword + suffix;

return_val = g_file_test(filename.c_str(), G_FILE_TEST_EXISTS);
if (return_val)
break;
}
}
return return_val;
}

在/stardict-3.0.1/src/readword.cpp中有两个这样的地方,另一个在

void ReadWord::RealTts_read(const gchar *word)
bool ReadWord::RealTts_canRead(const gchar *word)

void ReadWord::Command_read(const gchar *word)这个函数中,都这样改。

(大家在此文件中搜一搜wav 这个词就可以知道有几 处)

改好之后,保存文件

tar -jcf stardict-3.0.1.tar.bz2  /tmp/ stardict-3.0.1

将其放到/usr/portage/distfiles 目录下(将好将原来的另保存一份)

 

此文件为我改好的readword.cpp 文件内容

#ifdef HAVE_CONFIG_H # include "config.h" #endif #include <cstring> #include <string> #include <glib/gi18n.h> #include "conf.h" #include "desktop.hpp" #include "utils.h" #include "stardict.h" #include "readword.h" ReadWord::ReadWord() { const std::string &path = conf->get_string_at("dictionary/tts_path"); LoadRealTtsPath(path.c_str()); use_command_tts = conf->get_bool("/apps/stardict/preferences/dictionary/use_tts_program"); tts_program_cmdline = conf->get_string("/apps/stardict/preferences/dictionary/tts_program_cmdline"); } ReadWordType ReadWord::canRead(const gchar *word) { if (RealTts_canRead(word)) return READWORD_REALTTS; if (gpAppFrame->oStarDictPlugins->TtsPlugins.nplugins() > 0) return READWORD_TTS; if (use_command_tts && !tts_program_cmdline.empty()) return READWORD_COMMAND; return READWORD_CANNOT; } void ReadWord::read(const gchar *word, ReadWordType type) { if (type == READWORD_REALTTS) { RealTts_read(word); } else if (type == READWORD_TTS) { gpAppFrame->oStarDictPlugins->TtsPlugins.saytext(0, word); } else if (type == READWORD_COMMAND) { Command_read(word); } } void ReadWord::LoadRealTtsPath(const gchar *path) { std::list<std::string> paths; std::string str; const gchar *p, *p1; p = path; do { p1 = strchr(p, '/n'); if (p1) { str.assign(p, p1-p); if (!str.empty()) paths.push_back(str); p = p1+1; } } while (p1); str = p; if (!str.empty()) paths.push_back(str); ttspath.clear(); std::list<std::string>::const_iterator it; for (it=paths.begin(); it!=paths.end(); ++it) { #ifdef _WIN32 if (it->length()>1 && (*it)[1]==':') { if (g_file_test(it->c_str(), G_FILE_TEST_EXISTS)) ttspath.push_back(*it); } else { str = gStarDictDataDir + G_DIR_SEPARATOR_S + *it; if (g_file_test(str.c_str(), G_FILE_TEST_EXISTS)) ttspath.push_back(str); } #else if (g_file_test(it->c_str(), G_FILE_TEST_EXISTS)) ttspath.push_back(*it); #endif } } bool ReadWord::RealTts_canRead(const gchar *word) { bool return_val = false; if (!ttspath.empty() && word && g_ascii_isalpha(word[0])) { std::string lowerword; const gchar *p = word; while (*p) { if (*p!=' ') lowerword+=g_ascii_tolower(*p); p++; } std::string filename; std::list<std::string>::const_iterator it; for (it=ttspath.begin(); it!=ttspath.end(); ++it) { std::string suffix, aword; aword = *it + G_DIR_SEPARATOR_S + "a" + G_DIR_SEPARATOR_S + "a.mp3"; if (g_file_test(aword.c_str(), G_FILE_TEST_EXISTS)) suffix = ".mp3"; else suffix = ".wav"; filename = *it + G_DIR_SEPARATOR_S + lowerword[0] + G_DIR_SEPARATOR_S + lowerword + suffix; return_val = g_file_test(filename.c_str(), G_FILE_TEST_EXISTS); if (return_val) break; } } return return_val; } void ReadWord::Command_read(const gchar *word) { gchar *eword = g_shell_quote(word); gchar *command = g_strdup_printf(tts_program_cmdline.c_str(), eword); g_free(eword); system(command); g_free(command); } void ReadWord::RealTts_read(const gchar *word) { if (!ttspath.empty() && word && g_ascii_isalpha(word[0])) { std::string lowerword; const gchar *p = word; while (*p) { if (*p!=' ') lowerword+=g_ascii_tolower(*p); p++; } std::string filename; std::list<std::string>::const_iterator it; for (it=ttspath.begin(); it!=ttspath.end(); ++it) { std::string suffix, aword; aword = *it + G_DIR_SEPARATOR_S + "a" + G_DIR_SEPARATOR_S + "a.mp3"; if (g_file_test(aword.c_str(), G_FILE_TEST_EXISTS)) suffix = ".mp3"; else suffix = ".wav"; filename = *it + G_DIR_SEPARATOR_S + lowerword[0] + G_DIR_SEPARATOR_S + lowerword + suffix; if (g_file_test(filename.c_str(), G_FILE_TEST_EXISTS)) { play_wav_file(filename); break; } } } } const int Engine_RealTTS = 0; const int Engine_Command = 1; const int Engine_VirtualTTS_Base = 2; std::list<std::pair<std::string, int> > ReadWord::GetEngineList() { std::list<std::pair<std::string, int> > engine_list; if (!ttspath.empty()) { engine_list.push_back(std::pair<std::string, int>(_("Real People TTS"), Engine_RealTTS)); } size_t n = gpAppFrame->oStarDictPlugins->TtsPlugins.nplugins(); for (size_t i = 0; i < n; i++) { engine_list.push_back(std::pair<std::string, int>(gpAppFrame->oStarDictPlugins->TtsPlugins.tts_name(i), Engine_VirtualTTS_Base + i)); } if (use_command_tts && !tts_program_cmdline.empty()) { engine_list.push_back(std::pair<std::string, int>(_("Command TTS"), Engine_Command)); } return engine_list; } void ReadWord::ReadByEngine(const gchar *word, int engine_index) { if (engine_index == Engine_RealTTS) { RealTts_read(word); } else if (engine_index == Engine_Command) { Command_read(word); } else { gpAppFrame->oStarDictPlugins->TtsPlugins.saytext(engine_index - Engine_VirtualTTS_Base, word); } }

 

二 

(此处不必在此时改可以在运行软件的界面上修改)

在/stardict-3.0.1/src/conf.cpp中
#if defined(CONFIG_GTK) || defined (CONFIG_GPE)
add_entry("/apps/stardict/preferences/dictionary/play_command", std::string("play "));
#endif

把play改为mplayer。这个其实可以在安装运行以后再手动设置。

 

 

 

cd /usr/portage/app-dicts/stardict

 

 #ebuild  --help
  --skip-manifest       skip all manifest check(这个选项可以跳过md5 检查)

 


# ebuild   --skip-manifest stardict-3.0.1-r2.ebuild install  //将软件安装到 /var/tmp/portage/app-dicts/stardict-3.0.1-r2 /image/   

ebuild   --skip-manifest stardict-3.0.1-r2.ebuild  qmerge 将软件真正安装到系统   ( install 与qmerge 步骤不能交换)

 

此三步相当于emerge stardict 步骤

 

 

把发音库拷到/usr/share/OtdRealPeopleTTS下面,

tar -jxf OtdRealPeopleTTS.tar.gz2 -C /usr/share
运行,还是没有声音~
从上面的代码我们可以看到,StarDict只能读到/usr/share/OtdRealPeopleTTS下面路径和文件名都是小写的
声音文件。
这么多文件要一个个手工修改?当然不是了~
我这里有个shell脚本,修改这么多文件就靠它了~
运行它后,再运行StarDict应该就可以了

 

OtdRealPeopleTTS真人发音库下载地址:http://ubuntu:[email protected]/home/dbzhang800/wiki/OtdRealPeopleTTS.tar.gz
修改好的源码:http://myfilestorage.googlecode.com/files/stardict-3.0.1.tar.bz2
convert脚本(打开可以看到使用方法):http://myfilestorage.googlecode.com/files/convert

角本内容 笔录如下,你可将其保存为名为convert 的文件 照其注释运行

./convert  -l /usr/share/OtdRealPeopleTTS/

如此/usr/share/OtdRealPeopleTTS/ 下的所有文件都会被转化为小写,包括OtdRealPeopleTTS ,你需要手动将其改回大小写混用的,或者在软件界面理改成与其对应的路径

#!/bin/bash ############################################################ # 把目录下的所有文件和文件夹从大写转换到小写,并把文件名中的空格去掉 # 参数 convert -l ./mydir # -u: 小写到大写 # -l: 大写到小写 # dir 目录 ############################################################ hint () { echo " Usage: $0 [-l|-u] DIR1 [DIR2 DIR3...] -l to lowcase -u to upcase" exit 1 } if test $# -lt 2; then echo "Too few arguments." hint fi while [ "$1" ]; do case $1 in -l) ACTION="lo" shift 1 ;; -u) ACTION="up" shift 1 ;; *) if test -d $1; then DIR="$DIR $1" else echo "no such directory --- $1" hint fi shift ;; esac done # echo $ACTION # echo $DIR find $1 -name "* *" -print | while read name; do na=$(echo $name | sed 's/ //g') echo $na if [[ $name != $na ]]; then mv "$name" $na fi done FOUND=`find $DIR | sort -r` for i in $FOUND do DN=`dirname $i` echo "$DN" BS=`basename $i` echo "$BS" loBS=`echo $BS | tr '[A-Z]' '[a-z]'` upBS=`echo $BS | tr '[a-z]' '[A-Z]'` loDN=`echo $BS | tr '[A-Z]' '[a-z]'` upDN=`echo $BS | tr '[a-z]' '[A-Z]'` NAME1="$DN/$BS" if [ "$ACTION" = "lo" ]; then NAME2="$DN/$loBS" elif [ "$ACTION" = "up" ]; then NAME2="$DN/$upBS" fi if [ "$NAME1" = "$NAME2" ]; then echo "****: $NAME1 ---x--- $NAME2 identical!" else echo "- renaming $NAME1 --> $NAME2" mv "$NAME1" "$NAME2" fi done 

 

 

 

 

 

 

 

 

 

 

最近stardict启动经常失败,不知道为什么。有没有高人也遇到过这种情况?

tensecor@~$ stardict
PowerWord data parsing plug-in loaded.
Wiki data parsing plug-in loaded.
XDXF data parsing plug-in loaded.
HTML data parsing plug-in loaded.
WordNet dict rendering plug-in loaded.
Error, no spellchecking dictionary available!
Load /usr/lib/stardict/plugins/stardict_spell.so failed !
Dict.cn plug-in loaded.
WordNet data parsing plug-in loaded.
Man plug-in loaded.
QQWry plug-in loaded.
Segmentation fault

 

解决办法


 sudo mv /usr/lib/stardict/plugins/stardict_spell.so{,.bak}

 

或者直接删了 /usr/lib/stardict/plugins/stardict_spell.so

你可能感兴趣的:((转载+部分原创)星际译王在gentoo gnome (xfce4 上也可以)上的安装(并可以实现发音,)OtdRealPeopleTTS 不用非得把mp3 转化为wav)