|
(转载+部分原创)星际译王在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 文件内容
view plaincopy to clipboardprint?
1. #ifdef HAVE_CONFIG_H
2. # include "config.h"
3. #endif
4. #include <cstring>
5. #include <string>
6. #include <glib/gi18n.h>
7. #include "conf.h"
8. #include "desktop.hpp"
9. #include "utils.h"
10. #include "stardict.h"
11. #include "readword.h"
12. ReadWord::ReadWord()
13. {
14. const std::string &path = conf->get_string_at("dictionary/tts_path");
15. LoadRealTtsPath(path.c_str());
16. use_command_tts = conf->get_bool("/apps/stardict/preferences/dictionary/use_tts_program");
17. tts_program_cmdline = conf->get_string("/apps/stardict/preferences/dictionary/tts_program_cmdline");
18. }
19. ReadWordType ReadWord::canRead(const gchar *word)
20. {
21. if (RealTts_canRead(word))
22. return READWORD_REALTTS;
23. if (gpAppFrame->oStarDictPlugins->TtsPlugins.nplugins() > 0)
24. return READWORD_TTS;
25. if (use_command_tts && !tts_program_cmdline.empty())
26. return READWORD_COMMAND;
27. return READWORD_CANNOT;
28. }
29. void ReadWord::read(const gchar *word, ReadWordType type)
30. {
31. if (type == READWORD_REALTTS) {
32. RealTts_read(word);
33. } else if (type == READWORD_TTS) {
34. gpAppFrame->oStarDictPlugins->TtsPlugins.saytext(0, word);
35. } else if (type == READWORD_COMMAND) {
36. Command_read(word);
37. }
38. }
39. void ReadWord: oadRealTtsPath(const gchar *path)
40. {
41. std::list<std::string> paths;
42. std::string str;
43. const gchar *p, *p1;
44. p = path;
45. do {
46. p1 = strchr(p, '\n');
47. if (p1) {
48. str.assign(p, p1-p);
49. if (!str.empty())
50. paths.push_back(str);
51. p = p1+1;
52. }
53. } while (p1);
54. str = p;
55. if (!str.empty())
56. paths.push_back(str);
57. ttspath.clear();
58. std::list<std::string>::const_iterator it;
59. for (it=paths.begin(); it!=paths.end(); ++it) {
60. #ifdef _WIN32
61. if (it->length()>1 && (*it)[1]==':') {
62. if (g_file_test(it->c_str(), G_FILE_TEST_EXISTS))
63. ttspath.push_back(*it);
64. } else {
65. str = gStarDictDataDir + G_DIR_SEPARATOR_S + *it;
66. if (g_file_test(str.c_str(), G_FILE_TEST_EXISTS))
67. ttspath.push_back(str);
68. }
69. #else
70. if (g_file_test(it->c_str(), G_FILE_TEST_EXISTS))
71. ttspath.push_back(*it);
72. #endif
73. }
74. }
75. bool ReadWord::RealTts_canRead(const gchar *word)
76. {
77. bool return_val = false;
78. if (!ttspath.empty() && word && g_ascii_isalpha(word[0])) {
79. std::string lowerword;
80. const gchar *p = word;
81. while (*p) {
82. if (*p!=' ')
83. lowerword+=g_ascii_tolower(*p);
84. p++;
85. }
86. std::string filename;
87. std::list<std::string>::const_iterator it;
88. for (it=ttspath.begin(); it!=ttspath.end(); ++it) {
89. std::string suffix, aword;
90. aword = *it + G_DIR_SEPARATOR_S + "a" + G_DIR_SEPARATOR_S + "a.mp3";
91. if (g_file_test(aword.c_str(), G_FILE_TEST_EXISTS))
92. suffix = ".mp3";
93. else
94. suffix = ".wav";
95. filename = *it + G_DIR_SEPARATOR_S + lowerword[0] + G_DIR_SEPARATOR_S + lowerword + suffix;
96. return_val = g_file_test(filename.c_str(), G_FILE_TEST_EXISTS);
97. if (return_val)
98. break;
99. }
100. }
101. return return_val;
102. }
103. void ReadWord::Command_read(const gchar *word)
104. {
105. gchar *eword = g_shell_quote(word);
106. gchar *command = g_strdup_printf(tts_program_cmdline.c_str(), eword);
107. g_free(eword);
108. system(command);
109. g_free(command);
110. }
111. void ReadWord::RealTts_read(const gchar *word)
112. {
113. if (!ttspath.empty() && word && g_ascii_isalpha(word[0])) {
114. std::string lowerword;
115. const gchar *p = word;
116. while (*p) {
117. if (*p!=' ')
118. lowerword+=g_ascii_tolower(*p);
119. p++;
120. }
121. std::string filename;
122. std::list<std::string>::const_iterator it;
123. for (it=ttspath.begin(); it!=ttspath.end(); ++it) {
124. std::string suffix, aword;
125. aword = *it + G_DIR_SEPARATOR_S + "a" + G_DIR_SEPARATOR_S + "a.mp3";
126. if (g_file_test(aword.c_str(), G_FILE_TEST_EXISTS))
127. suffix = ".mp3";
128. else
129. suffix = ".wav";
130. filename = *it + G_DIR_SEPARATOR_S + lowerword[0] + G_DIR_SEPARATOR_S + lowerword + suffix;
131. if (g_file_test(filename.c_str(), G_FILE_TEST_EXISTS)) {
132. play_wav_file(filename);
133. break;
134. }
135. }
136. }
137. }
138. const int Engine_RealTTS = 0;
139. const int Engine_Command = 1;
140. const int Engine_VirtualTTS_Base = 2;
141. std::list<std::pair<std::string, int> > ReadWord::GetEngineList()
142. {
143. std::list<std::pair<std::string, int> > engine_list;
144. if (!ttspath.empty()) {
145. engine_list.push_back(std::pair<std::string, int>(_("Real People TTS"), Engine_RealTTS));
146. }
147. size_t n = gpAppFrame->oStarDictPlugins->TtsPlugins.nplugins();
148. for (size_t i = 0; i < n; i++) {
149. engine_list.push_back(std::pair<std::string, int>(gpAppFrame->oStarDictPlugins->TtsPlugins.tts_name(i), Engine_VirtualTTS_Base + i));
150. }
151. if (use_command_tts && !tts_program_cmdline.empty()) {
152. engine_list.push_back(std::pair<std::string, int>(_("Command TTS"), Engine_Command));
153. }
154. return engine_list;
155. }
156. void ReadWord::ReadByEngine(const gchar *word, int engine_index)
157. {
158. if (engine_index == Engine_RealTTS) {
159. RealTts_read(word);
160. } else if (engine_index == Engine_Command) {
161. Command_read(word);
162. } else {
163. gpAppFrame->oStarDictPlugins->TtsPlugins.saytext(engine_index - Engine_VirtualTTS_Base, word);
164. }
165. }
#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: oadRealTtsPath(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:ubuntuftp@ftp.ubun ... ealPeopleTTS.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 ,你需要手动将其改回大小写混用的,或者在软件界面理改成与其对应的路径
view plaincopy to clipboardprint?
1. #!/bin/bash
2. ############################################################
3. # 把目录下的所有文件和文件夹从大写转换到小写,并把文件名中的空格去掉
4. # 参数 convert -l ./mydir
5. # -u: 小写到大写
6. # -l: 大写到小写
7. # dir 目录
8. ############################################################
9. hint ()
10. {
11. echo " Usage: $0 [-l|-u] DIR1 [DIR2 DIR3...]
12. -l to lowcase
13. -u to upcase"
14. exit 1
15. }
16. if test $# -lt 2; then
17. echo "Too few arguments."
18. hint
19. fi
20. while [ "$1" ]; do
21. case $1 in
22. -l)
23. ACTION="lo"
24. shift 1
25. ;;
26. -u)
27. ACTION="up"
28. shift 1
29. ;;
30. *)
31. if test -d $1; then
32. DIR="$DIR $1"
33. else
34. echo "no such directory --- $1"
35. hint
36. fi
37. shift
38. ;;
39. esac
40. done
41. # echo $ACTION
42. # echo $DIR
43. find $1 -name "* *" -print |
44. while read name; do
45. na=$(echo $name | sed 's/ //g')
46. echo $na
47. if [[ $name != $na ]]; then
48. mv "$name" $na
49. fi
50. done
51. FOUND=`find $DIR | sort -r`
52. for i in $FOUND
53. do
54. DN=`dirname $i`
55. echo "$DN"
56. BS=`basename $i`
57. echo "$BS"
58. loBS=`echo $BS | tr '[A-Z]' '[a-z]'`
59. upBS=`echo $BS | tr '[a-z]' '[A-Z]'`
60.
61. loDN=`echo $BS | tr '[A-Z]' '[a-z]'`
62. upDN=`echo $BS | tr '[a-z]' '[A-Z]'`
63.
64. NAME1="$DN/$BS"
65. if [ "$ACTION" = "lo" ]; then
66. NAME2="$DN/$loBS"
67. elif [ "$ACTION" = "up" ]; then
68. NAME2="$DN/$upBS"
69. fi
70. if [ "$NAME1" = "$NAME2" ]; then
71. echo "****: $NAME1 ---x--- $NAME2 identical!"
72. else
73. echo "- renaming $NAME1 --> $NAME2"
74. mv "$NAME1" "$NAME2"
75. fi
76. done
#!/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
解决办法 |
|