Google文字转语音API


Answers:


63

旧答案:

尝试使用以下URL:http : //translate.google.com/translate_tts? tl=zh-CN&q=Hello% 20World它会自动生成一个wav文件,您可以通过任何.net编程轻松地通过HTTP请求获得该文件。

编辑:

哦,谷歌,您认为您可以通过脆弱的http标头验证来阻止人们使用您的出色服务。

这是获得多种语言回复的解决方案(我们将尝试添加更多内容):

节点JS

// 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'))

卷曲

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

请注意,标头基于@Chris Cirefice的示例,如果标头在某些时候停止工作,我将尝试重新创建此代码起作用的条件。当前标头的所有功劳都归功于他和WireShark这个很棒的工具。(也感谢Google未对此进行修补)


3
上面的链接已断开。Google Translate API文档位于developers.google.com/translate
埃里克·史密斯


2
如果您在隐身浏览器会话中尝试它,它将起作用,因此,是的,请求中不应包含引荐来源标头。
David d C e Freitas 2012年

上述网址是否有速率限制?
kouton

12
Google已实施了滥用保护措施,因此该URL现在重定向到CAPTCHA页面。为了解决这个问题,请参阅我的最新更新
克里斯·西里菲斯

49

在对Schahriar SaffarShargh的答案的更新中,Google最近实施了“ Google滥用”功能,从而无法将任何常规的旧HTTP GET发送到以下网址:

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

以前效果还不错。现在,点击此链接将为您提供一个验证码。这也会影响浏览器外的HTTP GET请求(例如使用cURL),因为使用该URL可以重定向到滥用保护页面(CAPTCHA)。

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

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

Google翻译发送&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

这个解决方案有点脆弱;Google将来很有可能会改变其处理这些请求的方式,因此最后我建议让Google制作一个我们可以使用的真实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

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


编辑3:Google现在要求每个GET请求都有一个令牌(tk在querystring中由标记)。下面是经过修改的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命令中,并且它可以工作。

注意:显然,该解决方案非常脆弱,并且打破了Google架构师的想法,他们引入了新的要求,例如令牌。这个令牌明天可能不起作用(尽管我会检查并报告)……重点是,依靠此方法并不明智;相反,应该转向商业化的TTS解决方案,尤其是在生产中使用TTS时。

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


如果此解决方案将来无法解决,请在此答案上留下您的评论,以便我们可以尝试找到解决方法!


1
@Syom另请参阅我的编辑:),检查Wireshark或其他网络分析工具,以确保正确发送了标头。正如我在回答中提到的那样,某些设备可能会剥离自定义标头,或者执行其他不希望有的事情导致请求失败。
克里斯·西里菲斯

1
@Syom有趣的是,如果没有它,我将无法运行它Referer……好吧,一个额外的标题“以防万一”现在就不会受到伤害;)
Chris Cirefice

1
@ dr.doom很高兴知道我在帮忙:)
Chris Cirefice 2015年

1
@Akiva只要您使用的语言可以打开文件,那绝对有可能。您可以使用字符串连接来构建CURL命令,或使用字符串替换来替换q=XXXXtl=XX部分(这是首选)。请注意,整个字符串必须经过URL编码,否则文本查询中的空格将导致超时。因此q=Hello world必须编码为q=Hello%20world
克里斯·西里菲斯

2
这似乎又被打破了。基于这篇文章的我的代码工作了几个月(大约在jan-feb '17左右),但是现在已经失效了(apr '17)。用client = tw-ob替换client = t似乎可以解决问题。请验证并更新答案。
杜布(Doub)'17

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);

我设法在gTTS的fork中成功将此端口移植到python ,所以我知道这是可行的

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

编辑2:Google已更改了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都每隔UTC分钟更改一次。在算法的最后步骤之一,令牌由第二部分进行XOR。

新的令牌生成代码为:

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");

当然,我不能再生成有效的url,因为我不知道a和b的生成方式。


2
感谢您添加另一个答案,+ 1!我将编辑我的答案以指向您的答案,以进一步说明。
克里斯·西里菲斯

大!非常感谢。
西蒙

1
Google再次更改了令牌结构。现在,该算法不起作用。有什么新的解决方案吗?
西蒙

3
@Syom在将客户端更改为tw-ob时,始终存在一种更简单的方法。我目前正在调查Google所做的更改。它们似乎很小,但它们使用每分钟更改一次的随机文本扩展了种子。我会在知道更多信息后再回报。
布德

感谢您的回复。我将寻找可能的解决方案。
西蒙(Simon)

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>

jQuery查询

$(document).ready(function(){

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

});

外部资源:

https://code.sensitivevoice.org/sensitivevoice.js


1
这实际上是有效的,而无需破解或担心发生故障。
imrek

5

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

wget -q -U Mozilla "http://translate.google.com/translate_tts?tl=en&q=Hello"

将输出保存到mp3文件中:

wget -q -U Mozilla "http://translate.google.com/translate_tts?tl=en&q=Hello" -O hello.mp3

请享用 !!


5

