Google文字转语音API

use*_*017 71 text-to-speech google-text-to-speech

我想知道如何在我的.NET项目中使用Google Text-to-Speech API.我想我需要调用一个URL来使用Web服务,但对我来说这个想法并不清楚.有人可以帮忙吗?

Sch*_*rgh 62

老答案:

尝试使用此网址:http: //translate.google.com/translate_tts? tl = en&q = Hello%20World它将自动生成一个wav文件,您可以通过任何.net编程轻松获取HTTP请求.

编辑:

哦谷歌,你以为你可以通过脆弱的http标头验证来阻止人们使用你的精彩服务.

这是一个以多种语言获得响应的解决方案(我会尝试添加更多内容):

的NodeJS

// npm install `request`
const fs = require('fs');
const request = require('request');
const text = 'Hello World';

const options = {
    url: `https://translate.google.com/translate_tts?ie=UTF-8&q=${encodeURIComponent(text)}&tl=en&client=tw-ob`,
    headers: {
        'Referer': 'http://translate.google.com/',
        'User-Agent': 'stagefright/1.2 (Linux;Android 5.0)'
    }
}

request(options)
    .pipe(fs.createWriteStream('tts.mp3'))
Run Code Online (Sandbox Code Playgroud)

卷曲

curl 'https://translate.google.com/translate_tts?ie=UTF-8&q=Hello%20Everyone&tl=en&client=tw-ob' -H 'Referer: http://translate.google.com/' -H 'User-Agent: stagefright/1.2 (Linux;Android 5.0)' > google_tts.mp3
Run Code Online (Sandbox Code Playgroud)

