web-dev-qa-db-fra.com

API Google Text-To-Speech

Je souhaite savoir comment utiliser l'API Google Text-to-Speech dans mon projet .NET. Je pense que j'ai besoin d'appeler une URL pour utiliser le service Web, mais l'idée pour moi n'est pas claire. Quelqu'un peut-il aider?

70
user1296017

Ancienne réponse:

Essayez d’utiliser cette URL: http://translate.google.com/translate_tts?tl=en&q=Hello%20World Il générera automatiquement un fichier wav que vous pourrez facilement obtenir avec un HTTP demande via n'importe quelle programmation .net.

Modifier:

Ohh Google, vous pensiez pouvoir empêcher les gens d’utiliser votre merveilleux service avec une vérification en-tête http fragile.

Voici une solution pour obtenir une réponse dans plusieurs langues (j'essaierai d'en ajouter d'autres au fur et à mesure):

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

Curl

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

Notez que les en-têtes sont basés sur l'exemple de @Chris Cirefice. S'ils arrêtent de fonctionner, je tenterai de recréer les conditions pour que ce code fonctionne. Tous les crédits pour les en-têtes actuels vont à lui et au merveilleux outil qu'est WireShark. (merci également à Google de ne pas avoir corrigé cela)

60

Dans une mise à jour de réponse de Schahriar SaffarShargh , Google a récemment mis en place une fonctionnalité "d'abus de Google", rendant impossible l'envoi de tout ancien HTTP GET classique à une URL telle que:

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

qui a fonctionné très bien et dandy auparavant. Maintenant, suivre un tel lien vous présente un CAPTCHA. Cela affecte également les requêtes HTTP GET en dehors du navigateur (comme avec cURL), car l'utilisation de cette URL donne une redirection vers la page de protection contre les abus (CAPTCHA).

Pour commencer, vous devez ajouter le paramètre de requête client à l'URL de la requête:

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

Google Translate envoie &client=t, Vous devriez donc aussi.

Avant de faire cette requête HTTP, assurez-vous de définir l'en-tête Referer:

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

Evidemment, l'en-tête User-Agent Est également requis, mais curieusement, il peut être vide:

User-Agent:

Éditer : [~ # ~] note [~ # ~] - sur certains agents utilisateurs, tels que Android 4.X, le personnalisé ) L’en-tête User-Agent Est non envoyé, ce qui signifie que Google ne répond pas à la demande. Afin de résoudre ce problème, je règle simplement le paramètre User-Agent Sur un paramètre valide, tel que stagefright/1.2 (Linux;Android 5.0). Utilisez Wireshark pour déboguer les demandes (comme je le faisais) si les serveurs de Google ne répondent pas et assurez-vous que ces en-têtes sont correctement définis dans le GET! Google répondra avec un 503 Service Unavailable Si la demande échoue, suivie d'une redirection vers la page CAPTCHA.

Cette solution est un peu fragile. il est tout à fait possible que Google change la façon dont ils traitent ces demandes dans le futur. Je suggère donc de demander à Google de créer un real endpoint API (gratuit ou payant) que nous pourrons utiliser sans se sentir sale pour truquer les en-têtes HTTP.


Edit 2 : Pour ceux que cela intéresse, cette commande cURL devrait fonctionner parfaitement pour télécharger un mp3 de Hello en anglais:

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

Comme vous le remarquerez peut-être, j'ai défini les en-têtes Referer et User-Agent Dans la demande, ainsi que le paramètre client=t À la chaîne de requête. Vous pouvez utiliser https au lieu de http, à vous de choisir!


Edit 3 : Google a maintenant besoin d'un jeton pour chaque requête GET (notée par tk dans la chaîne de requête). Ci-dessous se trouve la commande révisée cURL qui téléchargera correctement un fichier mp3 TTS:

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

Notez le & tk = 995126.592330 dans la chaîne de requête; c'est le nouveau jeton. J'ai obtenu ce jeton en appuyant sur l'icône du haut-parleur sur translate.google.com Et en regardant la requête GET. J'ai simplement ajouté ce paramètre de chaîne de requête à la commande cURL précédente, et cela fonctionne.

[~ # ~] note [~ # ~]: évidemment cette solution est très fragile, et se casse à la caprice des architectes de Google qui introduisent de nouvelles choses comme les jetons requis pour les demandes. Ce jeton risque de ne pas fonctionner demain (bien que je vérifie et que je fasse rapport) ... le fait est qu'il n'est pas sage de compter sur cette méthode; au lieu de cela, il convient de se tourner vers une solution TTS commerciale, en particulier si vous utilisez TTS en production.

Pour plus d'explications sur la génération de jetons et sur ce que vous pourrez peut-être faire à ce sujet, voir réponse de Boude .


Si cette solution ne fonctionne plus dans le futur, laissez un commentaire sur cette réponse afin que nous puissions essayer de trouver une solution!

46
Chris Cirefice

Développer sur réponse de Chris . J'ai réussi à inverser le processus de génération de jeton.

Le jeton de la demande est basé sur le texte et sur une variable TKK globale définie dans le script de page. Ceux-ci sont hachés en JavaScript, ce qui donne le paramètre tk.

Quelque part dans le script de page, vous trouverez quelque chose comme ceci:

TKK='403413';

C'est le nombre d'heures écoulées depuis Epoch.

Le texte est pompé dans la fonction suivante (quelque peu désobfusquée):

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

J'ai réussi à porter ceci vers python dans mon fork de gTTS , donc je sais que cela fonctionne.

Edit: Le code de génération de jeton utilisé par gTTS a maintenant été déplacé dans gTTS-token .

Edit 2: Google a modifié l'API (quelque part autour du 10/05/2016), cette méthode nécessite quelques modifications. Je travaille actuellement sur ceci. Pendant ce temps, changer le client en tw-ob semble fonctionner.

Edit 3:

Les changements sont mineurs, mais ennuyeux pour le moins. Le TKK comprend maintenant deux parties. Vous cherchez quelque chose comme 406986.2817744745. Comme vous pouvez le constater, la première partie est restée la même. La deuxième partie est la somme de deux nombres apparemment aléatoires. TKK=eval('((function(){var a\x3d2680116022;var b\x3d137628723;return 406986+\x27.\x27+(a+b)})())'); Ici \x3d Signifie = Et \x27 Est '. A et b changent chaque minute UTC. Lors de l'une des dernières étapes de l'algorithme, le jeton est soumis à une analyse XOR par la deuxième partie.

Le nouveau code de génération de jeton est le suivant:

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

Bien sûr, je ne peux plus générer d'URL valide, car je ne sais pas comment a et b sont générés.

17
Boude

Une alternative supplémentaire est: responsivevoice.org un exemple simple: JsFiddle est Ici

[~ # ~] 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/ -->
    });

});

