5

How to create mp3 from any text with Google TTS?

1) I try to find google.translate API, but finded only "audio to text", except "text to audio"!

2) I try to find SpeechSynthesis convert to mp3, but again find nothing!

3) I find only site "beta.soundoftext.com", they generate mp3 audio file without API interface.

So, can anyone help me, please. I searching for any ways to convert text to SPEECH for my web-site (Dedicated Server). Thank you!

inpost
  • 61
  • 1
  • 1
  • 4
  • for **(1)** try researching : ["**text to speech**" API](https://www.google.co.uk/search?ei=sesBWuKhOYfFkgWpy4nQCw&q=%22google%22+%22text+to+speech%22+api) instead of _"text to audio"_. Tell us here what you've tried **specifically with** using Google TTS (show code) and what error message you get... – VC.One Nov 07 '17 at 17:27

3 Answers3

3

I'm the creator of Sound of Text.

My site does have an API! (As of last week)

You can find the documentation for the API here: https://soundoftext.com/docs.

However, behind the scenes, I'm just using an npm library that automatically generates the Google Translate TTS link for me. Specifically, I'm using this library: https://www.npmjs.com/package/google-tts-api

I'm pretty sure every popular language has a library that does a similar thing, and I can help you find it if you tell me what language you prefer to use.

Or you can just use my API =)

florabtw
  • 193
  • 1
  • 8
0

A Python script have been created for it and the script is now available on Github.

All the input there are pretty straightforward, except for the language part where some language code might be less familiar by users, in these cases documentation from Google is available and you can check what's the code for the language you want the engine to speak in.

user930067
  • 276
  • 3
  • 10
0

Guy Rotem wrote a js function to get a tk token here. I adapted it for Java:

public class Hasher {
    public long shiftLeftOrRightThenSumOrXor(long num, String[] opArray) {
        long result = num;

        int current = 0;
        while (current < opArray.length)  {
            char op1 = opArray[current].charAt(1);  //  '+' | '-' ~ SUM | XOR
            char op2 = opArray[current].charAt(0);  //  '+' | '^' ~ SLL | SRL
            char xd = opArray[current].charAt(2);   //  [0-9a-f]

            assertError(op1 == '+'
                    || op1 == '-', "Invalid OP: " + op1);
            assertError(op2 == '+'
                    || op2 == '^', "Invalid OP: " + op2);
            assertError(('0' <= xd && xd <= '9')
                    || ('a' <= xd && xd <='f'), "Not an 0x? value: " + xd);

            int shiftAmount = hexCharAsNumber(xd);
            int mask = (op1 == '+') ? ((int) result) >>> shiftAmount : ((int) result) << shiftAmount;

            long subresult = (op2 == '+') ? (((int) result) + ((int) mask) & 0xffffffff)
                    : (((int) result) ^ mask);
            result = subresult;
            current++;
        }

        return result;
    }

    public void assertError(boolean cond, String e) {
        if (!cond) {
            System.err.println();
        }
    }

    public int hexCharAsNumber(char xd) {
        return (xd >= 'a') ? xd - 87 : Character.getNumericValue(xd);
    }

    public int[] transformQuery(String query) {
        int[] e = new int[1000];
        int resultSize = 1000;

        for (int f = 0, g = 0; g < query.length(); g++) {
            int l = query.charAt(g);
            if (l < 128) {
                e[f++] = l;                 //  0{l[6-0]}
            } else if (l < 2048) {
                e[f++] = l >> 6 | 0xC0;     //  110{l[10-6]}
                e[f++] = l & 0x3F | 0x80;   //  10{l[5-0]}
            } else if (0xD800 == (l & 0xFC00) &&
                    g + 1 < query.length() && 0xDC00 == (query.charAt(g + 1) & 0xFC00)) {
                //  that's pretty rare... (avoid ovf?)
                l = (1 << 16) + ((l & 0x03FF) << 10) + (query.charAt(++g) & 0x03FF);
                e[f++] = l >> 18 | 0xF0;        //  111100{l[9-8*]}
                e[f++] = l >> 12 & 0x3F | 0x80; //  10{l[7*-2]}
                e[f++] = l & 0x3F | 0x80;       //  10{(l+1)[5-0]}
            } else {
                e[f++] = l >> 12 | 0xE0;        //  1110{l[15-12]}
                e[f++] = l >> 6 & 0x3F | 0x80;  //  10{l[11-6]}
                e[f++] = l & 0x3F | 0x80;       //  10{l[5-0]}
            }

            resultSize = f;
        }

        return Arrays.copyOf(e, resultSize);
    }