请注意,标题基于@Chris Cirefice的示例,如果它们在某些时候停止工作,我将尝试重新创建此代码运行的条件.当前标题的所有学分都归他所有,也是WireShark的精彩工具.(也感谢谷歌没有打补丁)

  • Google已实施滥用保护,因此此网址现在会重定向到CAPTCHA页面.要解决此问题,请参阅[我的答案 - 更新](http://stackoverflow.com/a/31791632/1986871). (10认同)
  • 上面的链接已被破坏.Google翻译API文档位于https://developers.google.com/translate/. (3认同)
  • 试试这个http://translate.google.com/translate_tts?tl=en&q=Hello%20World显然,从Stackoverflow引用链接时出现问题,但我通过JS尝试了HTTP请求,并将其与HTML5声音api一起使用,正常工作精细! (2认同)
  • 如果您在隐身浏览器会话中尝试它,它是有效的,所以是的,请求中不应该有referer标头. (2认同)

Chr*_*ice 48

在更新Schahriar SaffarShargh的回答时,Google最近实施了"Google滥用"功能,因此无法将任何常规旧的HTTP GET发送到以下网址:

http://translate.google.com/translate_tts?tl=en&q=Hello%20World

以前工作得很好,花花公子.现在,通过这样的链接向您展示了一个CAPTCHA.这也会影响浏览器外的HTTP GET请求(例如使用cURL),因为使用该URL会重定向到滥用保护页面(CAPTCHA).

首先,您必须将query参数添加client到请求URL:

http://translate.google.com/translate_tts?tl=en&q=Hello%20World&client=t

谷歌翻译发送&client=t,所以你也应该发送.

在发出HTTP请求之前,请确保设置Referer标头:

Referer: http://translate.google.com/

显然,User-Agent标题也是必需的,但有趣的是它可以是空白的:

User-Agent:

编辑:注意 - 在某些用户代理(例如Android 4.X)上,不会发送自定义 User-Agent标头,这意味着Google不会为请求提供服务.为了解决这个问题,我只需将其设置为有效的,例如.如果Google的服务器没有响应,请使用Wireshark来调试请求(就像我一样),并确保在这些服务器中正确设置这些标头!如果请求失败,Google将回复,然后重定向到CAPTCHA页面.User-Agentstagefright/1.2 (Linux;Android 5.0)GET503 Service Unavailable

这个解决方案有点脆弱; 谷歌完全有可能在未来改变他们处理这些请求的方式,所以最后我建议让谷歌制作一个真正的 API端点(免费或付费),我们可以使用它而不会因伪造HTTP标头而感到肮脏.


编辑2:对于那些感兴趣的人,这个cURL命令应该可以很好地下载英文Hello的mp3 :

curl 'http://translate.google.com/translate_tts?ie=UTF-8&q=Hello&tl=en&client=t' -H 'Referer: http://translate.google.com/' -H 'User-Agent: stagefright/1.2 (Linux;Android 5.0)' > google_tts.mp3
Run Code Online (Sandbox Code Playgroud)

您可能已经注意到,我已在请求中设置了两个RefererUser-Agent标头,并将client=t参数添加到查询字符串中.您可以选择使用https而不是http您的选择!


编辑3:Google现在需要为每个GET请求提供一个令牌(tk在查询字符串中注明).下面是修改后的cURL命令,可以正确下载TTS mp3:

curl 'https://translate.google.com/translate_tts?ie=UTF-8&q=hello&tl=en&tk=995126.592330&client=t' -H 'user-agent: stagefright/1.2 (Linux;Android 5.0)' -H 'referer: https://translate.google.com/' > google_tts.mp3

请注意查询字符串中的&tk = 995126.592330 ; 这是新令牌.我通过按下扬声器图标translate.google.com并查看GET请求获得此令牌.我只是将这个querystring参数添加到以前的cURL命令中,并且它可以工作.

注意:显然这个解决方案非常脆弱,并且在谷歌的架构师的心血来潮中突然出现,他们引入了新的东西,比如请求所需的令牌.这个令牌可能明天不起作用(虽然我会检查并报告)...重点是,依靠这种方法是不明智的; 相反,应该转向商业TTS解决方案,特别是如果在生产中使用TTS.

有关令牌生成的进一步说明以及您可能对此做些什么,请参阅Boude的答案.


如果此解决方案在将来的任何时间中断,请对此答案发表评论,以便我们可以尝试找到它的解决方案!

  • 这似乎又被打破了.我的代码基于这篇文章工作了几个月(jan-feb '17),但现在已经破了(2017年4月).用client = tw-ob替换client = t似乎可以解决这个问题.请验证并更新答案. (2认同)

Bou*_*ude 17

扩大克里斯的回答.我设法对令牌生成过程进行逆向工程.

请求的标记基于文本和页面脚本中设置的全局TKK变量.这些在JavaScript中进行散列,从而产生tk参数.

在页面脚本的某处你会发现这样的东西:

TKK='403413';

这是自纪元以来经过的小时数.

该文本在以下函数中进行了抽取(稍微进行了反混淆):

var query = "Hello person";
var cM = function(a) {
    return function() {
        return a
    }
};
var of = "=";
var dM = function(a, b) {
    for (var c = 0; c < b.length - 2; c += 3) {
        var d = b.charAt(c + 2),
            d = d >= t ? d.charCodeAt(0) - 87 : Number(d),
            d = b.charAt(c + 1) == Tb ? a >>> d : a << d;
        a = b.charAt(c) == Tb ? a + d & 4294967295 : a ^ d
    }
    return a
};

var eM = null;
var cb = 0;
var k = "";
var Vb = "+-a^+6";
var Ub = "+-3^+b+-f";
var t = "a";
var Tb = "+";
var dd = ".";
var hoursBetween = Math.floor(Date.now() / 3600000);
window.TKK = hoursBetween.toString();

fM = function(a) {
    var b;
    if (null === eM) {
        var c = cM(String.fromCharCode(84)); // char 84 is T
        b = cM(String.fromCharCode(75)); // char 75 is K
        c = [c(), c()];
        c[1] = b();
        // So basically we're getting window.TKK
        eM = Number(window[c.join(b())]) || 0
    }
    b = eM;

    // This piece of code is used to convert d into the utf-8 encoding of a
    var d = cM(String.fromCharCode(116)),
        c = cM(String.fromCharCode(107)),
        d = [d(), d()];
    d[1] = c();
    for (var c = cb + d.join(k) +
            of, d = [], e = 0, f = 0; f < a.length; f++) {
        var g = a.charCodeAt(f);

        128 > g ? d[e++] = g : (2048 > g ? d[e++] = g >> 6 | 192 : (55296 == (g & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ? (g = 65536 + ((g & 1023) << 10) + (a.charCodeAt(++f) & 1023), d[e++] = g >> 18 | 240, d[e++] = g >> 12 & 63 | 128) : d[e++] = g >> 12 | 224, d[e++] = g >> 6 & 63 | 128), d[e++] = g & 63 | 128)
    }


    a = b || 0;
    for (e = 0; e < d.length; e++) a += d[e], a = dM(a, Vb);
    a = dM(a, Ub);
    0 > a && (a = (a & 2147483647) + 2147483648);
    a %= 1E6;
    return a.toString() + dd + (a ^ b)
};

var token = fM(query);
var url = "https://translate.google.com/translate_tts?ie=UTF-8&q="  + encodeURI(query) + "&tl=en&total=1&idx=0&textlen=12&tk=" + token + "&client=t";
document.write(url);
Run Code Online (Sandbox Code Playgroud)

我设法在我的gTTS分支中成功将它移植到python ,所以我知道这很有用.

编辑:到目前为止,gTTS使用的令牌生成代码已移至gTTS-token.

编辑2:谷歌已经改变了API(2016-05-10左右),这种方法需要进行一些修改.我正在研究这个问题.在此期间,将客户端更改为tw-ob似乎有效.

编辑3:

这些变化很小,但至少可以说是烦人的.TKK现在有两个部分.看起来像406986.2817744745.如你所见,第一部分保持不变.第二部分是两个看似随机数的总和.TKK=eval('((function(){var a\x3d2680116022;var b\x3d137628723;return 406986+\x27.\x27+(a+b)})())');\x3d意味着=\x27'.每隔一分钟,a和b都会改变.在算法的最后一步中,令牌由第二部分进行异或.

新令牌生成代码是:

var xr = function(a) {
    return function() {
        return a
    }
};
var yr = function(a, b) {
    for (var c = 0; c < b.length - 2; c += 3) {
        var d = b.charAt(c + 2)
          , d = "a" <= d ? d.charCodeAt(0) - 87 : Number(d)
          , d = "+" == b.charAt(c + 1) ? a >>> d : a << d;
        a = "+" == b.charAt(c) ? a + d & 4294967295 : a ^ d
    }
    return a
};
var zr = null;
var Ar = function(a) {
    var b;
    if (null  !== zr)
        b = zr;
    else {
        b = xr(String.fromCharCode(84));
        var c = xr(String.fromCharCode(75));
        b = [b(), b()];
        b[1] = c();
        b = (zr = window[b.join(c())] || "") || ""
    }
    var d = xr(String.fromCharCode(116))
      , c = xr(String.fromCharCode(107))
      , d = [d(), d()];
    d[1] = c();
    c = "&" + d.join("") + 
    "=";
    d = b.split(".");
    b = Number(d[0]) || 0;
    for (var e = [], f = 0, g = 0; g < a.length; g++) {
        var l = a.charCodeAt(g);
        128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 : (55296 == (l & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023),
        e[f++] = l >> 18 | 240,
        e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224,
        e[f++] = l >> 6 & 63 | 128),
        e[f++] = l & 63 | 128)
    }
    a = b;
    for (f = 0; f < e.length; f++)
        a += e[f],
        a = yr(a, "+-a^+6");
    a = yr(a, "+-3^+b+-f");
    a ^= Number(d[1]) || 0;
    0 > a && (a = (a & 2147483647) + 2147483648);
    a %= 1E6;
    return c + (a.toString() + "." + (a ^ b))
}
;
Ar("test");
Run Code Online (Sandbox Code Playgroud)

当然我不能生成有效的URL,因为我不知道a和b是如何生成的.

  • @Syom [在将客户端更改为tw-ob时,一直存在一种更简单的方法.](http://stackoverflow.com/a/32053452/1017005)我目前正在调查Google所做的更改.它们似乎很小,但它们用随机文本扩展了它们的种子,每分钟都会改变.一旦我知道更多,我会报告回来. (3认同)
  • 感谢您添加另一个答案,+ 1!我将编辑我的答案,指出你的进一步解释. (2认同)

DMS*_*Jax 13

另一个选择是:responsivevoice.org一个简单的例子JsFiddle就在这里

HTML

<div id="container">
<input type="text" name="text">
<button id="gspeech" class="say">Say It</button>
<audio id="player1" src="" class="speech" hidden></audio>
</div>
Run Code Online (Sandbox Code Playgroud)

JQuery的

$(document).ready(function(){

 $('#gspeech').on('click', function(){

        var text = $('input[name="text"]').val();
        responsiveVoice.speak("" + text +"");
        <!--  http://responsivevoice.org/ -->
    });

});
Run Code Online (Sandbox Code Playgroud)

外部资源:

https://code.responsivevoice.org/responsivevoice.js

  • 这实际上是有效的,无需破解或担心某些东西会损坏。 (2认同)

Th3*_*ter 5

您可以使用Wget:D下载语音

wget -q -U Mozilla "http://translate.google.com/translate_tts?tl=en&q=Hello"
Run Code Online (Sandbox Code Playgroud)

将输出保存到mp3文件中:

wget -q -U Mozilla "http://translate.google.com/translate_tts?tl=en&q=Hello" -O hello.mp3
Run Code Online (Sandbox Code Playgroud)

请享用 !!


Rob*_*Rob 5

好的,因此Google已经引入了令牌(请参阅新网址中的tk参数),而旧的解决方案似乎无效。我找到了一种替代方法-我什至认为它听起来更好,声音更多!该命令不是很漂亮,但是可以。请注意,这仅用于测试目的(我将其用于一个小的domotica项目),如果您打算将其用于商业用途,请使用acapella-group的真实版本。

curl $(curl --data 'MyLanguages=sonid10&MySelectedVoice=Sharon&MyTextForTTS=Hello%20World&t=1&SendToVaaS=' 'http://www.acapela-group.com/demo-tts/DemoHTML5Form_V2.php' | grep -o "http.*mp3") > tts_output.mp3
Run Code Online (Sandbox Code Playgroud)

一些受支持的声音是:

  • 沙龙
  • 艾拉(真正的孩子的声音)
  • EmilioEnglish(正版儿童语音)
  • Josh(纯正的儿童声音)
  • 卡伦
  • 肯尼(儿童语音)
  • 劳拉
  • 米迦
  • 耐莉(人工儿童语音)
  • 竿
  • 瑞安
  • 扫罗
  • 斯科特(真正的少年声音)
  • 特蕾西
  • ValeriaEnglish(正版儿童语音)
  • WillBadGuy(情感声音)
  • WillFromAfar(情感声音)
  • WillHappy(情感声音)
  • WillLittleCreature(情感声音)
  • WillOldMan(情感声音)
  • WillSad(情感声音)
  • WillUpClose(情感声音)

它还支持多种语言和更多声音-为此,我将引导您访问他们的网站;http://www.acapela-group.com/