背景
Ubuntu 11.10 環境で Open JTalk で TTS(Text to Speech)させようとしたら 10.04 の時のように簡単に導入できなかったので、他の TTS 手段を探していて行き着きました。
はじめに
Google TTS は Google 翻訳で結果を喋らせたりするときに使われています。これは非公式ですが API を叩くと利用することができます(参考:Googleのテキスト読み上げ非公式API発見 | TechCrunch Japan)。
例
(2012/03/19 「!」が含まれているとエラーになってしまっていたので修正)
こいつを C++ で引っ張ってきてしまおう、ということをやってみます。
CLXを利用してデータを取得
CLXは本家によると以下のようなものです。
CLX C++ Libraries は,文字列処理やネットワークプログラミングの補助などを行うための, ヘッダファイルのみで構成された C++ ライブラリです. CLX C++ Libraries は, BSDライセンスで配布しています.ソースコードの複製・改変は自由ですが, 自己責任でお願い致します.
ヘッダオンリで動くのでコンパイルも楽々です。
インストールも簡単です。
ここからファイルを落としてきて解凍&パスの通った場所に配置するだけです。
Ubuntu での例
tar xzvf clx_0.18.2.tar.gz sudo mv clx /usr/local/include/
ではでは早速 Google TTS に接続してファイルを落としてきましょう。
test.cpp
#include <fstream> #include <clx/http.h> #include <clx/uri.h> int main() { // 接続&データ取得 clx::http session(clx::uri::encode("translate.google.com")); session.get(clx::uri::encode("/translate_tts?tl=ja&q=aiueo")); // 出力 std::ofstream ofs("test.mp3", std::ios::binary); ofs << session.body() << std::endl; }
コンパイルオプションはいりません。
g++ test.cpp
で、実行すると「えーあいーゆーいーおー」としゃべる mp3 が出来ます。
日本語を翻訳する
しかし「aiueo」のところを「あいうえお」などとした場合は、良く分からない言葉をしゃべる mp3 になってしまいます。これは User-Agent を見て弾かれていることが原因のようです(参考:Google TTS(日本語)を使う | www.ffffine.net)。ソースを見てみましたが、clx::http 内では特に User-Agent を与えていません。そして外部からこれを設定するような関数もありません。ので、直接 http.h をいじって、User-Agent をごまかしてしまいます。
clx/http.h - 242行目
query << "Host: " << host_ << "\r\n"; query << "User-Agent: Mozilla/5.5\r\n"; // 追記
これで次のように「aiueo」部分を変えたファイルをコンパイルすれば正常に再生されます。
#include <fstream> #include <clx/http.h> #include <clx/uri.h> int main() { // 接続&データ取得 clx::http session(clx::uri::encode("translate.google.com")); session.get(clx::uri::encode("/translate_tts?tl=ja&q=ゆっくりしていってね!")); // 出力 std::ofstream ofs("yukkuri.mp3", std::ios::binary); ofs << session.body() << std::endl; }
CLX 便利です。
失敗編
Boost.Asioを使ってみた
#include <fstream> #include <iostream> #include <string> #include <boost/asio.hpp> #include <boost/format.hpp> int main(int argc, char const* argv[]) { // 喋らせたい言葉 const std::string text = "ゆっくりしていってね"; // google tts に接続 boost::asio::ip::tcp::iostream s( "translate.google.com", "http" ); // 送信 std::cout << argv[1] << std::endl; s << boost::format("GET /translate_tts?tl=ja&q=%1% HTTP/1.1\r\n") % text; s << "Host: translate.google.com\r\n"; s << "User-Agent:Mozilla/5.5\r\n"; s << "\r\n"; s << std::flush; // 受信 std::ofstream fout("test.mpg", std::ios::binary); std::string buf; while(std::getline(s, buf)) { fout << buf << std::endl; } }
勝手に終わってくれない。。ので Ctrl + C して終了するとファイルは出来ています。ただ最後がちょっと途切れる。
cpp-netlibを使ってみようとした
Proposed for Boost な cpp-netlib を使おうとしたのですが、ちょっと大変そうだったので断念。。 Boost に組み込まれてから再チャレンジしようと思います。
おわりに
rti さんも作られていたようです!
2012-03-11 14:51:00 via web to @hecomi
@super_rti うぉぉ、気づきませんでした、すごいw エントリにリンク貼らせて下さい。
2012-03-11 14:54:56 via TweetDeck to @super_rti
@hecomi どうぞどうぞw boost.asioで http操作ってすごく面倒で大変。昔作ってたURlパーサとかそこらへんを流用してなんとかできた感じ。 ctx楽そうで裏山鹿。URL
2012-03-11 15:02:55 via web to @hecomi