最近一直在喜马拉雅听有声小说《轮转长生》。每天会更新两集。但由于我记忆力差,所以如果等着每天的小说更新,就会由于记不住之前的情节而感觉很迷茫。所以我去搜了下,发现了这个小说的文本。于是就想如果能用Text To Speech把文字变成语音的话,不就能一直听下去,而不用等播音了嘛。
于是我就去搜各种TTS API Chinese。发现了iSpeech, tts-api,voicerss之类的服务。确实,TTS技术发展了这么多年,肯定有巨多的服务提供商。但翻了一圈发现中文的效果都很差。郁闷的时候想起Google Translate的TTS,就是那个整天被人当B-Box玩的东西。
Google-TTS
这是一个非官方的Google TTS库,但是文档里说到Playbackwill only work when running the script locally as Google's server only returns audio if you can prevent the browser from sending the Referrer HTTP Header to their server
,看来是Google对referrer做了检查。不过这点后面看起来似乎没那么严格。
我们先用个简单的页面测试一下播音(注意科学上网),播放一小段中文听起来还不错。
<html>
<head lang="en">
<script type="text/javascript" src="https://rawgithub.com/hiddentao/google-tts/master/google-tts.min.js"></script>
</head>
<body>
<script>
var tts = new GoogleTTS('zh-CN');
tts.play('你好呀呀呀呀', 'zh-CN', function (err) {
console.log('complete');
});
</script>
</body>
拿小说
这就用到了之前介绍的技术Import.io。安装桌面应用,Create API from URL 2.0,找一个详情页,比如第一百五十三章 照片上的三口之家,选择文章内容的div改column名为text。就可以create啦。
看一下文章的url是连续的,好,那就用node写个循环,然后用AVOS把文章内容保存下来。
// ...省略初始化
var Chapter = AV.Object.extend('Chapter');
_.each(_.map(_.range(27888, 27996), function (num) {
return 'http://book.guidaye.com/daomu/85/' + num + '.html';
}), function (url) {
var q = new AV.Query(Chapter);
q.equalTo('url', url);
q.first()
.then(function (chapter) {
if (chapter) {
console.log('exists,%s',url);
} else {
unirest.get('https://api.import.io/store/data/c2f29086-18a8-4c7b-9d5d-6ea1d54a9bc5/_query')
.query({
'input/webpage/url': url,
'_user': '[UER]',
'_apikey': '[API KEY]'
})
.end(function (response) {
new Chapter({
url: response.body.pageUrl,
text: response.body.results[0].text
}).save().then(function () {
console.log('done,%s', response.body.pageUrl);
}, function (err) {
console.log(err);
})
})
}
})
})
跑一遍基本就ok啦,如果有发生错误的就再执行一遍验证下。
读小说
好,我们要一个前端页面来读小说。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="https://rawgithub.com/hiddentao/google-tts/master/google-tts.min.js"></script>
<script src="https://leancloud.cn/scripts/lib/av-0.4.5.min.js"></script>
</head>
<body>
<div id='playing'></div>
<script>
AV.initialize("[APPID]", "[APPKEY]");
function speakChapter(chapterNum) {
var url = 'http://book.guidaye.com/daomu/85/' + chapterNum + '.html';
var Chapter = AV.Object.extend('Chapter');
var query = new AV.Query(Chapter);
query.equalTo('url', url);
query.first()
.then(function (chapter) {
document.getElementById('playing').text = "playing:" + url;
console.log('playing,%s', chapter.get('url'));
var tts = new GoogleTTS('zh-CN');
tts.play(chapter.get('text'), "zh-CN", function (err) {
console.log('complete,%s', chapter.url);
});
}, function (err) {
console.log(err);
})
}
//speakChapter(27889);
</script>
</body>
</html>
我们在console里实验一下speakChapter(27889);
,终于开始读啦!听起来感觉还好,但还是TTS的最大普遍问题:语气不对。每个人说的,旁白说的都是一个味道...另一个问题是,读文章的时候一段以后会需要几秒钟的加载时间去加载下一段。而这个gap很有可能是一句话的中间。这就让人听起来很诡异了...“雷英...(上个厕所)...雄笑了笑”...
最后说一下浏览器问题。我发现safari打开这个页面就能正常播放,所以,也还算可忍~
好啦,按这个思路我们可以把自己喜欢的小说播放出来~如果你想把声音保存成mp3的话,可以用node-google-text-to-speech来把数据pipe到文件里,再用pushbullet类的产品把数据同步到移动端去。
29天啦,坐等吃串!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。