好吧,因此Google引入了令牌(请参阅新url中的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

一些受支持的声音是:

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

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


嗨,您能发表一下如何在php中使用吗?
西蒙

就像@srik所报告的那样,此解决方案已失效,并且至今仍然有效。似乎Acapela集团删除了该php文件,以便从其服务器直接访问。
Code Doggo

1
似乎可以再次使用,但是acapela小组此后在tts中添加了背景音乐,因此现在使用起来有点分散注意力。虽然质量很好。
曹萌


4

Google文字转语音

<!DOCTYPE html>
<html>
    <head>
        <script>
            function play(id){
            var text = document.getElementById(id).value;
            var url = 'http://translate.google.com/translate_tts?tl=en&q='+text;
            var a = new Audio(url);
                a.play();
            }
        </script>
    </head>
    <body>
        <input type="text" id="text" />
        <button onclick="play('text');"> Speak it </button>
    </body>
</html>

3

3
使用wget执行wget translation.google.com/translate_tts?tl=zh-CN&q=Hello%20World 会发送此错误HTTP请求,等待响应... 403禁止2014-08-30 14:43:26错误403:禁止。
2014年

伙计们,我正在使用类似于此代码的TTS。“ translate.google.com/translate_tts吗?我应该允许somethime下载文件吗?
阿米尔2015年



1

转到console.developer.google.com登录并获取API密钥,或使用Microsoft bing的API
https://msdn.microsoft.com/en-us/library/?f=255&MSPPError=-2147217396

甚至更好地使用AT&T的语音API developer.att.com(收费)
以进行语音识别

Public Class Voice_recognition

    Public Function convertTotext(ByVal path As String, ByVal output As String) As String
        Dim request As HttpWebRequest = DirectCast(HttpWebRequest.Create("https://www.google.com/speech-api/v1/recognize?xjerr=1&client=speech2text&lang=en-US&maxresults=10"), HttpWebRequest)
        'path = Application.StartupPath & "curinputtmp.mp3"
        request.Timeout = 60000
        request.Method = "POST"
        request.KeepAlive = True
        request.ContentType = "audio/x-flac; rate=8000"  
        request.UserAgent = "speech2text"

        Dim fInfo As New FileInfo(path)
        Dim numBytes As Long = fInfo.Length
        Dim data As Byte()

        Using fStream As New FileStream(path, FileMode.Open, FileAccess.Read)
            data = New Byte(CInt(fStream.Length - 1)) {}
            fStream.Read(data, 0, CInt(fStream.Length))
            fStream.Close()
        End Using

        Using wrStream As Stream = request.GetRequestStream()
            wrStream.Write(data, 0, data.Length)
        End Using

        Try
            Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
            Dim resp = response.GetResponseStream()

            If resp IsNot Nothing Then
                Dim sr As New StreamReader(resp)
                MessageBox.Show(sr.ReadToEnd())

                resp.Close()
                resp.Dispose()
            End If
        Catch ex As System.Exception
            MessageBox.Show(ex.Message)
        End Try

        Return 0
    End Function
End Class

对于文本到语音:使用this

我认为,
如果不使用vb​​script到vb / C#转换器,您会理解的。
然后仍然没有与我联系。

我以前做过这个,现在找不到代码,这就是为什么我不直接给你代码的原因。



0
#! /usr/bin/python2
# -*- coding: utf-8 -*-

def run(cmd):
    import os
    import sys
    from subprocess import Popen, PIPE
    print(cmd)
    proc=Popen(cmd, stdin=None, stdout=PIPE, stderr=None, shell=True)
    while True:
        data = proc.stdout.readline()   # Alternatively proc.stdout.read(1024)
        if len(data) == 0:
            print("Finished process")
            break
        sys.stdout.write(data)

import urllib

msg='Hello preety world'
msg=urllib.quote_plus(msg)
# -v verbosity
cmd='curl '+ \
    '--output tts_responsivevoice.mp2 '+ \
    "\""+'https://code.responsivevoice.org/develop/getvoice.php?t='+msg+'&tl=en-US&sv=g2&vn=&pitch=0.5&rate=0.5&vol=1'+"\""+ \
    ' -H '+"\""+'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.0'+"\""+ \
    ' -H '+"\""+'Accept: audio/webm,audio/ogg,audio/wav,audio/*;q=0.9,application/ogg;q=0.7,video/*;q=0.6,*/*;q=0.5'+"\""+ \
    ' -H '+"\""+'Accept-Language: pl,en-US;q=0.7,en;q=0.3'+"\""+ \
    ' -H '+"\""+'Range: bytes=0-'+"\""+ \
    ' -H '+"\""+'Referer: http://code.responsivevoice.org/develop/examples/example2.html'+"\""+ \
    ' -H '+"\""+'Cookie: __cfduid=ac862i73b6a61bf50b66713fdb4d9f62c1454856476; _ga=GA1.2.2126195996.1454856480; _gat=1'+"\""+ \
    ' -H '+"\""+'Connection: keep-alive'+"\""+ \
    ''
print('***************************')
print(cmd)
print('***************************')
run(cmd)

线:

/getvoice.php?t='+msg+'&tl=en-US&sv=g2&vn=&pitch=0.5&rate=0.5&vol=1'+"\""+ \

对语言负责。

tl=en-US

还有另一个有趣的站点,可以使用tts引擎以这种方式使用。

用o代替iv0na.c0m

祝你今天愉快

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.