    public long normalizeHash(long encondindRound2) {
        if (encondindRound2 < 0) {
            encondindRound2 = (encondindRound2 & 0x7fffffff) + 0x80000000L;
        }
        return (encondindRound2) % 1_000_000;
    }

    /*
    /   EXAMPLE:
    /
    /   INPUT: query: 'hola', windowTkk: '409837.2120040981'
    /   OUTPUT: '70528.480109'
    /
    */
    public String calcHash(String query, String windowTkk) {
        //  STEP 1: spread the the query char codes on a byte-array, 1-3 bytes per char
        int[] bytesArray = transformQuery(query);

        //  STEP 2: starting with TKK index,
        // add the array from last step one-by-one, and do 2 rounds of shift+add/xor
        String[] d = windowTkk.split("\\.");
        int tkkIndex = 0;
        try  {
            tkkIndex = Integer.valueOf(d[0]);
        }
        catch (Exception e)  {
            e.printStackTrace();
        }

        long tkkKey = 0;
        try  {
            tkkKey = Long.valueOf(d[1]);
        }
        catch (Exception e)  {
            e.printStackTrace();
        }

        int current = 0;
        long result = tkkIndex;
        while (current < bytesArray.length)  {
            result += bytesArray[current];
            long subresult = shiftLeftOrRightThenSumOrXor(result,
                    new String[] {"+-a", "^+6"});
            result = subresult;
            current++;
        }
        long encondingRound1 = result;
        //System.out.println("encodingRound1: " + encondingRound1);

        //  STEP 3: apply 3 rounds of shift+add/xor and XOR with they TKK key
        long encondingRound2 = ((int) shiftLeftOrRightThenSumOrXor(encondingRound1,
                new String[] {"+-3", "^+b", "+-f"})) ^ ((int) tkkKey);
        //System.out.println("encodingRound2: " + encondingRound2);

        //  STEP 4: Normalize to 2s complement & format
        long normalizedResult = normalizeHash(encondingRound2);
        //System.out.println("normalizedResult: " +  normalizedResult);

        return String.valueOf(normalizedResult) + "."
                + (((int) normalizedResult) ^ (tkkIndex));
    }
}

Once you have tk you need to just send a HTTP request like this (using okhttp library for sending requests):

HttpUrl.Builder urlBuilder = HttpUrl.parse("https://translate.google.com/translate_tts").newBuilder();
urlBuilder.addQueryParameter("ie", "UTF-8");
urlBuilder.addQueryParameter("q", foreignWord);
urlBuilder.addQueryParameter("tl", "de");
urlBuilder.addQueryParameter("total", "1");
urlBuilder.addQueryParameter("idx", "0");
urlBuilder.addQueryParameter("textlen",
        String.valueOf(foreignWord.length()));
urlBuilder.addQueryParameter("tk", hasher.getTk(foreignWord));
urlBuilder.addQueryParameter("client", "webapp");
urlBuilder.addQueryParameter("prev", "input");

String url = urlBuilder.build().toString();
Request request = new Request.Builder()
        .url(url)
        .addHeader("User-Agent", "Mozilla/5.0...")
        .addHeader("Accept-Language", Locale.US.getLanguage())
        .addHeader("Referer", "https://translate.google.com/")
        .get()
        .build();

OkHttpClient client = new OkHttpClient();
Call call = client.newCall(request);
Response response = call.execute();
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = new FileOutputStream(path + "/audio/" + foreignWord + ".mpga");
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(dataBuffer, 0, 1024)) != -1) {
    fileOutputStream.write(dataBuffer, 0, bytesRead);
}

It saves the file as .mpga, because that's what google returns. You can then use some other libraries to convert .mpga to .mp3.

parsecer
  • 4,758
  • 13
  • 71
  • 140