Ressource externe:

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

12
DMSJax

Google texte à la parole

<!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>
4
Panchal Deep

D'accord, Google a donc introduit des jetons (voir le paramètre tk dans la nouvelle URL) et l'ancienne solution ne semble pas fonctionner. J'ai trouvé une alternative - que je pense même qui sonne mieux et qui a plus de voix! La commande n'est pas jolie, mais ça marche. Veuillez noter que ceci est uniquement à des fins de test (je l'utilise pour un petit projet domotique) et utilisez la version réelle de acapella-group si vous envisagez de l'utiliser commercialement.

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

Certaines des voix prises en charge sont;

  • Sharon
  • Ella (voix d'enfant authentique)
  • EmilioEnglish (voix d'enfant authentique)
  • Josh (voix d'enfant authentique)
  • Karen
  • Kenny (voix artificielle d'enfant)
  • Laura
  • Micah
  • Nelly (voix artificielle d'enfant)
  • Barre
  • Ryan
  • Saul
  • Scott (voix d'adolescent authentique)
  • Tracy
  • ValeriaEnglish (voix d'enfant authentique)
  • Volonté
  • WillBadGuy (voix émotive)
  • WillFromAfar (voix émotive)
  • WillHappy (voix émotive)
  • WillLittleCreature (voix émotive)
  • WillOldMan (voix émotive)
  • WillSad (voix émotive)
  • WillUpClose (voix émotive)

Il prend également en charge plusieurs langues et plus de voix - pour cela je vous renvoie à leur site Web; http://www.acapela-group.com/

4
Rob Quist

Vous pouvez télécharger la voix avec Wget: D

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

Enregistrez la sortie dans un fichier mp3:

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

Prendre plaisir !!

4
Th3carpenter
4

Dès maintenant, le service de synthèse vocale officiel de Google est disponible à l'adresse https://cloud.google.com/text-to-speech/

C'est gratuit pour les 4 premiers millions de caractères.

2
Phakin
2
Thomas A. Markel

J'ai utilisé l'URL comme ci-dessus: http://translate.google.com/translate_tts?tl=fr&q=Hello%20World

Et demandé avec python bibliothèque..que je reçois HTTP 403 FORBIDDEN

Finalement, j'ai dû me moquer du User-Agent en-tête avec le celui du navigateur pour réussir.

1
ythdelmar

Parce que ça a été discuté ici, et que la première page de Google était celle-ci, j'ai décidé de laisser mes résultats sur Google. XD

vous n'avez vraiment plus besoin d'aller plus loin pour que cela fonctionne, restez simplement sur les épaules de géants:

il y a une norme

https://dvcs.w3.org/hg/speech-api/raw-file/tip/webspeechapi.html

et un exemple

http://html5-examples.craic.com/google_chrome_text_to_speech.html

au moins pour vos projets Web, cela devrait fonctionner (par exemple, asp.net)

1
Summer-Sky

Aller à console.developer.google.com vous connecter et obtenir une clé d’API ou utiliser l’API de Microsoft bing
https://msdn.Microsoft.com/en-us/library/?f=255&MSPPError=-2147217396

ou mieux, utilisez l’API vocale d’AT & T developer.att.com (payé)
Pour la reconnaissance vocale

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

Et pour le texte à la parole: tilisez ceci .

Je pense que tu comprendras ça
Si ne l’a pas fait, utilisez vbscript en convertisseur vb/C #.
ne m'a toujours pas contacté alors.

Je l'ai déjà fait, je ne trouve pas le code maintenant, c'est pourquoi je ne vous donne pas directement le code.

1
#! /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)

Ligne:

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

est responsable de la langue.

tl=en-US

Il existe un autre site intéressant avec des moteurs tts qui peut être utilisé de cette manière.

substitut o pour null iv0na.c0m

bonne journée

0
krzywynos